1  #include "Python.h"
       2  #include "pycore_ast.h"           // _PyAST_GetDocString()
       3  
       4  #define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
       5  #define ERR_LATE_FUTURE \
       6  "from __future__ imports must occur at the beginning of the file"
       7  
       8  static int
       9  future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)
      10  {
      11      int i;
      12  
      13      assert(s->kind == ImportFrom_kind);
      14  
      15      asdl_alias_seq *names = s->v.ImportFrom.names;
      16      for (i = 0; i < asdl_seq_LEN(names); i++) {
      17          alias_ty name = (alias_ty)asdl_seq_GET(names, i);
      18          const char *feature = PyUnicode_AsUTF8(name->name);
      19          if (!feature)
      20              return 0;
      21          if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
      22              continue;
      23          } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
      24              continue;
      25          } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
      26              continue;
      27          } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
      28              continue;
      29          } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
      30              continue;
      31          } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
      32              continue;
      33          } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
      34              continue;
      35          } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
      36              ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
      37          } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) {
      38              continue;
      39          } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) {
      40              ff->ff_features |= CO_FUTURE_ANNOTATIONS;
      41          } else if (strcmp(feature, "braces") == 0) {
      42              PyErr_SetString(PyExc_SyntaxError,
      43                              "not a chance");
      44              PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
      45              return 0;
      46          } else {
      47              PyErr_Format(PyExc_SyntaxError,
      48                           UNDEFINED_FUTURE_FEATURE, feature);
      49              PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
      50              return 0;
      51          }
      52      }
      53      return 1;
      54  }
      55  
      56  static int
      57  future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
      58  {
      59      int i, done = 0, prev_line = 0;
      60  
      61      if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
      62          return 1;
      63  
      64      if (asdl_seq_LEN(mod->v.Module.body) == 0)
      65          return 1;
      66  
      67      /* A subsequent pass will detect future imports that don't
      68         appear at the beginning of the file.  There's one case,
      69         however, that is easier to handle here: A series of imports
      70         joined by semi-colons, where the first import is a future
      71         statement but some subsequent import has the future form
      72         but is preceded by a regular import.
      73      */
      74  
      75      i = 0;
      76      if (_PyAST_GetDocString(mod->v.Module.body) != NULL)
      77          i++;
      78  
      79      for (; i < asdl_seq_LEN(mod->v.Module.body); i++) {
      80          stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
      81  
      82          if (done && s->lineno > prev_line)
      83              return 1;
      84          prev_line = s->lineno;
      85  
      86          /* The tests below will return from this function unless it is
      87             still possible to find a future statement.  The only things
      88             that can precede a future statement are another future
      89             statement and a doc string.
      90          */
      91  
      92          if (s->kind == ImportFrom_kind) {
      93              identifier modname = s->v.ImportFrom.module;
      94              if (modname &&
      95                  _PyUnicode_EqualToASCIIString(modname, "__future__")) {
      96                  if (done) {
      97                      PyErr_SetString(PyExc_SyntaxError,
      98                                      ERR_LATE_FUTURE);
      99                      PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
     100                      return 0;
     101                  }
     102                  if (!future_check_features(ff, s, filename))
     103                      return 0;
     104                  ff->ff_lineno = s->lineno;
     105              }
     106              else {
     107                  done = 1;
     108              }
     109          }
     110          else {
     111              done = 1;
     112          }
     113      }
     114      return 1;
     115  }
     116  
     117  
     118  PyFutureFeatures *
     119  _PyFuture_FromAST(mod_ty mod, PyObject *filename)
     120  {
     121      PyFutureFeatures *ff;
     122  
     123      ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
     124      if (ff == NULL) {
     125          PyErr_NoMemory();
     126          return NULL;
     127      }
     128      ff->ff_features = 0;
     129      ff->ff_lineno = -1;
     130  
     131      if (!future_parse(ff, mod, filename)) {
     132          PyObject_Free(ff);
     133          return NULL;
     134      }
     135      return ff;
     136  }