view Python/future.c @ 43410:b06b191b7cfa

Merged revisions 58203-58210 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r58204 | georg.brandl | 2007-09-19 08:37:19 +0200 (Wed, 19 Sep 2007) | 2 lines Fix #1169: remove docstrings in functions for -OO. ........ r58206 | sean.reifschneider | 2007-09-19 09:52:56 +0200 (Wed, 19 Sep 2007) | 2 lines issue1177: Ported Facundo's from urllib2 to urllib, accepting 2xx responses. ........ r58207 | facundo.batista | 2007-09-19 16:02:03 +0200 (Wed, 19 Sep 2007) | 3 lines Annotated the correction to urllib.py, issue #1177 ........ r58208 | facundo.batista | 2007-09-19 17:10:06 +0200 (Wed, 19 Sep 2007) | 7 lines Issue #1772851. Alters long.__hash__ from being *almost* completely predictable to being completely predictable. The value of hash(n) is unchanged for any n that's small enough to be representable as an int, and also unchanged for the vast majority of long integers n of reasonable size. ........ r58209 | thomas.wouters | 2007-09-19 19:27:29 +0200 (Wed, 19 Sep 2007) | 4 lines Fix obvious typo in threaded test. ........ r58210 | thomas.wouters | 2007-09-19 19:27:43 +0200 (Wed, 19 Sep 2007) | 4 lines Whitespace cleanup. ........
author Thomas Wouters <thomas@python.org>
date Wed, 19 Sep 2007 21:19:28 +0000
parents 302aeee32da8
children 305d7d2ce047
line wrap: on
line source

#include "Python.h"
#include "Python-ast.h"
#include "node.h"
#include "token.h"
#include "graminit.h"
#include "code.h"
#include "compile.h"
#include "symtable.h"

#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"

static int
future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
{
	int i;
	asdl_seq *names;

	assert(s->kind == ImportFrom_kind);

	names = s->v.ImportFrom.names;
	for (i = 0; i < asdl_seq_LEN(names); i++) {
                alias_ty name = (alias_ty)asdl_seq_GET(names, i);
		const char *feature = PyUnicode_AsString(name->name);
		if (!feature)
			return 0;
		if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
			continue;
		} else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
			continue;
		} else if (strcmp(feature, FUTURE_DIVISION) == 0) {
			continue;
		} else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
			continue;
		} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
			continue;
		} else if (strcmp(feature, "braces") == 0) {
			PyErr_SetString(PyExc_SyntaxError,
					"not a chance");
			PyErr_SyntaxLocation(filename, s->lineno);
			return 0;
		} else {
			PyErr_Format(PyExc_SyntaxError,
				     UNDEFINED_FUTURE_FEATURE, feature);
			PyErr_SyntaxLocation(filename, s->lineno);
			return 0;
		}
	}
	return 1;
}

static int
future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
{
	int i, found_docstring = 0, done = 0, prev_line = 0;

	static PyObject *future;
	if (!future) {
		future = PyUnicode_InternFromString("__future__");
		if (!future)
			return 0;
	}

	if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
		return 1;

	/* A subsequent pass will detect future imports that don't
	   appear at the beginning of the file.  There's one case,
	   however, that is easier to handl here: A series of imports
	   joined by semi-colons, where the first import is a future
	   statement but some subsequent import has the future form
	   but is preceded by a regular import.
	*/
	   

	for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
		stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);

		if (done && s->lineno > prev_line)
			return 1;
		prev_line = s->lineno;

		/* The tests below will return from this function unless it is
		   still possible to find a future statement.  The only things
		   that can precede a future statement are another future
		   statement and a doc string.
		*/

		if (s->kind == ImportFrom_kind) {
			if (s->v.ImportFrom.module == future) {
				if (done) {
					PyErr_SetString(PyExc_SyntaxError,
							ERR_LATE_FUTURE);
					PyErr_SyntaxLocation(filename, 
							     s->lineno);
					return 0;
				}
				if (!future_check_features(ff, s, filename))
					return 0;
				ff->ff_lineno = s->lineno;
			}
			else
				done = 1;
		}
		else if (s->kind == Expr_kind && !found_docstring) {
			expr_ty e = s->v.Expr.value;
			if (e->kind != Str_kind)
				done = 1;
			else
				found_docstring = 1;
		}
		else
			done = 1;
	}
	return 1;
}


PyFutureFeatures *
PyFuture_FromAST(mod_ty mod, const char *filename)
{
	PyFutureFeatures *ff;

	ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
	if (ff == NULL) {
		PyErr_NoMemory();
		return NULL;
	}
	ff->ff_features = 0;
	ff->ff_lineno = -1;

	if (!future_parse(ff, mod, filename)) {
		PyObject_Free(ff);
		return NULL;
	}
	return ff;
}