/Python/future.c (5cb21ac61c2a2311789fea8f93124d1eccd06653) (4679 bytes) (mode 100644) (type blob)
#include "Python.h"
#include "Python-ast.h"
#include "node.h"
#include "token.h"
#include "graminit.h"
#include "code.h"
#include "symtable.h"
#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
#define ERR_LATE_FUTURE \
"from __future__ imports must occur at the beginning of the file"
static int
future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *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_AsUTF8(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, FUTURE_PRINT_FUNCTION) == 0) {
continue;
} else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
continue;
} else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
} else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) {
ff->ff_features |= CO_FUTURE_GENERATOR_STOP;
} else if (strcmp(feature, "braces") == 0) {
PyErr_SetString(PyExc_SyntaxError,
"not a chance");
PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
return 0;
} else {
PyErr_Format(PyExc_SyntaxError,
UNDEFINED_FUTURE_FEATURE, feature);
PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
return 0;
}
}
return 1;
}
static int
future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
{
int i, done = 0, prev_line = 0;
if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
return 1;
if (asdl_seq_LEN(mod->v.Module.body) == 0)
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 handle 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) {
identifier modname = s->v.ImportFrom.module;
if (modname &&
_PyUnicode_EqualToASCIIString(modname, "__future__")) {
if (done) {
PyErr_SetString(PyExc_SyntaxError,
ERR_LATE_FUTURE);
PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
return 0;
}
if (!future_check_features(ff, s, filename))
return 0;
ff->ff_lineno = s->lineno;
}
else {
done = 1;
}
}
else {
done = 1;
}
}
return 1;
}
PyFutureFeatures *
PyFuture_FromASTObject(mod_ty mod, PyObject *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;
}
PyFutureFeatures *
PyFuture_FromAST(mod_ty mod, const char *filename_str)
{
PyFutureFeatures *ff;
PyObject *filename;
filename = PyUnicode_DecodeFSDefault(filename_str);
if (filename == NULL)
return NULL;
ff = PyFuture_FromASTObject(mod, filename);
Py_DECREF(filename);
return ff;
}
Mode |
Type |
Size |
Ref |
File |
100644 |
blob |
582 |
58471109208922c9ee8c4b06135725f03ed16814 |
.bzrignore |
100644 |
blob |
545 |
fcf9df6a7a698e4bd87ed0c1cc4ed70bad8b9887 |
.codecov.yml |
100644 |
blob |
255 |
82694d81f276b2c59a0a93a4f678e1852e625052 |
.gitattributes |
040000 |
tree |
- |
7e849e161267e730810fbbe6a848b14d5d002788 |
.github |
100644 |
blob |
1433 |
f436777c7cf099c43c9f04ad31fe1551b4f6079d |
.gitignore |
100644 |
blob |
1060 |
eb19a6c88d28d05588db25d21525ee2e19c22666 |
.hgeol |
100644 |
blob |
1358 |
68c607f2e8d420c8dfd0748efcd3b3b5447def16 |
.hgignore |
100644 |
blob |
8917 |
8f51c2ced49aed46d8b480280b630ea4264c57c3 |
.hgtags |
100644 |
blob |
1328 |
b9be0f11fdb829f16e9de1921257eb7ee45fac57 |
.hgtouch |
100644 |
blob |
264 |
f69ca2bf6acda78c03fa4974e17452e6baf370f5 |
.mention-bot |
100644 |
blob |
3512 |
e7e8694530ca21a6d7a19da3fab687a3e9d79e9c |
.travis.yml |
040000 |
tree |
- |
cc9d0cda2a69a4935d8550fdeb74df08c7403a8b |
Doc |
040000 |
tree |
- |
5dd6fc9dc09374506491247872c868eca111e256 |
Grammar |
040000 |
tree |
- |
cd8b4bafaede5f4f9167489b08f32be2c9cc1cdd |
Include |
100644 |
blob |
12773 |
f5d0b39a0cdddb91a31a537052b7d8d31a4aa79f |
LICENSE |
040000 |
tree |
- |
3690b4af0b558c5a5bdf91c95e7868b662cfb3ae |
Lib |
040000 |
tree |
- |
1db7415d4375525eaf8d05ddd5b088de3321041c |
Mac |
100644 |
blob |
59452 |
e5141f11dade2db62c6d5dfb2fe79528f948b6ab |
Makefile.pre.in |
040000 |
tree |
- |
870bc33839512fe6217ca33b44447c0f9636b656 |
Misc |
040000 |
tree |
- |
16b9bf7b58779e0ac085f748bf52409c632b2e88 |
Modules |
040000 |
tree |
- |
06e40820601a63a04fc9f9baa54c442dfbeb1a6c |
Objects |
040000 |
tree |
- |
b4df9f86f76a7e10a7d98259980d4f5d5d1223a1 |
PC |
040000 |
tree |
- |
1e837a7d204fd247fb9a105adaa758a6d63486d8 |
PCbuild |
040000 |
tree |
- |
75771c7c20fe7a121d596299c5440aef10c6f884 |
Parser |
040000 |
tree |
- |
3efbcc80237ab7c3d4eb5bf31c893ca6de88e747 |
Programs |
040000 |
tree |
- |
e2f223f3d33405a1030e8df6a21bdbb6c1078b51 |
Python |
100644 |
blob |
9325 |
9c95815d9e9d91b8dae8e05d8bbc696fe19f796b |
README.rst |
040000 |
tree |
- |
52c054fb01e9d587856b6ffcbcd972a3b7c12341 |
Tools |
100644 |
blob |
10914 |
2a745e57466cae1af014f239e5b91a8fc1fd64d8 |
aclocal.m4 |
100755 |
blob |
42856 |
1f5c50c0d1529d50b94dc3533ca72a47f0fa5849 |
config.guess |
100755 |
blob |
35740 |
d654d03cdcd2226a5d7584890717e674a8122f4f |
config.sub |
100755 |
blob |
485181 |
3e89bfabc3a519ae13a83e35eed97e7322b2b6e2 |
configure |
100644 |
blob |
161054 |
c58322dc8c7c07c0e38ca3c98e8ed89e108e2dfa |
configure.ac |
100755 |
blob |
7122 |
0ec27bcd488da5cad6ead13d70accbdbc40d31ef |
install-sh |
100644 |
blob |
41198 |
0a3d59ef9ae602fa02405c7b7068efaf7b55b21b |
pyconfig.h.in |
100644 |
blob |
98894 |
6a05643838bb4ef64ae093f7a0f816a80d6f09f4 |
setup.py |
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"
Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/benf_wspdigital/cpython
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/benf_wspdigital/cpython
Clone this repository using git:
git clone git://git.rocketgit.com/user/benf_wspdigital/cpython
You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a
merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main