LCOV - code coverage report
Current view: top level - Python - future.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 43 68 63.2 %
Date: 2017-04-19 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.10