Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (Revision 58857) +++ Python/pythonrun.c (Arbeitskopie) @@ -75,6 +75,7 @@ int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ int Py_InspectFlag; /* Needed to determine whether to exit at SystemError */ int Py_NoSiteFlag; /* Suppress 'import site' */ +int Py_StrBytesWarningFlag; /* Warn on str(bytes) and str(buffer) */ int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */ int Py_FrozenFlag; /* Needed by getpath.c */ int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */ Index: Include/pydebug.h =================================================================== --- Include/pydebug.h (Revision 58857) +++ Include/pydebug.h (Arbeitskopie) @@ -11,6 +11,7 @@ PyAPI_DATA(int) Py_InspectFlag; PyAPI_DATA(int) Py_OptimizeFlag; PyAPI_DATA(int) Py_NoSiteFlag; +PyAPI_DATA(int) Py_StrBytesWarningFlag; PyAPI_DATA(int) Py_UseClassExceptionsFlag; PyAPI_DATA(int) Py_FrozenFlag; PyAPI_DATA(int) Py_TabcheckFlag; Index: Objects/bytesobject.c =================================================================== --- Objects/bytesobject.c (Revision 58857) +++ Objects/bytesobject.c (Arbeitskopie) @@ -923,6 +923,23 @@ } static PyObject * +bytes_str(PyObject *op) +{ + if (Py_StrBytesWarningFlag == 1) { + if (PyErr_WarnEx(PyExc_Warning, + "Calling str() on a bytes instance.", + 1)) + return NULL; + } + if (Py_StrBytesWarningFlag > 1) { + PyErr_SetString(PyExc_TypeError, + "Calling str() on a bytes instance."); + return NULL; + } + return bytes_repr((PyBytesObject*)op); +} + +static PyObject * bytes_richcompare(PyObject *self, PyObject *other, int op) { Py_ssize_t self_size, other_size; @@ -3063,7 +3080,7 @@ &bytes_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ - (reprfunc)bytes_repr, /* tp_str */ + bytes_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &bytes_as_buffer, /* tp_as_buffer */ Index: Objects/stringobject.c =================================================================== --- Objects/stringobject.c (Revision 58857) +++ Objects/stringobject.c (Arbeitskopie) @@ -679,6 +679,23 @@ return PyString_Repr(op, 1); } +static PyObject * +string_str(PyObject *op) +{ + if (Py_StrBytesWarningFlag == 1) { + if (PyErr_WarnEx(PyExc_Warning, + "Calling str() on a bytes instance.", + 1)) + return NULL; + } + if (Py_StrBytesWarningFlag > 1) { + PyErr_SetString(PyExc_TypeError, + "Calling str() on a bytes instance."); + return NULL; + } + return string_repr(op); +} + static Py_ssize_t string_length(PyStringObject *a) { @@ -3090,13 +3107,13 @@ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ - string_repr, /* tp_repr */ + (reprfunc)string_repr, /* tp_repr */ 0, /* tp_as_number */ &string_as_sequence, /* tp_as_sequence */ &string_as_mapping, /* tp_as_mapping */ (hashfunc)string_hash, /* tp_hash */ 0, /* tp_call */ - string_repr, /* tp_str */ + string_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &string_as_buffer, /* tp_as_buffer */ Index: Modules/main.c =================================================================== --- Modules/main.c (Revision 58857) +++ Modules/main.c (Arbeitskopie) @@ -44,7 +44,7 @@ static int orig_argc; /* command line options */ -#define BASE_OPTS "c:dEhim:OStuvVW:xX?" +#define BASE_OPTS "bc:dEhim:OStuvVW:xX?" #define PROGRAM_OPTS BASE_OPTS @@ -55,32 +55,34 @@ /* Long usage message, split into parts < 512 bytes */ static char *usage_1 = "\ Options and arguments (and corresponding environment variables):\n\ +-b : issue warnings about str(bytes_instance) and str(buffer_instance)\n\ + (-bb: issue errors)\n\ -c cmd : program passed in as string (terminates option list)\n\ -d : debug output from parser; also PYTHONDEBUG=x\n\ -E : ignore environment variables (such as PYTHONPATH)\n\ -h : print this help message and exit (also --help)\n\ +"; +static char *usage_2 = "\ -i : inspect interactively after running script; forces a prompt even\n\ if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\ -"; -static char *usage_2 = "\ -m mod : run library module as a script (terminates option list)\n\ -O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\ -OO : remove doc-strings in addition to the -O optimizations\n\ -S : don't imply 'import site' on initialization\n\ -t : issue warnings about inconsistent tab usage (-tt: issue errors)\n\ --u : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x\n\ "; static char *usage_3 = "\ +-u : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x\n\ see man page for details on internal buffering relating to '-u'\n\ -v : verbose (trace import statements); also PYTHONVERBOSE=x\n\ can be supplied multiple times to increase verbosity\n\ -V : print the Python version number and exit (also --version)\n\ -W arg : warning control; arg is action:message:category:module:lineno\n\ -x : skip first line of source, allowing use of non-Unix forms of #!cmd\n\ +"; +static char *usage_4 = "\ file : program read from script file\n\ - : program read from stdin (default; interactive mode if a tty)\n\ -"; -static char *usage_4 = "\ arg ...: arguments passed to program in sys.argv[1:]\n\n\ Other environment variables:\n\ PYTHONSTARTUP: file executed on interactive startup (no default)\n\ @@ -252,6 +254,9 @@ } switch (c) { + case 'b': + Py_StrBytesWarningFlag++; + break; case 'd': Py_DebugFlag++;