Here's the result of my workon the matter, in two parts: (1) a
modified version of the naming conventions proposal; (2) a list giving
new names for almost all "global" (in some sense) names in the current
interpreter. This is not cast in concrete, so don't use this yet, but
read it through if you have time, and let me know where the weak spots
are.
--Guido
========================================================================
[Change bars indicate changes with respect to the first draft.]
| Naming Conventions -- Second Draft Proposal
| *******************************************
It is quite easy to extend Python with a new module written in C. It
should be equally easy to embed the Python interpreter as a library in
an existing (or new) application. This is indeed possible, but there
is a potential problem when the application is large: the Python
interpreter library defines many external names that may clash with
names defined by the application. To a lesser extend the macros,
| structures and typedefs defined in Python's public header files may
also clash with application-defined names (or with names defined by
other libraries, when the application needs to use several libraries
in one file).
This article proposes a change to the naming of all external
functions, macros, structures, typedefs etc. that are in any way
visible to the application with the intent to make clashes avoidable.
(This excludes the names of static functions and variables, local
variables, structure members, and macros, structures and typedefs
| defined in .c files or .h files for internal use only.) At the same
time the set of names is somewhat rationalized to make it easier to
guess where a name is defined.
The purpose of this proposal is to get feedback. This is your chance
to make your voice heard! Please evaluate every aspect of the
proposal and let me know whether you like it or not. No effort has
yet begun to implement the proposal, so there are no big costs
involved in changes to the proposal. Your opinion is especially
important if you have written (or are maintaining) code that extends
the Python interpreter, since you will have to change your code and
learn to use the new conventions.
| This is the second draft; the next version will be implemented,
| so this is your last chance to make your voice heard.
Note that these changes affect the C code that implements the Python
interpreter (and its extensions) only; the Python language as seen by
Python programmers will remain unchanged!
Basic Conventions
=================
The mechanism to avoid clashes is to prefix all relevant names with
the string Py. This gives an application a very simple way to avoid
clashes: simply don't define names starting with Py in the
application. A similar mechanism is successfully used by most
widespread libraries, e.g. X.
The full naming scheme gives functions a name as follows:
| [_]Py<Module>_<Function>, where <Module> is the (sometimes abbreviated)
name of the module to which the function belongs (this may also be a
basic type), and <Function> is a descriptive name for the function.
| [_] stands for an optional underscore (for internal functions).
The <Module> and <Function> parts use a mixed-case convention: each
is spelled with an initial capital letter, and if they consist of
multiple words each word has an initial capital. Embedded underscores
are not used except between <Module> and <Function>. Some examples:
| PyObject_Print
PyList_Append
PyList_GetItem
| PyList_Alloc
| PyString_AsString
PyErr_SetString
| Some utility functions have a prefix of just Py_, e.g.
|
| Py_FatalError
Py_MakeValue
Global variables are named using similar conventions, e.g.
PyList_Type
PyExc_ZeroDivisionError
| Names that have to be global for some reason but are
not part of the official interface have an initial underscore, e.g.
_Py_RefTotal
| _PyObject_New
| Macros that behave like functions are named like functions, e.g.:
| PyList_Valid
| _Py_NewReference
| Macros used as symbolic constants and enum values have a second part that
is entirely in capitals and uses underscores to separate words. So
do enums. E.g.:
Py_PRINT_RAW
| Macros that are not completely like functions (e.g. have a
| typedef as argument or may evaluate one or more arguments several
| times, or unsafe inline versions) also follow this convention, e.g.:
|
| Py_INCREF
| PyFloat_AS_DOUBLE
Typedefs contain no underscore; they consist of Py followed by one or
more words with initial capitals, e.g.:
PyObject
PyListObject
| PyNumberMethods
Most of these typedef names correspond to structures; the structure
tag will be the typedef name prefixed with an underdscore.
Note that the current system has a number of structures that are not
covered by typedefs. These will be given typedef names.
| For example:
|
| PyMemberDef
| PyMethodDef
Also note that pointer types will continue to be written with the "*"
notation, e.g. "PyObject *". Pointers in C have sufficiently special
semantics to make it important in practice to know whether a
particular variable is a pointer; e.g. Python frequently uses casts
between various object pointers.
| Typedefs do not end in "_t". I find this ugly and unnecessary.
| For now, header file names will remain unchanged. In the future,
| header files may be renamed to <Py/List.h> etc., with <Py/Python.h>
| a convenience header like the current "allobjects.h". (There was
| considerable diversity in the suggestions for a new directory
| structure, so for now I'll leave it unchanged until I have thought
| about it more.)
| Header files will be protected against multiple inclusion with a
| macro and an #ifdef, as follows:
|
| #ifndef PyFOO_H
| #define PyFOO_H
| .
| . (entire contents of file goes here)
| .
| #endif /* PyFOO_H */
Transition Period
=================
During a transition period, which will last at least two releases that
each live at least 3 months (giving a total of at least 6 months), it
will be possible to use the old names and the new names together.
The transition mechanism uses #define to identify the new and old names.
In the first transition release, the (majority of) source code will
still use the old names, including the old header file names, but
macros will be defined to support the use of the new names, e.g.:
#define PyObject object
In the second transition release, the source code will use the new
names, also for header file names, and macros will be defined to
support code that still uses the old names, e.g.:
#define object PyObject
| Header file names may be changed in the second transition release
| (if I can agree with myself on a good naming scheme).
In both transition releases, the compatibility macros will be gathered
in a single header file (a different one each time!).
A Python script will be provided which translates C code from the old
to the new naming conventions with 99% accuracy. It remains to be
seen whether occurrences in comments should be replaced; when comments
refer to functions and typedefs etc., they should, but some names
(e.g. object!) can also be used as a noun, so global substitutions may
cause undesired effects. Also, there are some situations where names
occurring in strings must be substituted!
| (the sections on other changes and an alternate proposal have been
| deleted)
========================================================================
# This file contains an almost complete list of identifiers that will
# change at the Great Renaming. The rules are explained in the file
# NAMING; this file just contains a list of mappings. With few
# exceptions, this file can be used as input for a renaming script that
# I have devised (which assumes its input lines contain pairs of old
# name and new name after comment stripping). Note that names which
# are global by mistake in the current are not listed here; they will
# be made static (manually). There may also be some names here that
# are not defined in the 0.9.8 release; these have been introduced in
# the code after that release. I've attempted to remove most of these
# but sometimes I may not have remembered their status correctly...
# ====== CPP symbols used to switch on ======
NDEBUG Py_NO_DEBUG
TRACE_REFS Py_TRACE_REFS
REF_DEBUG Py_REF_DEBUG
USE_... Py_USE_...
HAVE_PROTOTYPES Py_HAVE_PROTOTYPES
HAVE_STDLIB Py_HAVE_STDLIB
# Each .h file "foo.h" will be protected by a macro and ifdef as follows:
# #ifndef PyFOO_H
# #define PyFOO_H
# .
# . (entire contents of file goes here)
# .
# #endif /* PyFOO_H */
# ====== Data ======
# --- Misc global data ---
FalseObject _Py_ZeroStruct
NoObject _Py_NoneStruct
TrueObject _Py_TrueStruct
debugging Py_DebugFlag
gram _PyParser_Grammar
sys_profile _PySys_ProfileFunc
sys_trace _PySys_TraceFunc
threads_started _PyThread_Started
tok_name _PyParser_TokenNames
verbose Py_VerboseFlag
# --- Built-in exceptions ---
AttributeError PyExc_AttributeError
EOFError PyExc_EOFError
IOError PyExc_IOError
ImportError PyExc_ImportError
IndexError PyExc_IndexError
KeyError PyExc_KeyError
MemoryError PyExc_MemoryError
NameError PyExc_NameError
OverflowError PyExc_OverflowError
RuntimeError PyExc_RuntimeError
SyntaxError PyExc_SyntaxError
SystemError PyExc_SystemError
TypeError PyExc_TypeError
ValueError PyExc_ValueError
ZeroDivisionError PyExc_ZeroDivisionError
KeyboardInterrupt PyExc_KeyboardInterrupt
SystemExit PyExc_SystemExit
# --- Built-in type objects --- (only used through is_<type>object() macros)
# Atomic basic types
Floattype PyFloat_Type
Inttype PyInt_Type
Longtype PyLong_Type
Notype PyNothing_Type
Stringtype PyString_Type # Also composite (sequence)
Typetype PyType_Type
# Composite basic types
Listtype PyList_Type
Dicttype PyDict_Type
Tupletype PyTuple_Type
# I/O types
Filetype PyFile_Type
# Interpreter related types
Classtype PyClass_Type
Functype PyFunction_Type
Instancemethodtype PyMethod_Type
Instancetype PyInstance_Type
Methodtype PyCFunction_Type # Split in CMethod, CFunction?
Moduletype PyModule_Type
# Interpreter internal types
Codetype PyCode_Type
Frametype PyFrame_Type
# ====== Typedefs ======
*object PyObject
#varobject no longer visible for users
floatobject PyFloatObject
intobject PyIntObject
longobject PyLongObject
noobject PyNothingObject
stringobject PyStringObject
typeobject PyTypeObject
listobject PyListObject
dictobject PyDictObject
tupleobject PyTupleObject
fileobject PyFileObject
classobject PyClassObject
codeobject PyCodeObject
frameobject PyFrameObject
funcobject PyFunctionObject
instancemethodobject PyMethodObject
instanceobject PyInstanceObject
methodobject PyCFunctionObject # Split in CMethod, CFunction?
moduleobject PyModuleObject
number_methods PyNumberMethods
sequence_methods PySequenceMethods
mapping_methods PyMappingMethods
# ====== Funny CPP macros ======
OB_HEAD PyObject_HEAD
OB_VARHEAD PyObject_VAR_HEAD
OB_HEAD_INIT PyObject_HEAD_INIT
NEWOBJ PyObject_NEW
NEWVAROBJ PyObject_NEW_VAR
PROTO Py_PROTO
PROTO Py_FPROTO
# For ANY* I break my own rule of not defining names for pointer
# types, since here it is essential that the pointer not be
# dereferenced!
# (My script doesn't understand this, I'll fix it manually)
ANY* PyUnivPtr # either char* or void*
NEW PyMem_NEW
RESIZE PyMem_RESIZE
DEL PyMem_DEL
XDEL PyMem_XDEL
MALLARG size_t # this macro is no longer needed
BGN_SAVE Py_BEGIN_ALLOW_THREADS
RET_SAVE Py_BLOCK_THREADS
RES_SAVE Py_UNBLOCK_THREADS
END_SAVE Py_END_ALLOW_THREADS
# ====== Enumerated Values ======
# E_OK, etc.: unchanged (used internally only)
# T_INT, etc.: for now, these remain the same; in the future
# structmember.h will be replaced by a more powerful (extensible)
# module where types are expressed by strings.
# ====== Structure tags ======
# Avoid completely (use forward typedefs instead)
# (My script can't handle those, wil lfix manually)
#struct memberlist PyMemberDef
#struct methodlist PyMethodDef
#(etc.)
# ====== Type tests ======
is_floatobject PyFloat_Check
is_intobject PyInt_Check
is_longobject PyLong_Check
is_noobject PyNothing_Check
is_stringobject PyString_Check
is_typeobject PyType_Check
is_listobject PyList_Check
is_dictobject PyDict_Check
is_tupleobject PyTuple_Check
is_fileobject PyFile_Check
is_classobject PyClass_Check
is_codeobject PyCode_Check
is_frameobject PyFrame_Check
is_funcobject PyFunction_Check
is_instancemethodobject PyMethod_Check
is_instanceobject PyInstance_Check
is_methodobject PyCFunction_Check # Split in CMethod, CFunction?
is_moduleobject PyModule_Check
# Operations on built-in types
# --- Generic Object Operations ---
INCREF Py_INCREF # uses arg multiple times
DECREF Py_DECREF # " " " "
XINCREF Py_XINCREF
XDECREF Py_XDECREF
NEWREF _Py_NewReference
DELREF _Py_Dealloc
UNREF _Py_ForgetReference
None Py_None
False Py_False
True Py_True
cmpobject PyObject_Compare
getattr PyObject_GetAttrString
getattro PyObject_GetAttr
hashobject PyObject_Hash
newobject _PyObject_New
newvarobject _PyObject_NewVar
printobject PyObject_Print
reprobject PyObject_Repr
setattr PyObject_SetAttrString
setattro PyObject_SetAttr
testbool PyObject_IsTrue
# --- flags for PyObject_Print ---
PRINT_RAW Py_PRINT_RAW
# --- Atomic basic objects ---
float_buf_repr PyFloat_AsString # need to reverse arguments
getfloatvalue PyFloat_AsDouble
GETFLOATVALUE PyFloat_AS_DOUBLE
newfloatobject PyFloat_FromDouble
getintvalue PyInt_AsLong
GETINTVALUE PyInt_AS_LONG
newintobject PyInt_FromLong
alloclongobject _PyLong_New # used by marshal, mpz
dgetlongvalue PyLong_AsDouble
dnewlongobject PyLong_FromDouble
getlongvalue PyLong_AsLong
long_scan PyLong_FromString
newlongobject PyLong_FromLong
formatstring PyString_Format
getstringsize PyString_Size
getstringvalue PyString_AsString
GETSTRINGVALUE PyString_AS_STRING
joinstring PyString_Concat
newsizedstringobject PyString_FromStringAndSize
newstringobject PyString_FromString
resizestring _PyString_Resize
# --- Composite basic objects ---
addlistitem PyList_Append
getlistitem PyList_GetItem
GETLISTITEM PyList_GET_ITEM
getlistsize PyList_Size
getlistslice PyList_GetSlice
inslistitem PyList_Insert
newlistobject PyList_New
setlistitem PyList_SetItem
setlistslice PyList_SetSlice
sortlist PyList_Sort
# These are different from the 0.9.8 distribution! Hope you get the gist.
dictinsert PyDict_SetItemString
dictlookup PyDict_GetItemString
dictremove PyDict_DelItemString
getmappingitems PyDict_Items
getmappingkeys PyDict_Keys
getmappingvalues PyDict_Values
mappingclear PyDict_Clear
mappinggetnext PyDict_Next
mappinginsert PyDict_SetItem
mappinglookup PyDict_GetItem
mappingremove PyDict_DelItem
newmappingobject PyDict_New
gettupleitem PyTuple_GetItem
GETTUPLEITEM PyTuple_GET_ITEM
gettuplesize PyTuple_Size
gettupleslice PyTuple_GetSlice
newtupleobject PyTuple_New
settupleitem PyTuple_SetItem
# --- I/O Objects ---
filegetline PyFile_GetLine
getfilefile PyFile_AsFile
newfileobject PyFile_FromString
newopenfileobject PyFile_FromFile
softspace PyFile_SoftSpace
writeobject PyFile_WriteObject
writestring PyFile_WriteString
# --- Interpreter Related Objects ---
# These are really all internal
instancemethodgetclass PyMethod_Class
instancemethodgetfunc PyMethod_Function
instancemethodgetself PyMethod_Self
issubclass PyClass_IsSubclass
newclassobject PyClass_New
newinstancemethodobject PyMethod_New
newinstanceobject PyInstance_New
block PyTryBlock
extend_stack PyFrame_ExtendStack
newframeobject PyFrame_New
pop_block PyFrame_BlockPop
setup_block PyFrame_BlockSetup
getfunccode PyFunction_GetCode
getfuncglobals PyFunction_GetGlobals
newfuncobject PyFunction_New
method PyCFunction
findmethod Py_FindMethod # Will be replaced by another mechanism
getmethod PyCFunction_GetFunction
getself PyCFunction_GetSelf
getvarargs PyCFunction_IsVarArgs
newmethodobject PyCFunction_New
getmoduledict PyModule_GetDict
getmodulename PyModule_GetName
newmoduleobject PyModule_New
# ====== Text ======
# --- Parser and tokenizer --- (knows about tokens and grammar)
addaccelerators PyGrammar_AddAccelerators
finddfa PyGrammar_FindDFA
labelrepr PyGrammar_LabelRepr
listtree PyNode_ListTree
addchild PyNode_AddChild
freetree PyNode_Free
newtree PyNode_New
addtoken PyParser_AddToken
delparser PyParser_Delete
newparser PyParser_New
parsefile PyParser_ParseFile
parsestring PyParser_ParseString
tok_1char PyToken_OneChar
tok_2char PyToken_TwoChars
tok_free PyTokenizer_Free
tok_get PyTokenizer_Get
tok_setupf PyTokenizer_FromFile
tok_setups PyTokenizer_FromString
# --- Compiler --- (knows about grammar and objects and opcodes)
compile PyNode_Compile
newcodeobject PyCode_New
# --- Interpreter --- (knows about objects and opcodes)
call_object PyEval_CallObject
eval_code PyEval_EvalCode
flushline Py_FlushLine
getglobals PyEval_GetGlobals
getlocals PyEval_GetLocals
init_save_thread PyEval_InitThreads
printtraceback PyErr_PrintTraceBack
restore_thread PyEval_RestoreThread
save_thread PyEval_SaveThread
# --- Interpreter support ---
tb_fetch PyTraceBack_Fetch
tb_here PyTraceBack_Here
tb_print PyTraceBack_Print
tb_store PyTraceBack_Store
add_module PyImport_AddModule
doneimport PyImport_Cleanup
get_modules PyImport_GetModuleDict
import_module PyImport_ImportModule
init_frozen PyImport_ImportFrozenModule
initimport PyImport_Init
reload_module PyImport_ReloadModule
coerce PyNumber_Coerce
getbuiltin PyBuiltin_GetObject
initbuiltin PyBuiltin_Init
initmarshal PyMarshal_Init
rd_long PyMarshal_ReadLongFromFile
rd_object PyMarshal_ReadObjectFromFile
rds_object PyMarshal_ReadObjectFromString
wr_long PyMarshal_WriteLongToFile
wr_object PyMarshal_WriteObjectToFile
initsys PySys_Init
setpythonargv PySys_SetArgv
setpythonpath PySys_SetPath
sysget PySys_GetObject
sysgetfile PySys_GetFile
sysset PySys_SetObject
# --- Embedding support ---
compile_string Py_CompileString
fatal Py_FatalError
goaway Py_Exit
initall Py_Initialize
print_error PyErr_Print
parse_file PyParser_SimpleParseFile
parse_string PyParser_SimpleParseString
run PyRun_AnyFile
run_script PyRun_SimpleFile
run_command PyRun_SimpleString
run_file PyRun_File
run_string PyRun_String
run_tty_1 PyRun_InteractiveOne
run_tty_loop PyRun_InteractiveLoop
# --- Extension support ---
getmember PyMember_Get
setmember PyMember_Set
initmodule Py_InitModule
mkvalue Py_BuildValue
vmkvalue Py_VaBuildValue
# --- Get arguments ---
getargs PyArg_Parse
# getlonglistarg # unused -- will disappear
# getlongtuplearg # unused -- will disappear
# getshortlistarg # unused -- will disappear
# getshorttuplearg # unused -- will disappear
# --- Special set used by code generated by cgen.py (i.e. glmodule.c) ---
getichararg PyArg_GetChar
getidoublearray PyArg_GetDoubleArray
getifloatarg PyArg_GetFloat
getifloatarray PyArg_GetFloatArray
getilongarg PyArg_GetLong
getilongarray PyArg_GetLongArray
getilongarraysize PyArg_GetLongArraySize
getiobjectarg PyArg_GetObject
getishortarg PyArg_GetShort
getishortarray PyArg_GetShortArray
getishortarraysize PyArg_GetShortArraySize
getistringarg PyArg_GetString
# mknewcharobject (replaced by mkvalue("c", ...))
# --- Error handling ---
# (The 'Set' versions have an argument giving the exception type,
# the others don't)
err_badarg PyErr_BadArgument
err_badcall PyErr_BadInternalCall
err_input PyErr_Input
err_nomem PyErr_NoMemory
err_errno PyErr_SetFromErrno
err_set PyErr_SetNone
err_setstr PyErr_SetString
err_setval PyErr_SetObject
err_occurred PyErr_Occurred
err_get PyErr_GetAndClear
err_clear PyErr_Clear
# --- Operating system dependent code ---
fgets_intr PyOS_InterruptableGetString
initintr PyOS_InitInterrupts
intrcheck PyOS_InterruptOccurred
getmtime PyOS_GetLastModificationTime
--Guido van Rossum, CWI, Amsterdam <Guido.van.Rossum@cwi.nl>