LCOV - code coverage report
Current view: top level - Python - future.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 71 73 97.3 %
Date: 2022-07-20 13:12:14 Functions: 3 3 100.0 %
Branches: 55 60 91.7 %

           Branch data     Line data    Source code
       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                 :       1043 : future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)
      10                 :            : {
      11                 :            :     int i;
      12                 :            : 
      13                 :            :     assert(s->kind == ImportFrom_kind);
      14                 :            : 
      15                 :       1043 :     asdl_alias_seq *names = s->v.ImportFrom.names;
      16   [ +  -  +  + ]:       2718 :     for (i = 0; i < asdl_seq_LEN(names); i++) {
      17                 :       1683 :         alias_ty name = (alias_ty)asdl_seq_GET(names, i);
      18                 :       1683 :         const char *feature = PyUnicode_AsUTF8(name->name);
      19         [ -  + ]:       1683 :         if (!feature)
      20                 :          0 :             return 0;
      21         [ +  + ]:       1683 :         if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
      22                 :         15 :             continue;
      23         [ +  + ]:       1668 :         } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
      24                 :          3 :             continue;
      25         [ +  + ]:       1665 :         } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
      26                 :        330 :             continue;
      27         [ +  + ]:       1335 :         } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
      28                 :        656 :             continue;
      29         [ +  + ]:        679 :         } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
      30                 :          1 :             continue;
      31         [ +  + ]:        678 :         } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
      32                 :        105 :             continue;
      33         [ +  + ]:        573 :         } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
      34                 :        311 :             continue;
      35         [ +  + ]:        262 :         } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
      36                 :          1 :             ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
      37         [ +  + ]:        261 :         } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) {
      38                 :          2 :             continue;
      39         [ +  + ]:        259 :         } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) {
      40                 :        251 :             ff->ff_features |= CO_FUTURE_ANNOTATIONS;
      41         [ +  + ]:          8 :         } else if (strcmp(feature, "braces") == 0) {
      42                 :          3 :             PyErr_SetString(PyExc_SyntaxError,
      43                 :            :                             "not a chance");
      44                 :          3 :             PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
      45                 :          3 :             return 0;
      46                 :            :         } else {
      47                 :          5 :             PyErr_Format(PyExc_SyntaxError,
      48                 :            :                          UNDEFINED_FUTURE_FEATURE, feature);
      49                 :          5 :             PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
      50                 :          5 :             return 0;
      51                 :            :         }
      52                 :            :     }
      53                 :       1035 :     return 1;
      54                 :            : }
      55                 :            : 
      56                 :            : static int
      57                 :     113681 : future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
      58                 :            : {
      59                 :     113681 :     int i, done = 0, prev_line = 0;
      60                 :            : 
      61   [ +  +  +  + ]:     113681 :     if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
      62                 :      71342 :         return 1;
      63                 :            : 
      64   [ +  +  -  + ]:      42339 :     if (asdl_seq_LEN(mod->v.Module.body) == 0)
      65                 :        678 :         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                 :      41661 :     i = 0;
      76         [ +  + ]:      41661 :     if (_PyAST_GetDocString(mod->v.Module.body) != NULL)
      77                 :       4852 :         i++;
      78                 :            : 
      79   [ +  -  +  + ]:      86640 :     for (; i < asdl_seq_LEN(mod->v.Module.body); i++) {
      80                 :      56757 :         stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
      81                 :            : 
      82   [ +  +  +  + ]:      56757 :         if (done && s->lineno > prev_line)
      83                 :      11768 :             return 1;
      84                 :      44989 :         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         [ +  + ]:      44989 :         if (s->kind == ImportFrom_kind) {
      93                 :       4610 :             identifier modname = s->v.ImportFrom.module;
      94   [ +  +  +  + ]:       9042 :             if (modname &&
      95                 :       4432 :                 _PyUnicode_EqualToASCIIString(modname, "__future__")) {
      96         [ +  + ]:       1045 :                 if (done) {
      97                 :          2 :                     PyErr_SetString(PyExc_SyntaxError,
      98                 :            :                                     ERR_LATE_FUTURE);
      99                 :          2 :                     PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
     100                 :          2 :                     return 0;
     101                 :            :                 }
     102         [ +  + ]:       1043 :                 if (!future_check_features(ff, s, filename))
     103                 :          8 :                     return 0;
     104                 :       1035 :                 ff->ff_lineno = s->lineno;
     105                 :            :             }
     106                 :            :             else {
     107                 :       3565 :                 done = 1;
     108                 :            :             }
     109                 :            :         }
     110                 :            :         else {
     111                 :      40379 :             done = 1;
     112                 :            :         }
     113                 :            :     }
     114                 :      29883 :     return 1;
     115                 :            : }
     116                 :            : 
     117                 :            : 
     118                 :            : PyFutureFeatures *
     119                 :     113681 : _PyFuture_FromAST(mod_ty mod, PyObject *filename)
     120                 :            : {
     121                 :            :     PyFutureFeatures *ff;
     122                 :            : 
     123                 :     113681 :     ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
     124         [ -  + ]:     113681 :     if (ff == NULL) {
     125                 :            :         PyErr_NoMemory();
     126                 :          0 :         return NULL;
     127                 :            :     }
     128                 :     113681 :     ff->ff_features = 0;
     129                 :     113681 :     ff->ff_lineno = -1;
     130                 :            : 
     131         [ +  + ]:     113681 :     if (!future_parse(ff, mod, filename)) {
     132                 :         10 :         PyObject_Free(ff);
     133                 :         10 :         return NULL;
     134                 :            :     }
     135                 :     113671 :     return ff;
     136                 :            : }

Generated by: LCOV version 1.14