• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Argument Clinic
4# Copyright 2012-2013 by Larry Hastings.
5# Licensed to the PSF under a contributor agreement.
6#
7
8import abc
9import ast
10import atexit
11import collections
12import contextlib
13import copy
14import cpp
15import functools
16import hashlib
17import inspect
18import io
19import itertools
20import os
21import pprint
22import re
23import shlex
24import string
25import sys
26import tempfile
27import textwrap
28import traceback
29import types
30import uuid
31
32from types import *
33NoneType = type(None)
34
35# TODO:
36#
37# soon:
38#
39# * allow mixing any two of {positional-only, positional-or-keyword,
40#   keyword-only}
41#       * dict constructor uses positional-only and keyword-only
42#       * max and min use positional only with an optional group
43#         and keyword-only
44#
45
46version = '1'
47
48_empty = inspect._empty
49_void = inspect._void
50
51NoneType = type(None)
52
53class Unspecified:
54    def __repr__(self):
55        return '<Unspecified>'
56
57unspecified = Unspecified()
58
59
60class Null:
61    def __repr__(self):
62        return '<Null>'
63
64NULL = Null()
65
66
67class Unknown:
68    def __repr__(self):
69        return '<Unknown>'
70
71unknown = Unknown()
72
73sig_end_marker = '--'
74
75
76_text_accumulator_nt = collections.namedtuple("_text_accumulator", "text append output")
77
78def _text_accumulator():
79    text = []
80    def output():
81        s = ''.join(text)
82        text.clear()
83        return s
84    return _text_accumulator_nt(text, text.append, output)
85
86
87text_accumulator_nt = collections.namedtuple("text_accumulator", "text append")
88
89def text_accumulator():
90    """
91    Creates a simple text accumulator / joiner.
92
93    Returns a pair of callables:
94        append, output
95    "append" appends a string to the accumulator.
96    "output" returns the contents of the accumulator
97       joined together (''.join(accumulator)) and
98       empties the accumulator.
99    """
100    text, append, output = _text_accumulator()
101    return text_accumulator_nt(append, output)
102
103
104def warn_or_fail(fail=False, *args, filename=None, line_number=None):
105    joined = " ".join([str(a) for a in args])
106    add, output = text_accumulator()
107    if fail:
108        add("Error")
109    else:
110        add("Warning")
111    if clinic:
112        if filename is None:
113            filename = clinic.filename
114        if getattr(clinic, 'block_parser', None) and (line_number is None):
115            line_number = clinic.block_parser.line_number
116    if filename is not None:
117        add(' in file "' + filename + '"')
118    if line_number is not None:
119        add(" on line " + str(line_number))
120    add(':\n')
121    add(joined)
122    print(output())
123    if fail:
124        sys.exit(-1)
125
126
127def warn(*args, filename=None, line_number=None):
128    return warn_or_fail(False, *args, filename=filename, line_number=line_number)
129
130def fail(*args, filename=None, line_number=None):
131    return warn_or_fail(True, *args, filename=filename, line_number=line_number)
132
133
134def quoted_for_c_string(s):
135    for old, new in (
136        ('\\', '\\\\'), # must be first!
137        ('"', '\\"'),
138        ("'", "\\'"),
139        ):
140        s = s.replace(old, new)
141    return s
142
143def c_repr(s):
144    return '"' + s + '"'
145
146
147is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
148
149def is_legal_py_identifier(s):
150    return all(is_legal_c_identifier(field) for field in s.split('.'))
151
152# identifiers that are okay in Python but aren't a good idea in C.
153# so if they're used Argument Clinic will add "_value" to the end
154# of the name in C.
155c_keywords = set("""
156asm auto break case char const continue default do double
157else enum extern float for goto if inline int long
158register return short signed sizeof static struct switch
159typedef typeof union unsigned void volatile while
160""".strip().split())
161
162def ensure_legal_c_identifier(s):
163    # for now, just complain if what we're given isn't legal
164    if not is_legal_c_identifier(s):
165        fail("Illegal C identifier: {}".format(s))
166    # but if we picked a C keyword, pick something else
167    if s in c_keywords:
168        return s + "_value"
169    return s
170
171def rstrip_lines(s):
172    text, add, output = _text_accumulator()
173    for line in s.split('\n'):
174        add(line.rstrip())
175        add('\n')
176    text.pop()
177    return output()
178
179def format_escape(s):
180    # double up curly-braces, this string will be used
181    # as part of a format_map() template later
182    s = s.replace('{', '{{')
183    s = s.replace('}', '}}')
184    return s
185
186def linear_format(s, **kwargs):
187    """
188    Perform str.format-like substitution, except:
189      * The strings substituted must be on lines by
190        themselves.  (This line is the "source line".)
191      * If the substitution text is empty, the source line
192        is removed in the output.
193      * If the field is not recognized, the original line
194        is passed unmodified through to the output.
195      * If the substitution text is not empty:
196          * Each line of the substituted text is indented
197            by the indent of the source line.
198          * A newline will be added to the end.
199    """
200
201    add, output = text_accumulator()
202    for line in s.split('\n'):
203        indent, curly, trailing = line.partition('{')
204        if not curly:
205            add(line)
206            add('\n')
207            continue
208
209        name, curly, trailing = trailing.partition('}')
210        if not curly or name not in kwargs:
211            add(line)
212            add('\n')
213            continue
214
215        if trailing:
216            fail("Text found after {" + name + "} block marker!  It must be on a line by itself.")
217        if indent.strip():
218            fail("Non-whitespace characters found before {" + name + "} block marker!  It must be on a line by itself.")
219
220        value = kwargs[name]
221        if not value:
222            continue
223
224        value = textwrap.indent(rstrip_lines(value), indent)
225        add(value)
226        add('\n')
227
228    return output()[:-1]
229
230def indent_all_lines(s, prefix):
231    """
232    Returns 's', with 'prefix' prepended to all lines.
233
234    If the last line is empty, prefix is not prepended
235    to it.  (If s is blank, returns s unchanged.)
236
237    (textwrap.indent only adds to non-blank lines.)
238    """
239    split = s.split('\n')
240    last = split.pop()
241    final = []
242    for line in split:
243        final.append(prefix)
244        final.append(line)
245        final.append('\n')
246    if last:
247        final.append(prefix)
248        final.append(last)
249    return ''.join(final)
250
251def suffix_all_lines(s, suffix):
252    """
253    Returns 's', with 'suffix' appended to all lines.
254
255    If the last line is empty, suffix is not appended
256    to it.  (If s is blank, returns s unchanged.)
257    """
258    split = s.split('\n')
259    last = split.pop()
260    final = []
261    for line in split:
262        final.append(line)
263        final.append(suffix)
264        final.append('\n')
265    if last:
266        final.append(last)
267        final.append(suffix)
268    return ''.join(final)
269
270
271def version_splitter(s):
272    """Splits a version string into a tuple of integers.
273
274    The following ASCII characters are allowed, and employ
275    the following conversions:
276        a -> -3
277        b -> -2
278        c -> -1
279    (This permits Python-style version strings such as "1.4b3".)
280    """
281    version = []
282    accumulator = []
283    def flush():
284        if not accumulator:
285            raise ValueError('Unsupported version string: ' + repr(s))
286        version.append(int(''.join(accumulator)))
287        accumulator.clear()
288
289    for c in s:
290        if c.isdigit():
291            accumulator.append(c)
292        elif c == '.':
293            flush()
294        elif c in 'abc':
295            flush()
296            version.append('abc'.index(c) - 3)
297        else:
298            raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
299    flush()
300    return tuple(version)
301
302def version_comparitor(version1, version2):
303    iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
304    for i, (a, b) in enumerate(iterator):
305        if a < b:
306            return -1
307        if a > b:
308            return 1
309    return 0
310
311
312class CRenderData:
313    def __init__(self):
314
315        # The C statements to declare variables.
316        # Should be full lines with \n eol characters.
317        self.declarations = []
318
319        # The C statements required to initialize the variables before the parse call.
320        # Should be full lines with \n eol characters.
321        self.initializers = []
322
323        # The C statements needed to dynamically modify the values
324        # parsed by the parse call, before calling the impl.
325        self.modifications = []
326
327        # The entries for the "keywords" array for PyArg_ParseTuple.
328        # Should be individual strings representing the names.
329        self.keywords = []
330
331        # The "format units" for PyArg_ParseTuple.
332        # Should be individual strings that will get
333        self.format_units = []
334
335        # The varargs arguments for PyArg_ParseTuple.
336        self.parse_arguments = []
337
338        # The parameter declarations for the impl function.
339        self.impl_parameters = []
340
341        # The arguments to the impl function at the time it's called.
342        self.impl_arguments = []
343
344        # For return converters: the name of the variable that
345        # should receive the value returned by the impl.
346        self.return_value = "return_value"
347
348        # For return converters: the code to convert the return
349        # value from the parse function.  This is also where
350        # you should check the _return_value for errors, and
351        # "goto exit" if there are any.
352        self.return_conversion = []
353
354        # The C statements required to clean up after the impl call.
355        self.cleanup = []
356
357
358class FormatCounterFormatter(string.Formatter):
359    """
360    This counts how many instances of each formatter
361    "replacement string" appear in the format string.
362
363    e.g. after evaluating "string {a}, {b}, {c}, {a}"
364         the counts dict would now look like
365         {'a': 2, 'b': 1, 'c': 1}
366    """
367    def __init__(self):
368        self.counts = collections.Counter()
369
370    def get_value(self, key, args, kwargs):
371        self.counts[key] += 1
372        return ''
373
374class Language(metaclass=abc.ABCMeta):
375
376    start_line = ""
377    body_prefix = ""
378    stop_line = ""
379    checksum_line = ""
380
381    def __init__(self, filename):
382        pass
383
384    @abc.abstractmethod
385    def render(self, clinic, signatures):
386        pass
387
388    def parse_line(self, line):
389        pass
390
391    def validate(self):
392        def assert_only_one(attr, *additional_fields):
393            """
394            Ensures that the string found at getattr(self, attr)
395            contains exactly one formatter replacement string for
396            each valid field.  The list of valid fields is
397            ['dsl_name'] extended by additional_fields.
398
399            e.g.
400                self.fmt = "{dsl_name} {a} {b}"
401
402                # this passes
403                self.assert_only_one('fmt', 'a', 'b')
404
405                # this fails, the format string has a {b} in it
406                self.assert_only_one('fmt', 'a')
407
408                # this fails, the format string doesn't have a {c} in it
409                self.assert_only_one('fmt', 'a', 'b', 'c')
410
411                # this fails, the format string has two {a}s in it,
412                # it must contain exactly one
413                self.fmt2 = '{dsl_name} {a} {a}'
414                self.assert_only_one('fmt2', 'a')
415
416            """
417            fields = ['dsl_name']
418            fields.extend(additional_fields)
419            line = getattr(self, attr)
420            fcf = FormatCounterFormatter()
421            fcf.format(line)
422            def local_fail(should_be_there_but_isnt):
423                if should_be_there_but_isnt:
424                    fail("{} {} must contain {{{}}} exactly once!".format(
425                        self.__class__.__name__, attr, name))
426                else:
427                    fail("{} {} must not contain {{{}}}!".format(
428                        self.__class__.__name__, attr, name))
429
430            for name, count in fcf.counts.items():
431                if name in fields:
432                    if count > 1:
433                        local_fail(True)
434                else:
435                    local_fail(False)
436            for name in fields:
437                if fcf.counts.get(name) != 1:
438                    local_fail(True)
439
440        assert_only_one('start_line')
441        assert_only_one('stop_line')
442
443        field = "arguments" if "{arguments}" in self.checksum_line else "checksum"
444        assert_only_one('checksum_line', field)
445
446
447
448class PythonLanguage(Language):
449
450    language      = 'Python'
451    start_line    = "#/*[{dsl_name} input]"
452    body_prefix   = "#"
453    stop_line     = "#[{dsl_name} start generated code]*/"
454    checksum_line = "#/*[{dsl_name} end generated code: {arguments}]*/"
455
456
457def permute_left_option_groups(l):
458    """
459    Given [1, 2, 3], should yield:
460       ()
461       (3,)
462       (2, 3)
463       (1, 2, 3)
464    """
465    yield tuple()
466    accumulator = []
467    for group in reversed(l):
468        accumulator = list(group) + accumulator
469        yield tuple(accumulator)
470
471
472def permute_right_option_groups(l):
473    """
474    Given [1, 2, 3], should yield:
475      ()
476      (1,)
477      (1, 2)
478      (1, 2, 3)
479    """
480    yield tuple()
481    accumulator = []
482    for group in l:
483        accumulator.extend(group)
484        yield tuple(accumulator)
485
486
487def permute_optional_groups(left, required, right):
488    """
489    Generator function that computes the set of acceptable
490    argument lists for the provided iterables of
491    argument groups.  (Actually it generates a tuple of tuples.)
492
493    Algorithm: prefer left options over right options.
494
495    If required is empty, left must also be empty.
496    """
497    required = tuple(required)
498    result = []
499
500    if not required:
501        assert not left
502
503    accumulator = []
504    counts = set()
505    for r in permute_right_option_groups(right):
506        for l in permute_left_option_groups(left):
507            t = l + required + r
508            if len(t) in counts:
509                continue
510            counts.add(len(t))
511            accumulator.append(t)
512
513    accumulator.sort(key=len)
514    return tuple(accumulator)
515
516
517def strip_leading_and_trailing_blank_lines(s):
518    lines = s.rstrip().split('\n')
519    while lines:
520        line = lines[0]
521        if line.strip():
522            break
523        del lines[0]
524    return '\n'.join(lines)
525
526@functools.lru_cache()
527def normalize_snippet(s, *, indent=0):
528    """
529    Reformats s:
530        * removes leading and trailing blank lines
531        * ensures that it does not end with a newline
532        * dedents so the first nonwhite character on any line is at column "indent"
533    """
534    s = strip_leading_and_trailing_blank_lines(s)
535    s = textwrap.dedent(s)
536    if indent:
537        s = textwrap.indent(s, ' ' * indent)
538    return s
539
540
541def wrap_declarations(text, length=78):
542    """
543    A simple-minded text wrapper for C function declarations.
544
545    It views a declaration line as looking like this:
546        xxxxxxxx(xxxxxxxxx,xxxxxxxxx)
547    If called with length=30, it would wrap that line into
548        xxxxxxxx(xxxxxxxxx,
549                 xxxxxxxxx)
550    (If the declaration has zero or one parameters, this
551    function won't wrap it.)
552
553    If this doesn't work properly, it's probably better to
554    start from scratch with a more sophisticated algorithm,
555    rather than try and improve/debug this dumb little function.
556    """
557    lines = []
558    for line in text.split('\n'):
559        prefix, _, after_l_paren = line.partition('(')
560        if not after_l_paren:
561            lines.append(line)
562            continue
563        parameters, _, after_r_paren = after_l_paren.partition(')')
564        if not _:
565            lines.append(line)
566            continue
567        if ',' not in parameters:
568            lines.append(line)
569            continue
570        parameters = [x.strip() + ", " for x in parameters.split(',')]
571        prefix += "("
572        if len(prefix) < length:
573            spaces = " " * len(prefix)
574        else:
575            spaces = " " * 4
576
577        while parameters:
578            line = prefix
579            first = True
580            while parameters:
581                if (not first and
582                    (len(line) + len(parameters[0]) > length)):
583                    break
584                line += parameters.pop(0)
585                first = False
586            if not parameters:
587                line = line.rstrip(", ") + ")" + after_r_paren
588            lines.append(line.rstrip())
589            prefix = spaces
590    return "\n".join(lines)
591
592
593class CLanguage(Language):
594
595    body_prefix   = "#"
596    language      = 'C'
597    start_line    = "/*[{dsl_name} input]"
598    body_prefix   = ""
599    stop_line     = "[{dsl_name} start generated code]*/"
600    checksum_line = "/*[{dsl_name} end generated code: {arguments}]*/"
601
602    def __init__(self, filename):
603        super().__init__(filename)
604        self.cpp = cpp.Monitor(filename)
605        self.cpp.fail = fail
606
607    def parse_line(self, line):
608        self.cpp.writeline(line)
609
610    def render(self, clinic, signatures):
611        function = None
612        for o in signatures:
613            if isinstance(o, Function):
614                if function:
615                    fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
616                function = o
617        return self.render_function(clinic, function)
618
619    def docstring_for_c_string(self, f):
620        text, add, output = _text_accumulator()
621        # turn docstring into a properly quoted C string
622        for line in f.docstring.split('\n'):
623            add('"')
624            add(quoted_for_c_string(line))
625            add('\\n"\n')
626
627        if text[-2] == sig_end_marker:
628            # If we only have a signature, add the blank line that the
629            # __text_signature__ getter expects to be there.
630            add('"\\n"')
631        else:
632            text.pop()
633            add('"')
634        return ''.join(text)
635
636    def output_templates(self, f):
637        parameters = list(f.parameters.values())
638        assert parameters
639        assert isinstance(parameters[0].converter, self_converter)
640        del parameters[0]
641        converters = [p.converter for p in parameters]
642
643        has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
644        default_return_converter = (not f.return_converter or
645            f.return_converter.type == 'PyObject *')
646
647        positional = parameters and parameters[-1].is_positional_only()
648        all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
649        first_optional = len(parameters)
650        for i, p in enumerate(parameters):
651            c = p.converter
652            if type(c) != object_converter:
653                break
654            if c.format_unit != 'O':
655                break
656            if p.default is not unspecified:
657                first_optional = min(first_optional, i)
658        else:
659            all_boring_objects = True
660
661        new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
662
663        meth_o = (len(parameters) == 1 and
664              parameters[0].is_positional_only() and
665              not converters[0].is_optional() and
666              not new_or_init)
667
668        # we have to set these things before we're done:
669        #
670        # docstring_prototype
671        # docstring_definition
672        # impl_prototype
673        # methoddef_define
674        # parser_prototype
675        # parser_definition
676        # impl_definition
677        # cpp_if
678        # cpp_endif
679        # methoddef_ifndef
680
681        return_value_declaration = "PyObject *return_value = NULL;"
682
683        methoddef_define = normalize_snippet("""
684            #define {methoddef_name}    \\
685                {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
686            """)
687        if new_or_init and not f.docstring:
688            docstring_prototype = docstring_definition = ''
689        else:
690            docstring_prototype = normalize_snippet("""
691                PyDoc_VAR({c_basename}__doc__);
692                """)
693            docstring_definition = normalize_snippet("""
694                PyDoc_STRVAR({c_basename}__doc__,
695                {docstring});
696                """)
697        impl_definition = normalize_snippet("""
698            static {impl_return_type}
699            {c_basename}_impl({impl_parameters})
700            """)
701        impl_prototype = parser_prototype = parser_definition = None
702
703        parser_prototype_keyword = normalize_snippet("""
704            static PyObject *
705            {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
706            """)
707
708        parser_prototype_fastcall = normalize_snippet("""
709            static PyObject *
710            {c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
711            """)
712
713        parser_prototype_varargs = normalize_snippet("""
714            static PyObject *
715            {c_basename}({self_type}{self_name}, PyObject *args)
716            """)
717
718        # parser_body_fields remembers the fields passed in to the
719        # previous call to parser_body. this is used for an awful hack.
720        parser_body_fields = ()
721        def parser_body(prototype, *fields):
722            nonlocal parser_body_fields
723            add, output = text_accumulator()
724            add(prototype)
725            parser_body_fields = fields
726
727            fields = list(fields)
728            fields.insert(0, normalize_snippet("""
729                {{
730                    {return_value_declaration}
731                    {declarations}
732                    {initializers}
733                """) + "\n")
734            # just imagine--your code is here in the middle
735            fields.append(normalize_snippet("""
736                    {modifications}
737                    {return_value} = {c_basename}_impl({impl_arguments});
738                    {return_conversion}
739
740                {exit_label}
741                    {cleanup}
742                    return return_value;
743                }}
744                """))
745            for field in fields:
746                add('\n')
747                add(field)
748            return output()
749
750        def insert_keywords(s):
751            return linear_format(s, declarations=
752                'static const char * const _keywords[] = {{{keywords}, NULL}};\n'
753                'static _PyArg_Parser _parser = {{"{format_units}:{name}", _keywords, 0}};\n'
754                '{declarations}')
755
756        if not parameters:
757            # no parameters, METH_NOARGS
758
759            flags = "METH_NOARGS"
760
761            parser_prototype = normalize_snippet("""
762                static PyObject *
763                {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
764                """)
765            parser_definition = parser_prototype
766
767            if default_return_converter:
768                parser_definition = parser_prototype + '\n' + normalize_snippet("""
769                    {{
770                        return {c_basename}_impl({impl_arguments});
771                    }}
772                    """)
773            else:
774                parser_definition = parser_body(parser_prototype)
775
776        elif meth_o:
777            flags = "METH_O"
778
779            if (isinstance(converters[0], object_converter) and
780                converters[0].format_unit == 'O'):
781                meth_o_prototype = normalize_snippet("""
782                    static PyObject *
783                    {c_basename}({impl_parameters})
784                    """)
785
786                if default_return_converter:
787                    # maps perfectly to METH_O, doesn't need a return converter.
788                    # so we skip making a parse function
789                    # and call directly into the impl function.
790                    impl_prototype = parser_prototype = parser_definition = ''
791                    impl_definition = meth_o_prototype
792                else:
793                    # SLIGHT HACK
794                    # use impl_parameters for the parser here!
795                    parser_prototype = meth_o_prototype
796                    parser_definition = parser_body(parser_prototype)
797
798            else:
799                argname = 'arg'
800                if parameters[0].name == argname:
801                    argname += '_'
802                parser_prototype = normalize_snippet("""
803                    static PyObject *
804                    {c_basename}({self_type}{self_name}, PyObject *%s)
805                    """ % argname)
806
807                parser_definition = parser_body(parser_prototype, normalize_snippet("""
808                    if (!PyArg_Parse(%s, "{format_units}:{name}", {parse_arguments})) {{
809                        goto exit;
810                    }}
811                    """ % argname, indent=4))
812
813        elif has_option_groups:
814            # positional parameters with option groups
815            # (we have to generate lots of PyArg_ParseTuple calls
816            #  in a big switch statement)
817
818            flags = "METH_VARARGS"
819            parser_prototype = parser_prototype_varargs
820
821            parser_definition = parser_body(parser_prototype, '    {option_group_parsing}')
822
823        elif positional and all_boring_objects:
824            # positional-only, but no option groups,
825            # and nothing but normal objects:
826            # PyArg_UnpackTuple!
827
828            flags = "METH_VARARGS"
829            parser_prototype = parser_prototype_varargs
830
831            parser_definition = parser_body(parser_prototype, normalize_snippet("""
832                if (!PyArg_UnpackTuple(args, "{name}",
833                    {unpack_min}, {unpack_max},
834                    {parse_arguments})) {{
835                    goto exit;
836                }}
837                """, indent=4))
838
839        elif positional:
840            # positional-only, but no option groups
841            # we only need one call to PyArg_ParseTuple
842
843            flags = "METH_VARARGS"
844            parser_prototype = parser_prototype_varargs
845
846            parser_definition = parser_body(parser_prototype, normalize_snippet("""
847                if (!PyArg_ParseTuple(args, "{format_units}:{name}",
848                    {parse_arguments})) {{
849                    goto exit;
850                }}
851                """, indent=4))
852
853        elif not new_or_init:
854            flags = "METH_FASTCALL"
855
856            parser_prototype = parser_prototype_fastcall
857
858            body = normalize_snippet("""
859                if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
860                    {parse_arguments})) {{
861                    goto exit;
862                }}
863                """, indent=4)
864            parser_definition = parser_body(parser_prototype, body)
865            parser_definition = insert_keywords(parser_definition)
866        else:
867            # positional-or-keyword arguments
868            flags = "METH_VARARGS|METH_KEYWORDS"
869
870            parser_prototype = parser_prototype_keyword
871
872            body = normalize_snippet("""
873                if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
874                    {parse_arguments})) {{
875                    goto exit;
876                }}
877                """, indent=4)
878            parser_definition = parser_body(parser_prototype, body)
879            parser_definition = insert_keywords(parser_definition)
880
881
882        if new_or_init:
883            methoddef_define = ''
884
885            if f.kind == METHOD_NEW:
886                parser_prototype = parser_prototype_keyword
887            else:
888                return_value_declaration = "int return_value = -1;"
889                parser_prototype = normalize_snippet("""
890                    static int
891                    {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
892                    """)
893
894            fields = list(parser_body_fields)
895            parses_positional = 'METH_NOARGS' not in flags
896            parses_keywords = 'METH_KEYWORDS' in flags
897            if parses_keywords:
898                assert parses_positional
899
900            if not parses_keywords:
901                fields.insert(0, normalize_snippet("""
902                    if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) {{
903                        goto exit;
904                    }}
905                    """, indent=4))
906                if not parses_positional:
907                    fields.insert(0, normalize_snippet("""
908                        if ({self_type_check}!_PyArg_NoPositional("{name}", args)) {{
909                            goto exit;
910                        }}
911                        """, indent=4))
912
913            parser_definition = parser_body(parser_prototype, *fields)
914            if parses_keywords:
915                parser_definition = insert_keywords(parser_definition)
916
917
918        if f.methoddef_flags:
919            flags += '|' + f.methoddef_flags
920
921        methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
922
923        methoddef_ifndef = ''
924        conditional = self.cpp.condition()
925        if not conditional:
926            cpp_if = cpp_endif = ''
927        else:
928            cpp_if = "#if " + conditional
929            cpp_endif = "#endif /* " + conditional + " */"
930
931            if methoddef_define and f.name not in clinic.ifndef_symbols:
932                clinic.ifndef_symbols.add(f.name)
933                methoddef_ifndef = normalize_snippet("""
934                    #ifndef {methoddef_name}
935                        #define {methoddef_name}
936                    #endif /* !defined({methoddef_name}) */
937                    """)
938
939
940        # add ';' to the end of parser_prototype and impl_prototype
941        # (they mustn't be None, but they could be an empty string.)
942        assert parser_prototype is not None
943        if parser_prototype:
944            assert not parser_prototype.endswith(';')
945            parser_prototype += ';'
946
947        if impl_prototype is None:
948            impl_prototype = impl_definition
949        if impl_prototype:
950            impl_prototype += ";"
951
952        parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
953
954        d = {
955            "docstring_prototype" : docstring_prototype,
956            "docstring_definition" : docstring_definition,
957            "impl_prototype" : impl_prototype,
958            "methoddef_define" : methoddef_define,
959            "parser_prototype" : parser_prototype,
960            "parser_definition" : parser_definition,
961            "impl_definition" : impl_definition,
962            "cpp_if" : cpp_if,
963            "cpp_endif" : cpp_endif,
964            "methoddef_ifndef" : methoddef_ifndef,
965        }
966
967        # make sure we didn't forget to assign something,
968        # and wrap each non-empty value in \n's
969        d2 = {}
970        for name, value in d.items():
971            assert value is not None, "got a None value for template " + repr(name)
972            if value:
973                value = '\n' + value + '\n'
974            d2[name] = value
975        return d2
976
977    @staticmethod
978    def group_to_variable_name(group):
979        adjective = "left_" if group < 0 else "right_"
980        return "group_" + adjective + str(abs(group))
981
982    def render_option_group_parsing(self, f, template_dict):
983        # positional only, grouped, optional arguments!
984        # can be optional on the left or right.
985        # here's an example:
986        #
987        # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
988        #
989        # Here group D are required, and all other groups are optional.
990        # (Group D's "group" is actually None.)
991        # We can figure out which sets of arguments we have based on
992        # how many arguments are in the tuple.
993        #
994        # Note that you need to count up on both sides.  For example,
995        # you could have groups C+D, or C+D+E, or C+D+E+F.
996        #
997        # What if the number of arguments leads us to an ambiguous result?
998        # Clinic prefers groups on the left.  So in the above example,
999        # five arguments would map to B+C, not C+D.
1000
1001        add, output = text_accumulator()
1002        parameters = list(f.parameters.values())
1003        if isinstance(parameters[0].converter, self_converter):
1004            del parameters[0]
1005
1006        groups = []
1007        group = None
1008        left = []
1009        right = []
1010        required = []
1011        last = unspecified
1012
1013        for p in parameters:
1014            group_id = p.group
1015            if group_id != last:
1016                last = group_id
1017                group = []
1018                if group_id < 0:
1019                    left.append(group)
1020                elif group_id == 0:
1021                    group = required
1022                else:
1023                    right.append(group)
1024            group.append(p)
1025
1026        count_min = sys.maxsize
1027        count_max = -1
1028
1029        add("switch (PyTuple_GET_SIZE(args)) {\n")
1030        for subset in permute_optional_groups(left, required, right):
1031            count = len(subset)
1032            count_min = min(count_min, count)
1033            count_max = max(count_max, count)
1034
1035            if count == 0:
1036                add("""    case 0:
1037        break;
1038""")
1039                continue
1040
1041            group_ids = {p.group for p in subset}  # eliminate duplicates
1042            d = {}
1043            d['count'] = count
1044            d['name'] = f.name
1045            d['format_units'] = "".join(p.converter.format_unit for p in subset)
1046
1047            parse_arguments = []
1048            for p in subset:
1049                p.converter.parse_argument(parse_arguments)
1050            d['parse_arguments'] = ", ".join(parse_arguments)
1051
1052            group_ids.discard(0)
1053            lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
1054            lines = "\n".join(lines)
1055
1056            s = """
1057    case {count}:
1058        if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments})) {{
1059            goto exit;
1060        }}
1061        {group_booleans}
1062        break;
1063"""[1:]
1064            s = linear_format(s, group_booleans=lines)
1065            s = s.format_map(d)
1066            add(s)
1067
1068        add("    default:\n")
1069        s = '        PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
1070        add(s.format(f.full_name, count_min, count_max))
1071        add('        goto exit;\n')
1072        add("}")
1073        template_dict['option_group_parsing'] = format_escape(output())
1074
1075    def render_function(self, clinic, f):
1076        if not f:
1077            return ""
1078
1079        add, output = text_accumulator()
1080        data = CRenderData()
1081
1082        assert f.parameters, "We should always have a 'self' at this point!"
1083        parameters = f.render_parameters
1084        converters = [p.converter for p in parameters]
1085
1086        templates = self.output_templates(f)
1087
1088        f_self = parameters[0]
1089        selfless = parameters[1:]
1090        assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
1091
1092        last_group = 0
1093        first_optional = len(selfless)
1094        positional = selfless and selfless[-1].is_positional_only()
1095        new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
1096        default_return_converter = (not f.return_converter or
1097            f.return_converter.type == 'PyObject *')
1098        has_option_groups = False
1099
1100        # offset i by -1 because first_optional needs to ignore self
1101        for i, p in enumerate(parameters, -1):
1102            c = p.converter
1103
1104            if (i != -1) and (p.default is not unspecified):
1105                first_optional = min(first_optional, i)
1106
1107            # insert group variable
1108            group = p.group
1109            if last_group != group:
1110                last_group = group
1111                if group:
1112                    group_name = self.group_to_variable_name(group)
1113                    data.impl_arguments.append(group_name)
1114                    data.declarations.append("int " + group_name + " = 0;")
1115                    data.impl_parameters.append("int " + group_name)
1116                    has_option_groups = True
1117
1118            c.render(p, data)
1119
1120        if has_option_groups and (not positional):
1121            fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
1122
1123        # HACK
1124        # when we're METH_O, but have a custom return converter,
1125        # we use "impl_parameters" for the parsing function
1126        # because that works better.  but that means we must
1127        # suppress actually declaring the impl's parameters
1128        # as variables in the parsing function.  but since it's
1129        # METH_O, we have exactly one anyway, so we know exactly
1130        # where it is.
1131        if ("METH_O" in templates['methoddef_define'] and
1132            '{impl_parameters}' in templates['parser_prototype']):
1133            data.declarations.pop(0)
1134
1135        template_dict = {}
1136
1137        full_name = f.full_name
1138        template_dict['full_name'] = full_name
1139
1140        if new_or_init:
1141            name = f.cls.name
1142        else:
1143            name = f.name
1144
1145        template_dict['name'] = name
1146
1147        if f.c_basename:
1148            c_basename = f.c_basename
1149        else:
1150            fields = full_name.split(".")
1151            if fields[-1] == '__new__':
1152                fields.pop()
1153            c_basename = "_".join(fields)
1154
1155        template_dict['c_basename'] = c_basename
1156
1157        methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1158        template_dict['methoddef_name'] = methoddef_name
1159
1160        template_dict['docstring'] = self.docstring_for_c_string(f)
1161
1162        template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
1163        f_self.converter.set_template_dict(template_dict)
1164
1165        f.return_converter.render(f, data)
1166        template_dict['impl_return_type'] = f.return_converter.type
1167
1168        template_dict['declarations'] = format_escape("\n".join(data.declarations))
1169        template_dict['initializers'] = "\n\n".join(data.initializers)
1170        template_dict['modifications'] = '\n\n'.join(data.modifications)
1171        template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1172        template_dict['format_units'] = ''.join(data.format_units)
1173        template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1174        template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1175        template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
1176        template_dict['return_conversion'] = format_escape("".join(data.return_conversion).rstrip())
1177        template_dict['cleanup'] = format_escape("".join(data.cleanup))
1178        template_dict['return_value'] = data.return_value
1179
1180        # used by unpack tuple code generator
1181        ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1182        unpack_min = first_optional
1183        unpack_max = len(selfless)
1184        template_dict['unpack_min'] = str(unpack_min)
1185        template_dict['unpack_max'] = str(unpack_max)
1186
1187        if has_option_groups:
1188            self.render_option_group_parsing(f, template_dict)
1189
1190        # buffers, not destination
1191        for name, destination in clinic.destination_buffers.items():
1192            template = templates[name]
1193            if has_option_groups:
1194                template = linear_format(template,
1195                        option_group_parsing=template_dict['option_group_parsing'])
1196            template = linear_format(template,
1197                declarations=template_dict['declarations'],
1198                return_conversion=template_dict['return_conversion'],
1199                initializers=template_dict['initializers'],
1200                modifications=template_dict['modifications'],
1201                cleanup=template_dict['cleanup'],
1202                )
1203
1204            # Only generate the "exit:" label
1205            # if we have any gotos
1206            need_exit_label = "goto exit;" in template
1207            template = linear_format(template,
1208                exit_label="exit:" if need_exit_label else ''
1209                )
1210
1211            s = template.format_map(template_dict)
1212
1213            # mild hack:
1214            # reflow long impl declarations
1215            if name in {"impl_prototype", "impl_definition"}:
1216                s = wrap_declarations(s)
1217
1218            if clinic.line_prefix:
1219                s = indent_all_lines(s, clinic.line_prefix)
1220            if clinic.line_suffix:
1221                s = suffix_all_lines(s, clinic.line_suffix)
1222
1223            destination.append(s)
1224
1225        return clinic.get_destination('block').dump()
1226
1227
1228
1229
1230@contextlib.contextmanager
1231def OverrideStdioWith(stdout):
1232    saved_stdout = sys.stdout
1233    sys.stdout = stdout
1234    try:
1235        yield
1236    finally:
1237        assert sys.stdout is stdout
1238        sys.stdout = saved_stdout
1239
1240
1241def create_regex(before, after, word=True, whole_line=True):
1242    """Create an re object for matching marker lines."""
1243    group_re = r"\w+" if word else ".+"
1244    pattern = r'{}({}){}'
1245    if whole_line:
1246        pattern = '^' + pattern + '$'
1247    pattern = pattern.format(re.escape(before), group_re, re.escape(after))
1248    return re.compile(pattern)
1249
1250
1251class Block:
1252    r"""
1253    Represents a single block of text embedded in
1254    another file.  If dsl_name is None, the block represents
1255    verbatim text, raw original text from the file, in
1256    which case "input" will be the only non-false member.
1257    If dsl_name is not None, the block represents a Clinic
1258    block.
1259
1260    input is always str, with embedded \n characters.
1261    input represents the original text from the file;
1262    if it's a Clinic block, it is the original text with
1263    the body_prefix and redundant leading whitespace removed.
1264
1265    dsl_name is either str or None.  If str, it's the text
1266    found on the start line of the block between the square
1267    brackets.
1268
1269    signatures is either list or None.  If it's a list,
1270    it may only contain clinic.Module, clinic.Class, and
1271    clinic.Function objects.  At the moment it should
1272    contain at most one of each.
1273
1274    output is either str or None.  If str, it's the output
1275    from this block, with embedded '\n' characters.
1276
1277    indent is either str or None.  It's the leading whitespace
1278    that was found on every line of input.  (If body_prefix is
1279    not empty, this is the indent *after* removing the
1280    body_prefix.)
1281
1282    preindent is either str or None.  It's the whitespace that
1283    was found in front of every line of input *before* the
1284    "body_prefix" (see the Language object).  If body_prefix
1285    is empty, preindent must always be empty too.
1286
1287    To illustrate indent and preindent: Assume that '_'
1288    represents whitespace.  If the block processed was in a
1289    Python file, and looked like this:
1290      ____#/*[python]
1291      ____#__for a in range(20):
1292      ____#____print(a)
1293      ____#[python]*/
1294    "preindent" would be "____" and "indent" would be "__".
1295
1296    """
1297    def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1298        assert isinstance(input, str)
1299        self.input = input
1300        self.dsl_name = dsl_name
1301        self.signatures = signatures or []
1302        self.output = output
1303        self.indent = indent
1304        self.preindent = preindent
1305
1306    def __repr__(self):
1307        dsl_name = self.dsl_name or "text"
1308        def summarize(s):
1309            s = repr(s)
1310            if len(s) > 30:
1311                return s[:26] + "..." + s[0]
1312            return s
1313        return "".join((
1314            "<Block ", dsl_name, " input=", summarize(self.input), " output=", summarize(self.output), ">"))
1315
1316
1317class BlockParser:
1318    """
1319    Block-oriented parser for Argument Clinic.
1320    Iterator, yields Block objects.
1321    """
1322
1323    def __init__(self, input, language, *, verify=True):
1324        """
1325        "input" should be a str object
1326        with embedded \n characters.
1327
1328        "language" should be a Language object.
1329        """
1330        language.validate()
1331
1332        self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1333        self.block_start_line_number = self.line_number = 0
1334
1335        self.language = language
1336        before, _, after = language.start_line.partition('{dsl_name}')
1337        assert _ == '{dsl_name}'
1338        self.find_start_re = create_regex(before, after, whole_line=False)
1339        self.start_re = create_regex(before, after)
1340        self.verify = verify
1341        self.last_checksum_re = None
1342        self.last_dsl_name = None
1343        self.dsl_name = None
1344        self.first_block = True
1345
1346    def __iter__(self):
1347        return self
1348
1349    def __next__(self):
1350        while True:
1351            if not self.input:
1352                raise StopIteration
1353
1354            if self.dsl_name:
1355                return_value = self.parse_clinic_block(self.dsl_name)
1356                self.dsl_name = None
1357                self.first_block = False
1358                return return_value
1359            block = self.parse_verbatim_block()
1360            if self.first_block and not block.input:
1361                continue
1362            self.first_block = False
1363            return block
1364
1365
1366    def is_start_line(self, line):
1367        match = self.start_re.match(line.lstrip())
1368        return match.group(1) if match else None
1369
1370    def _line(self, lookahead=False):
1371        self.line_number += 1
1372        line = self.input.pop()
1373        if not lookahead:
1374            self.language.parse_line(line)
1375        return line
1376
1377    def parse_verbatim_block(self):
1378        add, output = text_accumulator()
1379        self.block_start_line_number = self.line_number
1380
1381        while self.input:
1382            line = self._line()
1383            dsl_name = self.is_start_line(line)
1384            if dsl_name:
1385                self.dsl_name = dsl_name
1386                break
1387            add(line)
1388
1389        return Block(output())
1390
1391    def parse_clinic_block(self, dsl_name):
1392        input_add, input_output = text_accumulator()
1393        self.block_start_line_number = self.line_number + 1
1394        stop_line = self.language.stop_line.format(dsl_name=dsl_name)
1395        body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1396
1397        def is_stop_line(line):
1398            # make sure to recognize stop line even if it
1399            # doesn't end with EOL (it could be the very end of the file)
1400            if not line.startswith(stop_line):
1401                return False
1402            remainder = line[len(stop_line):]
1403            return (not remainder) or remainder.isspace()
1404
1405        # consume body of program
1406        while self.input:
1407            line = self._line()
1408            if is_stop_line(line) or self.is_start_line(line):
1409                break
1410            if body_prefix:
1411                line = line.lstrip()
1412                assert line.startswith(body_prefix)
1413                line = line[len(body_prefix):]
1414            input_add(line)
1415
1416        # consume output and checksum line, if present.
1417        if self.last_dsl_name == dsl_name:
1418            checksum_re = self.last_checksum_re
1419        else:
1420            before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, arguments='{arguments}').partition('{arguments}')
1421            assert _ == '{arguments}'
1422            checksum_re = create_regex(before, after, word=False)
1423            self.last_dsl_name = dsl_name
1424            self.last_checksum_re = checksum_re
1425
1426        # scan forward for checksum line
1427        output_add, output_output = text_accumulator()
1428        arguments = None
1429        while self.input:
1430            line = self._line(lookahead=True)
1431            match = checksum_re.match(line.lstrip())
1432            arguments = match.group(1) if match else None
1433            if arguments:
1434                break
1435            output_add(line)
1436            if self.is_start_line(line):
1437                break
1438
1439        output = output_output()
1440        if arguments:
1441            d = {}
1442            for field in shlex.split(arguments):
1443                name, equals, value = field.partition('=')
1444                if not equals:
1445                    fail("Mangled Argument Clinic marker line: {!r}".format(line))
1446                d[name.strip()] = value.strip()
1447
1448            if self.verify:
1449                if 'input' in d:
1450                    checksum = d['output']
1451                    input_checksum = d['input']
1452                else:
1453                    checksum = d['checksum']
1454                    input_checksum = None
1455
1456                computed = compute_checksum(output, len(checksum))
1457                if checksum != computed:
1458                    fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1459                         "Suggested fix: remove all generated code including "
1460                         "the end marker,\n"
1461                         "or use the '-f' option."
1462                        .format(checksum, computed))
1463        else:
1464            # put back output
1465            output_lines = output.splitlines(keepends=True)
1466            self.line_number -= len(output_lines)
1467            self.input.extend(reversed(output_lines))
1468            output = None
1469
1470        return Block(input_output(), dsl_name, output=output)
1471
1472
1473class BlockPrinter:
1474
1475    def __init__(self, language, f=None):
1476        self.language = language
1477        self.f = f or io.StringIO()
1478
1479    def print_block(self, block):
1480        input = block.input
1481        output = block.output
1482        dsl_name = block.dsl_name
1483        write = self.f.write
1484
1485        assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1486
1487        if not dsl_name:
1488            write(input)
1489            return
1490
1491        write(self.language.start_line.format(dsl_name=dsl_name))
1492        write("\n")
1493
1494        body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1495        if not body_prefix:
1496            write(input)
1497        else:
1498            for line in input.split('\n'):
1499                write(body_prefix)
1500                write(line)
1501                write("\n")
1502
1503        write(self.language.stop_line.format(dsl_name=dsl_name))
1504        write("\n")
1505
1506        input = ''.join(block.input)
1507        output = ''.join(block.output)
1508        if output:
1509            if not output.endswith('\n'):
1510                output += '\n'
1511            write(output)
1512
1513        arguments="output={} input={}".format(compute_checksum(output, 16), compute_checksum(input, 16))
1514        write(self.language.checksum_line.format(dsl_name=dsl_name, arguments=arguments))
1515        write("\n")
1516
1517    def write(self, text):
1518        self.f.write(text)
1519
1520
1521class BufferSeries:
1522    """
1523    Behaves like a "defaultlist".
1524    When you ask for an index that doesn't exist yet,
1525    the object grows the list until that item exists.
1526    So o[n] will always work.
1527
1528    Supports negative indices for actual items.
1529    e.g. o[-1] is an element immediately preceding o[0].
1530    """
1531
1532    def __init__(self):
1533        self._start = 0
1534        self._array = []
1535        self._constructor = _text_accumulator
1536
1537    def __getitem__(self, i):
1538        i -= self._start
1539        if i < 0:
1540            self._start += i
1541            prefix = [self._constructor() for x in range(-i)]
1542            self._array = prefix + self._array
1543            i = 0
1544        while i >= len(self._array):
1545            self._array.append(self._constructor())
1546        return self._array[i]
1547
1548    def clear(self):
1549        for ta in self._array:
1550            ta._text.clear()
1551
1552    def dump(self):
1553        texts = [ta.output() for ta in self._array]
1554        return "".join(texts)
1555
1556
1557class Destination:
1558    def __init__(self, name, type, clinic, *args):
1559        self.name = name
1560        self.type = type
1561        self.clinic = clinic
1562        valid_types = ('buffer', 'file', 'suppress')
1563        if type not in valid_types:
1564            fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1565        extra_arguments = 1 if type == "file" else 0
1566        if len(args) < extra_arguments:
1567            fail("Not enough arguments for destination " + name + " new " + type)
1568        if len(args) > extra_arguments:
1569            fail("Too many arguments for destination " + name + " new " + type)
1570        if type =='file':
1571            d = {}
1572            filename = clinic.filename
1573            d['path'] = filename
1574            dirname, basename = os.path.split(filename)
1575            if not dirname:
1576                dirname = '.'
1577            d['dirname'] = dirname
1578            d['basename'] = basename
1579            d['basename_root'], d['basename_extension'] = os.path.splitext(filename)
1580            self.filename = args[0].format_map(d)
1581
1582        self.buffers = BufferSeries()
1583
1584    def __repr__(self):
1585        if self.type == 'file':
1586            file_repr = " " + repr(self.filename)
1587        else:
1588            file_repr = ''
1589        return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1590
1591    def clear(self):
1592        if self.type != 'buffer':
1593            fail("Can't clear destination" + self.name + " , it's not of type buffer")
1594        self.buffers.clear()
1595
1596    def dump(self):
1597        return self.buffers.dump()
1598
1599
1600# maps strings to Language objects.
1601# "languages" maps the name of the language ("C", "Python").
1602# "extensions" maps the file extension ("c", "py").
1603languages = { 'C': CLanguage, 'Python': PythonLanguage }
1604extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1605extensions['py'] = PythonLanguage
1606
1607
1608# maps strings to callables.
1609# these callables must be of the form:
1610#   def foo(name, default, *, ...)
1611# The callable may have any number of keyword-only parameters.
1612# The callable must return a CConverter object.
1613# The callable should not call builtins.print.
1614converters = {}
1615
1616# maps strings to callables.
1617# these callables follow the same rules as those for "converters" above.
1618# note however that they will never be called with keyword-only parameters.
1619legacy_converters = {}
1620
1621
1622# maps strings to callables.
1623# these callables must be of the form:
1624#   def foo(*, ...)
1625# The callable may have any number of keyword-only parameters.
1626# The callable must return a CConverter object.
1627# The callable should not call builtins.print.
1628return_converters = {}
1629
1630clinic = None
1631class Clinic:
1632
1633    presets_text = """
1634preset block
1635everything block
1636methoddef_ifndef buffer 1
1637docstring_prototype suppress
1638parser_prototype suppress
1639cpp_if suppress
1640cpp_endif suppress
1641
1642preset original
1643everything block
1644methoddef_ifndef buffer 1
1645docstring_prototype suppress
1646parser_prototype suppress
1647cpp_if suppress
1648cpp_endif suppress
1649
1650preset file
1651everything file
1652methoddef_ifndef file 1
1653docstring_prototype suppress
1654parser_prototype suppress
1655impl_definition block
1656
1657preset buffer
1658everything buffer
1659methoddef_ifndef buffer 1
1660impl_definition block
1661docstring_prototype suppress
1662impl_prototype suppress
1663parser_prototype suppress
1664
1665preset partial-buffer
1666everything buffer
1667methoddef_ifndef buffer 1
1668docstring_prototype block
1669impl_prototype suppress
1670methoddef_define block
1671parser_prototype block
1672impl_definition block
1673
1674"""
1675
1676    def __init__(self, language, printer=None, *, force=False, verify=True, filename=None):
1677        # maps strings to Parser objects.
1678        # (instantiated from the "parsers" global.)
1679        self.parsers = {}
1680        self.language = language
1681        if printer:
1682            fail("Custom printers are broken right now")
1683        self.printer = printer or BlockPrinter(language)
1684        self.verify = verify
1685        self.force = force
1686        self.filename = filename
1687        self.modules = collections.OrderedDict()
1688        self.classes = collections.OrderedDict()
1689        self.functions = []
1690
1691        self.line_prefix = self.line_suffix = ''
1692
1693        self.destinations = {}
1694        self.add_destination("block", "buffer")
1695        self.add_destination("suppress", "suppress")
1696        self.add_destination("buffer", "buffer")
1697        if filename:
1698            self.add_destination("file", "file", "{dirname}/clinic/{basename}.h")
1699
1700        d = self.get_destination_buffer
1701        self.destination_buffers = collections.OrderedDict((
1702            ('cpp_if', d('file')),
1703            ('docstring_prototype', d('suppress')),
1704            ('docstring_definition', d('file')),
1705            ('methoddef_define', d('file')),
1706            ('impl_prototype', d('file')),
1707            ('parser_prototype', d('suppress')),
1708            ('parser_definition', d('file')),
1709            ('cpp_endif', d('file')),
1710            ('methoddef_ifndef', d('file', 1)),
1711            ('impl_definition', d('block')),
1712        ))
1713
1714        self.destination_buffers_stack = []
1715        self.ifndef_symbols = set()
1716
1717        self.presets = {}
1718        preset = None
1719        for line in self.presets_text.strip().split('\n'):
1720            line = line.strip()
1721            if not line:
1722                continue
1723            name, value, *options = line.split()
1724            if name == 'preset':
1725                self.presets[value] = preset = collections.OrderedDict()
1726                continue
1727
1728            if len(options):
1729                index = int(options[0])
1730            else:
1731                index = 0
1732            buffer = self.get_destination_buffer(value, index)
1733
1734            if name == 'everything':
1735                for name in self.destination_buffers:
1736                    preset[name] = buffer
1737                continue
1738
1739            assert name in self.destination_buffers
1740            preset[name] = buffer
1741
1742        global clinic
1743        clinic = self
1744
1745    def add_destination(self, name, type, *args):
1746        if name in self.destinations:
1747            fail("Destination already exists: " + repr(name))
1748        self.destinations[name] = Destination(name, type, self, *args)
1749
1750    def get_destination(self, name):
1751        d = self.destinations.get(name)
1752        if not d:
1753            fail("Destination does not exist: " + repr(name))
1754        return d
1755
1756    def get_destination_buffer(self, name, item=0):
1757        d = self.get_destination(name)
1758        return d.buffers[item]
1759
1760    def parse(self, input):
1761        printer = self.printer
1762        self.block_parser = BlockParser(input, self.language, verify=self.verify)
1763        for block in self.block_parser:
1764            dsl_name = block.dsl_name
1765            if dsl_name:
1766                if dsl_name not in self.parsers:
1767                    assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1768                    self.parsers[dsl_name] = parsers[dsl_name](self)
1769                parser = self.parsers[dsl_name]
1770                try:
1771                    parser.parse(block)
1772                except Exception:
1773                    fail('Exception raised during parsing:\n' +
1774                         traceback.format_exc().rstrip())
1775            printer.print_block(block)
1776
1777        second_pass_replacements = {}
1778
1779        # these are destinations not buffers
1780        for name, destination in self.destinations.items():
1781            if destination.type == 'suppress':
1782                continue
1783            output = destination.dump()
1784
1785            if output:
1786
1787                block = Block("", dsl_name="clinic", output=output)
1788
1789                if destination.type == 'buffer':
1790                    block.input = "dump " + name + "\n"
1791                    warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1792                    printer.write("\n")
1793                    printer.print_block(block)
1794                    continue
1795
1796                if destination.type == 'file':
1797                    try:
1798                        dirname = os.path.dirname(destination.filename)
1799                        try:
1800                            os.makedirs(dirname)
1801                        except FileExistsError:
1802                            if not os.path.isdir(dirname):
1803                                fail("Can't write to destination {}, "
1804                                     "can't make directory {}!".format(
1805                                        destination.filename, dirname))
1806                        if self.verify:
1807                            with open(destination.filename, "rt") as f:
1808                                parser_2 = BlockParser(f.read(), language=self.language)
1809                                blocks = list(parser_2)
1810                                if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1811                                    fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
1812                    except FileNotFoundError:
1813                        pass
1814
1815                    block.input = 'preserve\n'
1816                    printer_2 = BlockPrinter(self.language)
1817                    printer_2.print_block(block)
1818                    with open(destination.filename, "wt") as f:
1819                        f.write(printer_2.f.getvalue())
1820                    continue
1821        text = printer.f.getvalue()
1822
1823        if second_pass_replacements:
1824            printer_2 = BlockPrinter(self.language)
1825            parser_2 = BlockParser(text, self.language)
1826            changed = False
1827            for block in parser_2:
1828                if block.dsl_name:
1829                    for id, replacement in second_pass_replacements.items():
1830                        if id in block.output:
1831                            changed = True
1832                            block.output = block.output.replace(id, replacement)
1833                printer_2.print_block(block)
1834            if changed:
1835                text = printer_2.f.getvalue()
1836
1837        return text
1838
1839
1840    def _module_and_class(self, fields):
1841        """
1842        fields should be an iterable of field names.
1843        returns a tuple of (module, class).
1844        the module object could actually be self (a clinic object).
1845        this function is only ever used to find the parent of where
1846        a new class/module should go.
1847        """
1848        in_classes = False
1849        parent = module = self
1850        cls = None
1851        so_far = []
1852
1853        for field in fields:
1854            so_far.append(field)
1855            if not in_classes:
1856                child = parent.modules.get(field)
1857                if child:
1858                    parent = module = child
1859                    continue
1860                in_classes = True
1861            if not hasattr(parent, 'classes'):
1862                return module, cls
1863            child = parent.classes.get(field)
1864            if not child:
1865                fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1866            cls = parent = child
1867
1868        return module, cls
1869
1870
1871def parse_file(filename, *, force=False, verify=True, output=None, encoding='utf-8'):
1872    extension = os.path.splitext(filename)[1][1:]
1873    if not extension:
1874        fail("Can't extract file type for file " + repr(filename))
1875
1876    try:
1877        language = extensions[extension](filename)
1878    except KeyError:
1879        fail("Can't identify file type for file " + repr(filename))
1880
1881    with open(filename, 'r', encoding=encoding) as f:
1882        raw = f.read()
1883
1884    # exit quickly if there are no clinic markers in the file
1885    find_start_re = BlockParser("", language).find_start_re
1886    if not find_start_re.search(raw):
1887        return
1888
1889    clinic = Clinic(language, force=force, verify=verify, filename=filename)
1890    cooked = clinic.parse(raw)
1891    if (cooked == raw) and not force:
1892        return
1893
1894    directory = os.path.dirname(filename) or '.'
1895
1896    with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
1897        bytes = cooked.encode(encoding)
1898        tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1899        with open(tmpfilename, "wb") as f:
1900            f.write(bytes)
1901        os.replace(tmpfilename, output or filename)
1902
1903
1904def compute_checksum(input, length=None):
1905    input = input or ''
1906    s = hashlib.sha1(input.encode('utf-8')).hexdigest()
1907    if length:
1908        s = s[:length]
1909    return s
1910
1911
1912
1913
1914class PythonParser:
1915    def __init__(self, clinic):
1916        pass
1917
1918    def parse(self, block):
1919        s = io.StringIO()
1920        with OverrideStdioWith(s):
1921            exec(block.input)
1922        block.output = s.getvalue()
1923
1924
1925class Module:
1926    def __init__(self, name, module=None):
1927        self.name = name
1928        self.module = self.parent = module
1929
1930        self.modules = collections.OrderedDict()
1931        self.classes = collections.OrderedDict()
1932        self.functions = []
1933
1934    def __repr__(self):
1935        return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1936
1937class Class:
1938    def __init__(self, name, module=None, cls=None, typedef=None, type_object=None):
1939        self.name = name
1940        self.module = module
1941        self.cls = cls
1942        self.typedef = typedef
1943        self.type_object = type_object
1944        self.parent = cls or module
1945
1946        self.classes = collections.OrderedDict()
1947        self.functions = []
1948
1949    def __repr__(self):
1950        return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1951
1952unsupported_special_methods = set("""
1953
1954__abs__
1955__add__
1956__and__
1957__bytes__
1958__call__
1959__complex__
1960__delitem__
1961__divmod__
1962__eq__
1963__float__
1964__floordiv__
1965__ge__
1966__getattr__
1967__getattribute__
1968__getitem__
1969__gt__
1970__hash__
1971__iadd__
1972__iand__
1973__ifloordiv__
1974__ilshift__
1975__imatmul__
1976__imod__
1977__imul__
1978__index__
1979__int__
1980__invert__
1981__ior__
1982__ipow__
1983__irshift__
1984__isub__
1985__iter__
1986__itruediv__
1987__ixor__
1988__le__
1989__len__
1990__lshift__
1991__lt__
1992__matmul__
1993__mod__
1994__mul__
1995__neg__
1996__new__
1997__next__
1998__or__
1999__pos__
2000__pow__
2001__radd__
2002__rand__
2003__rdivmod__
2004__repr__
2005__rfloordiv__
2006__rlshift__
2007__rmatmul__
2008__rmod__
2009__rmul__
2010__ror__
2011__round__
2012__rpow__
2013__rrshift__
2014__rshift__
2015__rsub__
2016__rtruediv__
2017__rxor__
2018__setattr__
2019__setitem__
2020__str__
2021__sub__
2022__truediv__
2023__xor__
2024
2025""".strip().split())
2026
2027
2028INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
2029INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
2030""".replace(",", "").strip().split()
2031
2032class Function:
2033    """
2034    Mutable duck type for inspect.Function.
2035
2036    docstring - a str containing
2037        * embedded line breaks
2038        * text outdented to the left margin
2039        * no trailing whitespace.
2040        It will always be true that
2041            (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
2042    """
2043
2044    def __init__(self, parameters=None, *, name,
2045                 module, cls=None, c_basename=None,
2046                 full_name=None,
2047                 return_converter, return_annotation=_empty,
2048                 docstring=None, kind=CALLABLE, coexist=False,
2049                 docstring_only=False):
2050        self.parameters = parameters or collections.OrderedDict()
2051        self.return_annotation = return_annotation
2052        self.name = name
2053        self.full_name = full_name
2054        self.module = module
2055        self.cls = cls
2056        self.parent = cls or module
2057        self.c_basename = c_basename
2058        self.return_converter = return_converter
2059        self.docstring = docstring or ''
2060        self.kind = kind
2061        self.coexist = coexist
2062        self.self_converter = None
2063        # docstring_only means "don't generate a machine-readable
2064        # signature, just a normal docstring".  it's True for
2065        # functions with optional groups because we can't represent
2066        # those accurately with inspect.Signature in 3.4.
2067        self.docstring_only = docstring_only
2068
2069        self.rendered_parameters = None
2070
2071    __render_parameters__ = None
2072    @property
2073    def render_parameters(self):
2074        if not self.__render_parameters__:
2075            self.__render_parameters__ = l = []
2076            for p in self.parameters.values():
2077                p = p.copy()
2078                p.converter.pre_render()
2079                l.append(p)
2080        return self.__render_parameters__
2081
2082    @property
2083    def methoddef_flags(self):
2084        if self.kind in (METHOD_INIT, METHOD_NEW):
2085            return None
2086        flags = []
2087        if self.kind == CLASS_METHOD:
2088            flags.append('METH_CLASS')
2089        elif self.kind == STATIC_METHOD:
2090            flags.append('METH_STATIC')
2091        else:
2092            assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
2093        if self.coexist:
2094            flags.append('METH_COEXIST')
2095        return '|'.join(flags)
2096
2097    def __repr__(self):
2098        return '<clinic.Function ' + self.name + '>'
2099
2100    def copy(self, **overrides):
2101        kwargs = {
2102            'name': self.name, 'module': self.module, 'parameters': self.parameters,
2103            'cls': self.cls, 'c_basename': self.c_basename,
2104            'full_name': self.full_name,
2105            'return_converter': self.return_converter, 'return_annotation': self.return_annotation,
2106            'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist,
2107            'docstring_only': self.docstring_only,
2108            }
2109        kwargs.update(overrides)
2110        f = Function(**kwargs)
2111
2112        parameters = collections.OrderedDict()
2113        for name, value in f.parameters.items():
2114            value = value.copy(function=f)
2115            parameters[name] = value
2116        f.parameters = parameters
2117        return f
2118
2119
2120class Parameter:
2121    """
2122    Mutable duck type of inspect.Parameter.
2123    """
2124
2125    def __init__(self, name, kind, *, default=_empty,
2126                 function, converter, annotation=_empty,
2127                 docstring=None, group=0):
2128        self.name = name
2129        self.kind = kind
2130        self.default = default
2131        self.function = function
2132        self.converter = converter
2133        self.annotation = annotation
2134        self.docstring = docstring or ''
2135        self.group = group
2136
2137    def __repr__(self):
2138        return '<clinic.Parameter ' + self.name + '>'
2139
2140    def is_keyword_only(self):
2141        return self.kind == inspect.Parameter.KEYWORD_ONLY
2142
2143    def is_positional_only(self):
2144        return self.kind == inspect.Parameter.POSITIONAL_ONLY
2145
2146    def copy(self, **overrides):
2147        kwargs = {
2148            'name': self.name, 'kind': self.kind, 'default':self.default,
2149                 'function': self.function, 'converter': self.converter, 'annotation': self.annotation,
2150                 'docstring': self.docstring, 'group': self.group,
2151            }
2152        kwargs.update(overrides)
2153        if 'converter' not in overrides:
2154            converter = copy.copy(self.converter)
2155            converter.function = kwargs['function']
2156            kwargs['converter'] = converter
2157        return Parameter(**kwargs)
2158
2159
2160
2161class LandMine:
2162    # try to access any
2163    def __init__(self, message):
2164        self.__message__ = message
2165
2166    def __repr__(self):
2167        return '<LandMine ' + repr(self.__message__) + ">"
2168
2169    def __getattribute__(self, name):
2170        if name in ('__repr__', '__message__'):
2171            return super().__getattribute__(name)
2172        # raise RuntimeError(repr(name))
2173        fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__)
2174
2175
2176def add_c_converter(f, name=None):
2177    if not name:
2178        name = f.__name__
2179        if not name.endswith('_converter'):
2180            return f
2181        name = name[:-len('_converter')]
2182    converters[name] = f
2183    return f
2184
2185def add_default_legacy_c_converter(cls):
2186    # automatically add converter for default format unit
2187    # (but without stomping on the existing one if it's already
2188    # set, in case you subclass)
2189    if ((cls.format_unit not in ('O&', '')) and
2190        (cls.format_unit not in legacy_converters)):
2191        legacy_converters[cls.format_unit] = cls
2192    return cls
2193
2194def add_legacy_c_converter(format_unit, **kwargs):
2195    """
2196    Adds a legacy converter.
2197    """
2198    def closure(f):
2199        if not kwargs:
2200            added_f = f
2201        else:
2202            added_f = functools.partial(f, **kwargs)
2203        if format_unit:
2204            legacy_converters[format_unit] = added_f
2205        return f
2206    return closure
2207
2208class CConverterAutoRegister(type):
2209    def __init__(cls, name, bases, classdict):
2210        add_c_converter(cls)
2211        add_default_legacy_c_converter(cls)
2212
2213class CConverter(metaclass=CConverterAutoRegister):
2214    """
2215    For the init function, self, name, function, and default
2216    must be keyword-or-positional parameters.  All other
2217    parameters must be keyword-only.
2218    """
2219
2220    # The C name to use for this variable.
2221    name = None
2222
2223    # The Python name to use for this variable.
2224    py_name = None
2225
2226    # The C type to use for this variable.
2227    # 'type' should be a Python string specifying the type, e.g. "int".
2228    # If this is a pointer type, the type string should end with ' *'.
2229    type = None
2230
2231    # The Python default value for this parameter, as a Python value.
2232    # Or the magic value "unspecified" if there is no default.
2233    # Or the magic value "unknown" if this value is a cannot be evaluated
2234    # at Argument-Clinic-preprocessing time (but is presumed to be valid
2235    # at runtime).
2236    default = unspecified
2237
2238    # If not None, default must be isinstance() of this type.
2239    # (You can also specify a tuple of types.)
2240    default_type = None
2241
2242    # "default" converted into a C value, as a string.
2243    # Or None if there is no default.
2244    c_default = None
2245
2246    # "default" converted into a Python value, as a string.
2247    # Or None if there is no default.
2248    py_default = None
2249
2250    # The default value used to initialize the C variable when
2251    # there is no default, but not specifying a default may
2252    # result in an "uninitialized variable" warning.  This can
2253    # easily happen when using option groups--although
2254    # properly-written code won't actually use the variable,
2255    # the variable does get passed in to the _impl.  (Ah, if
2256    # only dataflow analysis could inline the static function!)
2257    #
2258    # This value is specified as a string.
2259    # Every non-abstract subclass should supply a valid value.
2260    c_ignored_default = 'NULL'
2261
2262    # The C converter *function* to be used, if any.
2263    # (If this is not None, format_unit must be 'O&'.)
2264    converter = None
2265
2266    # Should Argument Clinic add a '&' before the name of
2267    # the variable when passing it into the _impl function?
2268    impl_by_reference = False
2269
2270    # Should Argument Clinic add a '&' before the name of
2271    # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
2272    parse_by_reference = True
2273
2274    #############################################################
2275    #############################################################
2276    ## You shouldn't need to read anything below this point to ##
2277    ## write your own converter functions.                     ##
2278    #############################################################
2279    #############################################################
2280
2281    # The "format unit" to specify for this variable when
2282    # parsing arguments using PyArg_ParseTuple (AndKeywords).
2283    # Custom converters should always use the default value of 'O&'.
2284    format_unit = 'O&'
2285
2286    # What encoding do we want for this variable?  Only used
2287    # by format units starting with 'e'.
2288    encoding = None
2289
2290    # Should this object be required to be a subclass of a specific type?
2291    # If not None, should be a string representing a pointer to a
2292    # PyTypeObject (e.g. "&PyUnicode_Type").
2293    # Only used by the 'O!' format unit (and the "object" converter).
2294    subclass_of = None
2295
2296    # Do we want an adjacent '_length' variable for this variable?
2297    # Only used by format units ending with '#'.
2298    length = False
2299
2300    # Should we show this parameter in the generated
2301    # __text_signature__? This is *almost* always True.
2302    # (It's only False for __new__, __init__, and METH_STATIC functions.)
2303    show_in_signature = True
2304
2305    # Overrides the name used in a text signature.
2306    # The name used for a "self" parameter must be one of
2307    # self, type, or module; however users can set their own.
2308    # This lets the self_converter overrule the user-settable
2309    # name, *just* for the text signature.
2310    # Only set by self_converter.
2311    signature_name = None
2312
2313    # keep in sync with self_converter.__init__!
2314    def __init__(self, name, py_name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs):
2315        self.name = name
2316        self.py_name = py_name
2317
2318        if default is not unspecified:
2319            if self.default_type and not isinstance(default, (self.default_type, Unknown)):
2320                if isinstance(self.default_type, type):
2321                    types_str = self.default_type.__name__
2322                else:
2323                    types_str = ', '.join((cls.__name__ for cls in self.default_type))
2324                fail("{}: default value {!r} for field {} is not of type {}".format(
2325                    self.__class__.__name__, default, name, types_str))
2326            self.default = default
2327
2328        if c_default:
2329            self.c_default = c_default
2330        if py_default:
2331            self.py_default = py_default
2332
2333        if annotation != unspecified:
2334            fail("The 'annotation' parameter is not currently permitted.")
2335
2336        # this is deliberate, to prevent you from caching information
2337        # about the function in the init.
2338        # (that breaks if we get cloned.)
2339        # so after this change we will noisily fail.
2340        self.function = LandMine("Don't access members of self.function inside converter_init!")
2341        self.converter_init(**kwargs)
2342        self.function = function
2343
2344    def converter_init(self):
2345        pass
2346
2347    def is_optional(self):
2348        return (self.default is not unspecified)
2349
2350    def _render_self(self, parameter, data):
2351        self.parameter = parameter
2352        original_name = self.name
2353        name = ensure_legal_c_identifier(original_name)
2354
2355        # impl_arguments
2356        s = ("&" if self.impl_by_reference else "") + name
2357        data.impl_arguments.append(s)
2358        if self.length:
2359            data.impl_arguments.append(self.length_name())
2360
2361        # impl_parameters
2362        data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2363        if self.length:
2364            data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2365
2366    def _render_non_self(self, parameter, data):
2367        self.parameter = parameter
2368        original_name = self.name
2369        name = ensure_legal_c_identifier(original_name)
2370
2371        # declarations
2372        d = self.declaration()
2373        data.declarations.append(d)
2374
2375        # initializers
2376        initializers = self.initialize()
2377        if initializers:
2378            data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2379
2380        # modifications
2381        modifications = self.modify()
2382        if modifications:
2383            data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2384
2385        # keywords
2386        if parameter.is_positional_only():
2387            data.keywords.append('')
2388        else:
2389            data.keywords.append(parameter.name)
2390
2391        # format_units
2392        if self.is_optional() and '|' not in data.format_units:
2393            data.format_units.append('|')
2394        if parameter.is_keyword_only() and '$' not in data.format_units:
2395            data.format_units.append('$')
2396        data.format_units.append(self.format_unit)
2397
2398        # parse_arguments
2399        self.parse_argument(data.parse_arguments)
2400
2401        # cleanup
2402        cleanup = self.cleanup()
2403        if cleanup:
2404            data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2405
2406    def render(self, parameter, data):
2407        """
2408        parameter is a clinic.Parameter instance.
2409        data is a CRenderData instance.
2410        """
2411        self._render_self(parameter, data)
2412        self._render_non_self(parameter, data)
2413
2414    def length_name(self):
2415        """Computes the name of the associated "length" variable."""
2416        if not self.length:
2417            return None
2418        return ensure_legal_c_identifier(self.name) + "_length"
2419
2420    # Why is this one broken out separately?
2421    # For "positional-only" function parsing,
2422    # which generates a bunch of PyArg_ParseTuple calls.
2423    def parse_argument(self, list):
2424        assert not (self.converter and self.encoding)
2425        if self.format_unit == 'O&':
2426            assert self.converter
2427            list.append(self.converter)
2428
2429        if self.encoding:
2430            list.append(c_repr(self.encoding))
2431        elif self.subclass_of:
2432            list.append(self.subclass_of)
2433
2434        legal_name = ensure_legal_c_identifier(self.name)
2435        s = ("&" if self.parse_by_reference else "") + legal_name
2436        list.append(s)
2437
2438        if self.length:
2439            list.append("&" + self.length_name())
2440
2441    #
2442    # All the functions after here are intended as extension points.
2443    #
2444
2445    def simple_declaration(self, by_reference=False):
2446        """
2447        Computes the basic declaration of the variable.
2448        Used in computing the prototype declaration and the
2449        variable declaration.
2450        """
2451        prototype = [self.type]
2452        if by_reference or not self.type.endswith('*'):
2453            prototype.append(" ")
2454        if by_reference:
2455            prototype.append('*')
2456        prototype.append(ensure_legal_c_identifier(self.name))
2457        return "".join(prototype)
2458
2459    def declaration(self):
2460        """
2461        The C statement to declare this variable.
2462        """
2463        declaration = [self.simple_declaration()]
2464        default = self.c_default
2465        if not default and self.parameter.group:
2466            default = self.c_ignored_default
2467        if default:
2468            declaration.append(" = ")
2469            declaration.append(default)
2470        declaration.append(";")
2471        if self.length:
2472            declaration.append('\nPy_ssize_clean_t ')
2473            declaration.append(self.length_name())
2474            declaration.append(';')
2475        return "".join(declaration)
2476
2477    def initialize(self):
2478        """
2479        The C statements required to set up this variable before parsing.
2480        Returns a string containing this code indented at column 0.
2481        If no initialization is necessary, returns an empty string.
2482        """
2483        return ""
2484
2485    def modify(self):
2486        """
2487        The C statements required to modify this variable after parsing.
2488        Returns a string containing this code indented at column 0.
2489        If no initialization is necessary, returns an empty string.
2490        """
2491        return ""
2492
2493    def cleanup(self):
2494        """
2495        The C statements required to clean up after this variable.
2496        Returns a string containing this code indented at column 0.
2497        If no cleanup is necessary, returns an empty string.
2498        """
2499        return ""
2500
2501    def pre_render(self):
2502        """
2503        A second initialization function, like converter_init,
2504        called just before rendering.
2505        You are permitted to examine self.function here.
2506        """
2507        pass
2508
2509
2510class bool_converter(CConverter):
2511    type = 'int'
2512    default_type = bool
2513    format_unit = 'p'
2514    c_ignored_default = '0'
2515
2516    def converter_init(self):
2517        if self.default is not unspecified:
2518            self.default = bool(self.default)
2519            self.c_default = str(int(self.default))
2520
2521class char_converter(CConverter):
2522    type = 'char'
2523    default_type = (bytes, bytearray)
2524    format_unit = 'c'
2525    c_ignored_default = "'\0'"
2526
2527    def converter_init(self):
2528        if isinstance(self.default, self.default_type) and (len(self.default) != 1):
2529            fail("char_converter: illegal default value " + repr(self.default))
2530
2531
2532@add_legacy_c_converter('B', bitwise=True)
2533class unsigned_char_converter(CConverter):
2534    type = 'unsigned char'
2535    default_type = int
2536    format_unit = 'b'
2537    c_ignored_default = "'\0'"
2538
2539    def converter_init(self, *, bitwise=False):
2540        if bitwise:
2541            self.format_unit = 'B'
2542
2543class byte_converter(unsigned_char_converter): pass
2544
2545class short_converter(CConverter):
2546    type = 'short'
2547    default_type = int
2548    format_unit = 'h'
2549    c_ignored_default = "0"
2550
2551class unsigned_short_converter(CConverter):
2552    type = 'unsigned short'
2553    default_type = int
2554    format_unit = 'H'
2555    c_ignored_default = "0"
2556
2557    def converter_init(self, *, bitwise=False):
2558        if not bitwise:
2559            fail("Unsigned shorts must be bitwise (for now).")
2560
2561@add_legacy_c_converter('C', accept={str})
2562class int_converter(CConverter):
2563    type = 'int'
2564    default_type = int
2565    format_unit = 'i'
2566    c_ignored_default = "0"
2567
2568    def converter_init(self, *, accept={int}, type=None):
2569        if accept == {str}:
2570            self.format_unit = 'C'
2571        elif accept != {int}:
2572            fail("int_converter: illegal 'accept' argument " + repr(accept))
2573        if type != None:
2574            self.type = type
2575
2576class unsigned_int_converter(CConverter):
2577    type = 'unsigned int'
2578    default_type = int
2579    format_unit = 'I'
2580    c_ignored_default = "0"
2581
2582    def converter_init(self, *, bitwise=False):
2583        if not bitwise:
2584            fail("Unsigned ints must be bitwise (for now).")
2585
2586class long_converter(CConverter):
2587    type = 'long'
2588    default_type = int
2589    format_unit = 'l'
2590    c_ignored_default = "0"
2591
2592class unsigned_long_converter(CConverter):
2593    type = 'unsigned long'
2594    default_type = int
2595    format_unit = 'k'
2596    c_ignored_default = "0"
2597
2598    def converter_init(self, *, bitwise=False):
2599        if not bitwise:
2600            fail("Unsigned longs must be bitwise (for now).")
2601
2602class long_long_converter(CConverter):
2603    type = 'long long'
2604    default_type = int
2605    format_unit = 'L'
2606    c_ignored_default = "0"
2607
2608class unsigned_long_long_converter(CConverter):
2609    type = 'unsigned long long'
2610    default_type = int
2611    format_unit = 'K'
2612    c_ignored_default = "0"
2613
2614    def converter_init(self, *, bitwise=False):
2615        if not bitwise:
2616            fail("Unsigned long long must be bitwise (for now).")
2617
2618class Py_ssize_t_converter(CConverter):
2619    type = 'Py_ssize_t'
2620    default_type = int
2621    format_unit = 'n'
2622    c_ignored_default = "0"
2623
2624
2625class float_converter(CConverter):
2626    type = 'float'
2627    default_type = float
2628    format_unit = 'f'
2629    c_ignored_default = "0.0"
2630
2631class double_converter(CConverter):
2632    type = 'double'
2633    default_type = float
2634    format_unit = 'd'
2635    c_ignored_default = "0.0"
2636
2637
2638class Py_complex_converter(CConverter):
2639    type = 'Py_complex'
2640    default_type = complex
2641    format_unit = 'D'
2642    c_ignored_default = "{0.0, 0.0}"
2643
2644
2645class object_converter(CConverter):
2646    type = 'PyObject *'
2647    format_unit = 'O'
2648
2649    def converter_init(self, *, converter=None, type=None, subclass_of=None):
2650        if converter:
2651            if subclass_of:
2652                fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2653            self.format_unit = 'O&'
2654            self.converter = converter
2655        elif subclass_of:
2656            self.format_unit = 'O!'
2657            self.subclass_of = subclass_of
2658
2659        if type is not None:
2660            self.type = type
2661
2662
2663#
2664# We define three conventions for buffer types in the 'accept' argument:
2665#
2666#  buffer  : any object supporting the buffer interface
2667#  rwbuffer: any object supporting the buffer interface, but must be writeable
2668#  robuffer: any object supporting the buffer interface, but must not be writeable
2669#
2670
2671class buffer: pass
2672class rwbuffer: pass
2673class robuffer: pass
2674
2675def str_converter_key(types, encoding, zeroes):
2676    return (frozenset(types), bool(encoding), bool(zeroes))
2677
2678str_converter_argument_map = {}
2679
2680class str_converter(CConverter):
2681    type = 'const char *'
2682    default_type = (str, Null, NoneType)
2683    format_unit = 's'
2684
2685    def converter_init(self, *, accept={str}, encoding=None, zeroes=False):
2686
2687        key = str_converter_key(accept, encoding, zeroes)
2688        format_unit = str_converter_argument_map.get(key)
2689        if not format_unit:
2690            fail("str_converter: illegal combination of arguments", key)
2691
2692        self.format_unit = format_unit
2693        self.length = bool(zeroes)
2694        if encoding:
2695            if self.default not in (Null, None, unspecified):
2696                fail("str_converter: Argument Clinic doesn't support default values for encoded strings")
2697            self.encoding = encoding
2698            self.type = 'char *'
2699            # sorry, clinic can't support preallocated buffers
2700            # for es# and et#
2701            self.c_default = "NULL"
2702
2703    def cleanup(self):
2704        if self.encoding:
2705            name = ensure_legal_c_identifier(self.name)
2706            return "".join(["if (", name, ") {\n   PyMem_FREE(", name, ");\n}\n"])
2707
2708#
2709# This is the fourth or fifth rewrite of registering all the
2710# crazy string converter format units.  Previous approaches hid
2711# bugs--generally mismatches between the semantics of the format
2712# unit and the arguments necessary to represent those semantics
2713# properly.  Hopefully with this approach we'll get it 100% right.
2714#
2715# The r() function (short for "register") both registers the
2716# mapping from arguments to format unit *and* registers the
2717# legacy C converter for that format unit.
2718#
2719def r(format_unit, *, accept, encoding=False, zeroes=False):
2720    if not encoding and format_unit != 's':
2721        # add the legacy c converters here too.
2722        #
2723        # note: add_legacy_c_converter can't work for
2724        #   es, es#, et, or et#
2725        #   because of their extra encoding argument
2726        #
2727        # also don't add the converter for 's' because
2728        # the metaclass for CConverter adds it for us.
2729        kwargs = {}
2730        if accept != {str}:
2731            kwargs['accept'] = accept
2732        if zeroes:
2733            kwargs['zeroes'] = True
2734        added_f = functools.partial(str_converter, **kwargs)
2735        legacy_converters[format_unit] = added_f
2736
2737    d = str_converter_argument_map
2738    key = str_converter_key(accept, encoding, zeroes)
2739    if key in d:
2740        sys.exit("Duplicate keys specified for str_converter_argument_map!")
2741    d[key] = format_unit
2742
2743r('es',  encoding=True,              accept={str})
2744r('es#', encoding=True, zeroes=True, accept={str})
2745r('et',  encoding=True,              accept={bytes, bytearray, str})
2746r('et#', encoding=True, zeroes=True, accept={bytes, bytearray, str})
2747r('s',                               accept={str})
2748r('s#',                 zeroes=True, accept={robuffer, str})
2749r('y',                               accept={robuffer})
2750r('y#',                 zeroes=True, accept={robuffer})
2751r('z',                               accept={str, NoneType})
2752r('z#',                 zeroes=True, accept={robuffer, str, NoneType})
2753del r
2754
2755
2756class PyBytesObject_converter(CConverter):
2757    type = 'PyBytesObject *'
2758    format_unit = 'S'
2759    # accept = {bytes}
2760
2761class PyByteArrayObject_converter(CConverter):
2762    type = 'PyByteArrayObject *'
2763    format_unit = 'Y'
2764    # accept = {bytearray}
2765
2766class unicode_converter(CConverter):
2767    type = 'PyObject *'
2768    default_type = (str, Null, NoneType)
2769    format_unit = 'U'
2770
2771@add_legacy_c_converter('u#', zeroes=True)
2772@add_legacy_c_converter('Z', accept={str, NoneType})
2773@add_legacy_c_converter('Z#', accept={str, NoneType}, zeroes=True)
2774class Py_UNICODE_converter(CConverter):
2775    type = 'Py_UNICODE *'
2776    default_type = (str, Null, NoneType)
2777    format_unit = 'u'
2778
2779    def converter_init(self, *, accept={str}, zeroes=False):
2780        format_unit = 'Z' if accept=={str, NoneType} else 'u'
2781        if zeroes:
2782            format_unit += '#'
2783            self.length = True
2784        self.format_unit = format_unit
2785
2786@add_legacy_c_converter('s*', accept={str, buffer})
2787@add_legacy_c_converter('z*', accept={str, buffer, NoneType})
2788@add_legacy_c_converter('w*', accept={rwbuffer})
2789class Py_buffer_converter(CConverter):
2790    type = 'Py_buffer'
2791    format_unit = 'y*'
2792    impl_by_reference = True
2793    c_ignored_default = "{NULL, NULL}"
2794
2795    def converter_init(self, *, accept={buffer}):
2796        if self.default not in (unspecified, None):
2797            fail("The only legal default value for Py_buffer is None.")
2798
2799        self.c_default = self.c_ignored_default
2800
2801        if accept == {str, buffer, NoneType}:
2802            format_unit = 'z*'
2803        elif accept == {str, buffer}:
2804            format_unit = 's*'
2805        elif accept == {buffer}:
2806            format_unit = 'y*'
2807        elif accept == {rwbuffer}:
2808            format_unit = 'w*'
2809        else:
2810            fail("Py_buffer_converter: illegal combination of arguments")
2811
2812        self.format_unit = format_unit
2813
2814    def cleanup(self):
2815        name = ensure_legal_c_identifier(self.name)
2816        return "".join(["if (", name, ".obj) {\n   PyBuffer_Release(&", name, ");\n}\n"])
2817
2818
2819def correct_name_for_self(f):
2820    if f.kind in (CALLABLE, METHOD_INIT):
2821        if f.cls:
2822            return "PyObject *", "self"
2823        return "PyObject *", "module"
2824    if f.kind == STATIC_METHOD:
2825        return "void *", "null"
2826    if f.kind in (CLASS_METHOD, METHOD_NEW):
2827        return "PyTypeObject *", "type"
2828    raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2829
2830def required_type_for_self_for_parser(f):
2831    type, _ = correct_name_for_self(f)
2832    if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2833        return type
2834    return None
2835
2836
2837class self_converter(CConverter):
2838    """
2839    A special-case converter:
2840    this is the default converter used for "self".
2841    """
2842    type = None
2843    format_unit = ''
2844
2845    def converter_init(self, *, type=None):
2846        self.specified_type = type
2847
2848    def pre_render(self):
2849        f = self.function
2850        default_type, default_name = correct_name_for_self(f)
2851        self.signature_name = default_name
2852        self.type = self.specified_type or self.type or default_type
2853
2854        kind = self.function.kind
2855        new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2856
2857        if (kind == STATIC_METHOD) or new_or_init:
2858            self.show_in_signature = False
2859
2860    # tp_new (METHOD_NEW) functions are of type newfunc:
2861    #     typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2862    # PyTypeObject is a typedef for struct _typeobject.
2863    #
2864    # tp_init (METHOD_INIT) functions are of type initproc:
2865    #     typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2866    #
2867    # All other functions generated by Argument Clinic are stored in
2868    # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2869    #     typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2870    # However!  We habitually cast these functions to PyCFunction,
2871    # since functions that accept keyword arguments don't fit this signature
2872    # but are stored there anyway.  So strict type equality isn't important
2873    # for these functions.
2874    #
2875    # So:
2876    #
2877    # * The name of the first parameter to the impl and the parsing function will always
2878    #   be self.name.
2879    #
2880    # * The type of the first parameter to the impl will always be of self.type.
2881    #
2882    # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2883    #   * The type of the first parameter to the parsing function is also self.type.
2884    #     This means that if you step into the parsing function, your "self" parameter
2885    #     is of the correct type, which may make debugging more pleasant.
2886    #
2887    # * Else if the function is tp_new (METHOD_NEW):
2888    #   * The type of the first parameter to the parsing function is "PyTypeObject *",
2889    #     so the type signature of the function call is an exact match.
2890    #   * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2891    #     in the impl call.
2892    #
2893    # * Else if the function is tp_init (METHOD_INIT):
2894    #   * The type of the first parameter to the parsing function is "PyObject *",
2895    #     so the type signature of the function call is an exact match.
2896    #   * If self.type != "PyObject *", we cast the first parameter to self.type
2897    #     in the impl call.
2898
2899    @property
2900    def parser_type(self):
2901        return required_type_for_self_for_parser(self.function) or self.type
2902
2903    def render(self, parameter, data):
2904        """
2905        parameter is a clinic.Parameter instance.
2906        data is a CRenderData instance.
2907        """
2908        if self.function.kind == STATIC_METHOD:
2909            return
2910
2911        self._render_self(parameter, data)
2912
2913        if self.type != self.parser_type:
2914            # insert cast to impl_argument[0], aka self.
2915            # we know we're in the first slot in all the CRenderData lists,
2916            # because we render parameters in order, and self is always first.
2917            assert len(data.impl_arguments) == 1
2918            assert data.impl_arguments[0] == self.name
2919            data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2920
2921    def set_template_dict(self, template_dict):
2922        template_dict['self_name'] = self.name
2923        template_dict['self_type'] = self.parser_type
2924        kind = self.function.kind
2925        cls = self.function.cls
2926
2927        if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef):
2928            if kind == METHOD_NEW:
2929                passed_in_type = self.name
2930            else:
2931                passed_in_type = 'Py_TYPE({})'.format(self.name)
2932
2933            line = '({passed_in_type} == {type_object}) &&\n        '
2934            d = {
2935                'type_object': self.function.cls.type_object,
2936                'passed_in_type': passed_in_type
2937                }
2938            template_dict['self_type_check'] = line.format_map(d)
2939
2940
2941
2942def add_c_return_converter(f, name=None):
2943    if not name:
2944        name = f.__name__
2945        if not name.endswith('_return_converter'):
2946            return f
2947        name = name[:-len('_return_converter')]
2948    return_converters[name] = f
2949    return f
2950
2951
2952class CReturnConverterAutoRegister(type):
2953    def __init__(cls, name, bases, classdict):
2954        add_c_return_converter(cls)
2955
2956class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2957
2958    # The C type to use for this variable.
2959    # 'type' should be a Python string specifying the type, e.g. "int".
2960    # If this is a pointer type, the type string should end with ' *'.
2961    type = 'PyObject *'
2962
2963    # The Python default value for this parameter, as a Python value.
2964    # Or the magic value "unspecified" if there is no default.
2965    default = None
2966
2967    def __init__(self, *, py_default=None, **kwargs):
2968        self.py_default = py_default
2969        try:
2970            self.return_converter_init(**kwargs)
2971        except TypeError as e:
2972            s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2973            sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2974
2975    def return_converter_init(self):
2976        pass
2977
2978    def declare(self, data, name="_return_value"):
2979        line = []
2980        add = line.append
2981        add(self.type)
2982        if not self.type.endswith('*'):
2983            add(' ')
2984        add(name + ';')
2985        data.declarations.append(''.join(line))
2986        data.return_value = name
2987
2988    def err_occurred_if(self, expr, data):
2989        data.return_conversion.append('if (({}) && PyErr_Occurred()) {{\n    goto exit;\n}}\n'.format(expr))
2990
2991    def err_occurred_if_null_pointer(self, variable, data):
2992        data.return_conversion.append('if ({} == NULL) {{\n    goto exit;\n}}\n'.format(variable))
2993
2994    def render(self, function, data):
2995        """
2996        function is a clinic.Function instance.
2997        data is a CRenderData instance.
2998        """
2999        pass
3000
3001add_c_return_converter(CReturnConverter, 'object')
3002
3003class NoneType_return_converter(CReturnConverter):
3004    def render(self, function, data):
3005        self.declare(data)
3006        data.return_conversion.append('''
3007if (_return_value != Py_None) {
3008    goto exit;
3009}
3010return_value = Py_None;
3011Py_INCREF(Py_None);
3012'''.strip())
3013
3014class bool_return_converter(CReturnConverter):
3015    type = 'int'
3016
3017    def render(self, function, data):
3018        self.declare(data)
3019        self.err_occurred_if("_return_value == -1", data)
3020        data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
3021
3022class long_return_converter(CReturnConverter):
3023    type = 'long'
3024    conversion_fn = 'PyLong_FromLong'
3025    cast = ''
3026    unsigned_cast = ''
3027
3028    def render(self, function, data):
3029        self.declare(data)
3030        self.err_occurred_if("_return_value == {}-1".format(self.unsigned_cast), data)
3031        data.return_conversion.append(
3032            ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
3033
3034class int_return_converter(long_return_converter):
3035    type = 'int'
3036    cast = '(long)'
3037
3038class init_return_converter(long_return_converter):
3039    """
3040    Special return converter for __init__ functions.
3041    """
3042    type = 'int'
3043    cast = '(long)'
3044
3045    def render(self, function, data):
3046        pass
3047
3048class unsigned_long_return_converter(long_return_converter):
3049    type = 'unsigned long'
3050    conversion_fn = 'PyLong_FromUnsignedLong'
3051    unsigned_cast = '(unsigned long)'
3052
3053class unsigned_int_return_converter(unsigned_long_return_converter):
3054    type = 'unsigned int'
3055    cast = '(unsigned long)'
3056    unsigned_cast = '(unsigned int)'
3057
3058class Py_ssize_t_return_converter(long_return_converter):
3059    type = 'Py_ssize_t'
3060    conversion_fn = 'PyLong_FromSsize_t'
3061
3062class size_t_return_converter(long_return_converter):
3063    type = 'size_t'
3064    conversion_fn = 'PyLong_FromSize_t'
3065    unsigned_cast = '(size_t)'
3066
3067
3068class double_return_converter(CReturnConverter):
3069    type = 'double'
3070    cast = ''
3071
3072    def render(self, function, data):
3073        self.declare(data)
3074        self.err_occurred_if("_return_value == -1.0", data)
3075        data.return_conversion.append(
3076            'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
3077
3078class float_return_converter(double_return_converter):
3079    type = 'float'
3080    cast = '(double)'
3081
3082
3083class DecodeFSDefault_return_converter(CReturnConverter):
3084    type = 'char *'
3085
3086    def render(self, function, data):
3087        self.declare(data)
3088        self.err_occurred_if_null_pointer("_return_value", data)
3089        data.return_conversion.append(
3090            'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
3091
3092
3093def eval_ast_expr(node, globals, *, filename='-'):
3094    """
3095    Takes an ast.Expr node.  Compiles and evaluates it.
3096    Returns the result of the expression.
3097
3098    globals represents the globals dict the expression
3099    should see.  (There's no equivalent for "locals" here.)
3100    """
3101
3102    if isinstance(node, ast.Expr):
3103        node = node.value
3104
3105    node = ast.Expression(node)
3106    co = compile(node, filename, 'eval')
3107    fn = types.FunctionType(co, globals)
3108    return fn()
3109
3110
3111class IndentStack:
3112    def __init__(self):
3113        self.indents = []
3114        self.margin = None
3115
3116    def _ensure(self):
3117        if not self.indents:
3118            fail('IndentStack expected indents, but none are defined.')
3119
3120    def measure(self, line):
3121        """
3122        Returns the length of the line's margin.
3123        """
3124        if '\t' in line:
3125            fail('Tab characters are illegal in the Argument Clinic DSL.')
3126        stripped = line.lstrip()
3127        if not len(stripped):
3128            # we can't tell anything from an empty line
3129            # so just pretend it's indented like our current indent
3130            self._ensure()
3131            return self.indents[-1]
3132        return len(line) - len(stripped)
3133
3134    def infer(self, line):
3135        """
3136        Infer what is now the current margin based on this line.
3137        Returns:
3138            1 if we have indented (or this is the first margin)
3139            0 if the margin has not changed
3140           -N if we have dedented N times
3141        """
3142        indent = self.measure(line)
3143        margin = ' ' * indent
3144        if not self.indents:
3145            self.indents.append(indent)
3146            self.margin = margin
3147            return 1
3148        current = self.indents[-1]
3149        if indent == current:
3150            return 0
3151        if indent > current:
3152            self.indents.append(indent)
3153            self.margin = margin
3154            return 1
3155        # indent < current
3156        if indent not in self.indents:
3157            fail("Illegal outdent.")
3158        outdent_count = 0
3159        while indent != current:
3160            self.indents.pop()
3161            current = self.indents[-1]
3162            outdent_count -= 1
3163        self.margin = margin
3164        return outdent_count
3165
3166    @property
3167    def depth(self):
3168        """
3169        Returns how many margins are currently defined.
3170        """
3171        return len(self.indents)
3172
3173    def indent(self, line):
3174        """
3175        Indents a line by the currently defined margin.
3176        """
3177        return self.margin + line
3178
3179    def dedent(self, line):
3180        """
3181        Dedents a line by the currently defined margin.
3182        (The inverse of 'indent'.)
3183        """
3184        margin = self.margin
3185        indent = self.indents[-1]
3186        if not line.startswith(margin):
3187            fail('Cannot dedent, line does not start with the previous margin:')
3188        return line[indent:]
3189
3190
3191class DSLParser:
3192    def __init__(self, clinic):
3193        self.clinic = clinic
3194
3195        self.directives = {}
3196        for name in dir(self):
3197            # functions that start with directive_ are added to directives
3198            _, s, key = name.partition("directive_")
3199            if s:
3200                self.directives[key] = getattr(self, name)
3201
3202            # functions that start with at_ are too, with an @ in front
3203            _, s, key = name.partition("at_")
3204            if s:
3205                self.directives['@' + key] = getattr(self, name)
3206
3207        self.reset()
3208
3209    def reset(self):
3210        self.function = None
3211        self.state = self.state_dsl_start
3212        self.parameter_indent = None
3213        self.keyword_only = False
3214        self.positional_only = False
3215        self.group = 0
3216        self.parameter_state = self.ps_start
3217        self.seen_positional_with_default = False
3218        self.indent = IndentStack()
3219        self.kind = CALLABLE
3220        self.coexist = False
3221        self.parameter_continuation = ''
3222        self.preserve_output = False
3223
3224    def directive_version(self, required):
3225        global version
3226        if version_comparitor(version, required) < 0:
3227            fail("Insufficient Clinic version!\n  Version: " + version + "\n  Required: " + required)
3228
3229    def directive_module(self, name):
3230        fields = name.split('.')
3231        new = fields.pop()
3232        module, cls = self.clinic._module_and_class(fields)
3233        if cls:
3234            fail("Can't nest a module inside a class!")
3235
3236        if name in module.classes:
3237            fail("Already defined module " + repr(name) + "!")
3238
3239        m = Module(name, module)
3240        module.modules[name] = m
3241        self.block.signatures.append(m)
3242
3243    def directive_class(self, name, typedef, type_object):
3244        fields = name.split('.')
3245        in_classes = False
3246        parent = self
3247        name = fields.pop()
3248        so_far = []
3249        module, cls = self.clinic._module_and_class(fields)
3250
3251        parent = cls or module
3252        if name in parent.classes:
3253            fail("Already defined class " + repr(name) + "!")
3254
3255        c = Class(name, module, cls, typedef, type_object)
3256        parent.classes[name] = c
3257        self.block.signatures.append(c)
3258
3259    def directive_set(self, name, value):
3260        if name not in ("line_prefix", "line_suffix"):
3261            fail("unknown variable", repr(name))
3262
3263        value = value.format_map({
3264            'block comment start': '/*',
3265            'block comment end': '*/',
3266            })
3267
3268        self.clinic.__dict__[name] = value
3269
3270    def directive_destination(self, name, command, *args):
3271        if command == 'new':
3272            self.clinic.add_destination(name, *args)
3273            return
3274
3275        if command == 'clear':
3276            self.clinic.get_destination(name).clear()
3277        fail("unknown destination command", repr(command))
3278
3279
3280    def directive_output(self, command_or_name, destination=''):
3281        fd = self.clinic.destination_buffers
3282
3283        if command_or_name == "preset":
3284            preset = self.clinic.presets.get(destination)
3285            if not preset:
3286                fail("Unknown preset " + repr(destination) + "!")
3287            fd.update(preset)
3288            return
3289
3290        if command_or_name == "push":
3291            self.clinic.destination_buffers_stack.append(fd.copy())
3292            return
3293
3294        if command_or_name == "pop":
3295            if not self.clinic.destination_buffers_stack:
3296                fail("Can't 'output pop', stack is empty!")
3297            previous_fd = self.clinic.destination_buffers_stack.pop()
3298            fd.update(previous_fd)
3299            return
3300
3301        # secret command for debugging!
3302        if command_or_name == "print":
3303            self.block.output.append(pprint.pformat(fd))
3304            self.block.output.append('\n')
3305            return
3306
3307        d = self.clinic.get_destination(destination)
3308
3309        if command_or_name == "everything":
3310            for name in list(fd):
3311                fd[name] = d
3312            return
3313
3314        if command_or_name not in fd:
3315            fail("Invalid command / destination name " + repr(command_or_name) + ", must be one of:\n  preset push pop print everything " + " ".join(fd))
3316        fd[command_or_name] = d
3317
3318    def directive_dump(self, name):
3319        self.block.output.append(self.clinic.get_destination(name).dump())
3320
3321    def directive_print(self, *args):
3322        self.block.output.append(' '.join(args))
3323        self.block.output.append('\n')
3324
3325    def directive_preserve(self):
3326        if self.preserve_output:
3327            fail("Can't have preserve twice in one block!")
3328        self.preserve_output = True
3329
3330    def at_classmethod(self):
3331        if self.kind is not CALLABLE:
3332            fail("Can't set @classmethod, function is not a normal callable")
3333        self.kind = CLASS_METHOD
3334
3335    def at_staticmethod(self):
3336        if self.kind is not CALLABLE:
3337            fail("Can't set @staticmethod, function is not a normal callable")
3338        self.kind = STATIC_METHOD
3339
3340    def at_coexist(self):
3341        if self.coexist:
3342            fail("Called @coexist twice!")
3343        self.coexist = True
3344
3345    def parse(self, block):
3346        self.reset()
3347        self.block = block
3348        self.saved_output = self.block.output
3349        block.output = []
3350        block_start = self.clinic.block_parser.line_number
3351        lines = block.input.split('\n')
3352        for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
3353            if '\t' in line:
3354                fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
3355            self.state(line)
3356
3357        self.next(self.state_terminal)
3358        self.state(None)
3359
3360        block.output.extend(self.clinic.language.render(clinic, block.signatures))
3361
3362        if self.preserve_output:
3363            if block.output:
3364                fail("'preserve' only works for blocks that don't produce any output!")
3365            block.output = self.saved_output
3366
3367    @staticmethod
3368    def ignore_line(line):
3369        # ignore comment-only lines
3370        if line.lstrip().startswith('#'):
3371            return True
3372
3373        # Ignore empty lines too
3374        # (but not in docstring sections!)
3375        if not line.strip():
3376            return True
3377
3378        return False
3379
3380    @staticmethod
3381    def calculate_indent(line):
3382        return len(line) - len(line.strip())
3383
3384    def next(self, state, line=None):
3385        # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3386        self.state = state
3387        if line is not None:
3388            self.state(line)
3389
3390    def state_dsl_start(self, line):
3391        # self.block = self.ClinicOutputBlock(self)
3392        if self.ignore_line(line):
3393            return
3394
3395        # is it a directive?
3396        fields = shlex.split(line)
3397        directive_name = fields[0]
3398        directive = self.directives.get(directive_name, None)
3399        if directive:
3400            try:
3401                directive(*fields[1:])
3402            except TypeError as e:
3403                fail(str(e))
3404            return
3405
3406        self.next(self.state_modulename_name, line)
3407
3408    def state_modulename_name(self, line):
3409        # looking for declaration, which establishes the leftmost column
3410        # line should be
3411        #     modulename.fnname [as c_basename] [-> return annotation]
3412        # square brackets denote optional syntax.
3413        #
3414        # alternatively:
3415        #     modulename.fnname [as c_basename] = modulename.existing_fn_name
3416        # clones the parameters and return converter from that
3417        # function.  you can't modify them.  you must enter a
3418        # new docstring.
3419        #
3420        # (but we might find a directive first!)
3421        #
3422        # this line is permitted to start with whitespace.
3423        # we'll call this number of spaces F (for "function").
3424
3425        if not line.strip():
3426            return
3427
3428        self.indent.infer(line)
3429
3430        # are we cloning?
3431        before, equals, existing = line.rpartition('=')
3432        if equals:
3433            full_name, _, c_basename = before.partition(' as ')
3434            full_name = full_name.strip()
3435            c_basename = c_basename.strip()
3436            existing = existing.strip()
3437            if (is_legal_py_identifier(full_name) and
3438                (not c_basename or is_legal_c_identifier(c_basename)) and
3439                is_legal_py_identifier(existing)):
3440                # we're cloning!
3441                fields = [x.strip() for x in existing.split('.')]
3442                function_name = fields.pop()
3443                module, cls = self.clinic._module_and_class(fields)
3444
3445                for existing_function in (cls or module).functions:
3446                    if existing_function.name == function_name:
3447                        break
3448                else:
3449                    existing_function = None
3450                if not existing_function:
3451                    print("class", cls, "module", module, "existing", existing)
3452                    print("cls. functions", cls.functions)
3453                    fail("Couldn't find existing function " + repr(existing) + "!")
3454
3455                fields = [x.strip() for x in full_name.split('.')]
3456                function_name = fields.pop()
3457                module, cls = self.clinic._module_and_class(fields)
3458
3459                if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3460                    fail("'kind' of function and cloned function don't match!  (@classmethod/@staticmethod/@coexist)")
3461                self.function = existing_function.copy(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename, docstring='')
3462
3463                self.block.signatures.append(self.function)
3464                (cls or module).functions.append(self.function)
3465                self.next(self.state_function_docstring)
3466                return
3467
3468        line, _, returns = line.partition('->')
3469
3470        full_name, _, c_basename = line.partition(' as ')
3471        full_name = full_name.strip()
3472        c_basename = c_basename.strip() or None
3473
3474        if not is_legal_py_identifier(full_name):
3475            fail("Illegal function name: {}".format(full_name))
3476        if c_basename and not is_legal_c_identifier(c_basename):
3477            fail("Illegal C basename: {}".format(c_basename))
3478
3479        return_converter = None
3480        if returns:
3481            ast_input = "def x() -> {}: pass".format(returns)
3482            module = None
3483            try:
3484                module = ast.parse(ast_input)
3485            except SyntaxError:
3486                pass
3487            if not module:
3488                fail("Badly-formed annotation for " + full_name + ": " + returns)
3489            try:
3490                name, legacy, kwargs = self.parse_converter(module.body[0].returns)
3491                if legacy:
3492                    fail("Legacy converter {!r} not allowed as a return converter"
3493                         .format(name))
3494                if name not in return_converters:
3495                    fail("No available return converter called " + repr(name))
3496                return_converter = return_converters[name](**kwargs)
3497            except ValueError:
3498                fail("Badly-formed annotation for " + full_name + ": " + returns)
3499
3500        fields = [x.strip() for x in full_name.split('.')]
3501        function_name = fields.pop()
3502        module, cls = self.clinic._module_and_class(fields)
3503
3504        fields = full_name.split('.')
3505        if fields[-1] == '__new__':
3506            if (self.kind != CLASS_METHOD) or (not cls):
3507                fail("__new__ must be a class method!")
3508            self.kind = METHOD_NEW
3509        elif fields[-1] == '__init__':
3510            if (self.kind != CALLABLE) or (not cls):
3511                fail("__init__ must be a normal method, not a class or static method!")
3512            self.kind = METHOD_INIT
3513            if not return_converter:
3514                return_converter = init_return_converter()
3515        elif fields[-1] in unsupported_special_methods:
3516            fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic!  (Yet.)")
3517
3518        if not return_converter:
3519            return_converter = CReturnConverter()
3520
3521        if not module:
3522            fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3523        self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3524                                 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3525        self.block.signatures.append(self.function)
3526
3527        # insert a self converter automatically
3528        type, name = correct_name_for_self(self.function)
3529        kwargs = {}
3530        if cls and type == "PyObject *":
3531            kwargs['type'] = cls.typedef
3532        sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs)
3533        p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3534        self.function.parameters[sc.name] = p_self
3535
3536        (cls or module).functions.append(self.function)
3537        self.next(self.state_parameters_start)
3538
3539    # Now entering the parameters section.  The rules, formally stated:
3540    #
3541    #   * All lines must be indented with spaces only.
3542    #   * The first line must be a parameter declaration.
3543    #   * The first line must be indented.
3544    #       * This first line establishes the indent for parameters.
3545    #       * We'll call this number of spaces P (for "parameter").
3546    #   * Thenceforth:
3547    #       * Lines indented with P spaces specify a parameter.
3548    #       * Lines indented with > P spaces are docstrings for the previous
3549    #         parameter.
3550    #           * We'll call this number of spaces D (for "docstring").
3551    #           * All subsequent lines indented with >= D spaces are stored as
3552    #             part of the per-parameter docstring.
3553    #           * All lines will have the first D spaces of the indent stripped
3554    #             before they are stored.
3555    #           * It's illegal to have a line starting with a number of spaces X
3556    #             such that P < X < D.
3557    #       * A line with < P spaces is the first line of the function
3558    #         docstring, which ends processing for parameters and per-parameter
3559    #         docstrings.
3560    #           * The first line of the function docstring must be at the same
3561    #             indent as the function declaration.
3562    #       * It's illegal to have any line in the parameters section starting
3563    #         with X spaces such that F < X < P.  (As before, F is the indent
3564    #         of the function declaration.)
3565    #
3566    # Also, currently Argument Clinic places the following restrictions on groups:
3567    #   * Each group must contain at least one parameter.
3568    #   * Each group may contain at most one group, which must be the furthest
3569    #     thing in the group from the required parameters.  (The nested group
3570    #     must be the first in the group when it's before the required
3571    #     parameters, and the last thing in the group when after the required
3572    #     parameters.)
3573    #   * There may be at most one (top-level) group to the left or right of
3574    #     the required parameters.
3575    #   * You must specify a slash, and it must be after all parameters.
3576    #     (In other words: either all parameters are positional-only,
3577    #      or none are.)
3578    #
3579    #  Said another way:
3580    #   * Each group must contain at least one parameter.
3581    #   * All left square brackets before the required parameters must be
3582    #     consecutive.  (You can't have a left square bracket followed
3583    #     by a parameter, then another left square bracket.  You can't
3584    #     have a left square bracket, a parameter, a right square bracket,
3585    #     and then a left square bracket.)
3586    #   * All right square brackets after the required parameters must be
3587    #     consecutive.
3588    #
3589    # These rules are enforced with a single state variable:
3590    # "parameter_state".  (Previously the code was a miasma of ifs and
3591    # separate boolean state variables.)  The states are:
3592    #
3593    #  [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ]   <- line
3594    # 01   2          3       4    5           6     <- state transitions
3595    #
3596    # 0: ps_start.  before we've seen anything.  legal transitions are to 1 or 3.
3597    # 1: ps_left_square_before.  left square brackets before required parameters.
3598    # 2: ps_group_before.  in a group, before required parameters.
3599    # 3: ps_required.  required parameters, positional-or-keyword or positional-only
3600    #     (we don't know yet).  (renumber left groups!)
3601    # 4: ps_optional.  positional-or-keyword or positional-only parameters that
3602    #    now must have default values.
3603    # 5: ps_group_after.  in a group, after required parameters.
3604    # 6: ps_right_square_after.  right square brackets after required parameters.
3605    ps_start, ps_left_square_before, ps_group_before, ps_required, \
3606    ps_optional, ps_group_after, ps_right_square_after = range(7)
3607
3608    def state_parameters_start(self, line):
3609        if self.ignore_line(line):
3610            return
3611
3612        # if this line is not indented, we have no parameters
3613        if not self.indent.infer(line):
3614            return self.next(self.state_function_docstring, line)
3615
3616        self.parameter_continuation = ''
3617        return self.next(self.state_parameter, line)
3618
3619
3620    def to_required(self):
3621        """
3622        Transition to the "required" parameter state.
3623        """
3624        if self.parameter_state != self.ps_required:
3625            self.parameter_state = self.ps_required
3626            for p in self.function.parameters.values():
3627                p.group = -p.group
3628
3629    def state_parameter(self, line):
3630        if self.parameter_continuation:
3631            line = self.parameter_continuation + ' ' + line.lstrip()
3632            self.parameter_continuation = ''
3633
3634        if self.ignore_line(line):
3635            return
3636
3637        assert self.indent.depth == 2
3638        indent = self.indent.infer(line)
3639        if indent == -1:
3640            # we outdented, must be to definition column
3641            return self.next(self.state_function_docstring, line)
3642
3643        if indent == 1:
3644            # we indented, must be to new parameter docstring column
3645            return self.next(self.state_parameter_docstring_start, line)
3646
3647        line = line.rstrip()
3648        if line.endswith('\\'):
3649            self.parameter_continuation = line[:-1]
3650            return
3651
3652        line = line.lstrip()
3653
3654        if line in ('*', '/', '[', ']'):
3655            self.parse_special_symbol(line)
3656            return
3657
3658        if self.parameter_state in (self.ps_start, self.ps_required):
3659            self.to_required()
3660        elif self.parameter_state == self.ps_left_square_before:
3661            self.parameter_state = self.ps_group_before
3662        elif self.parameter_state == self.ps_group_before:
3663            if not self.group:
3664                self.to_required()
3665        elif self.parameter_state in (self.ps_group_after, self.ps_optional):
3666            pass
3667        else:
3668            fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
3669
3670        # handle "as" for  parameters too
3671        c_name = None
3672        name, have_as_token, trailing = line.partition(' as ')
3673        if have_as_token:
3674            name = name.strip()
3675            if ' ' not in name:
3676                fields = trailing.strip().split(' ')
3677                if not fields:
3678                    fail("Invalid 'as' clause!")
3679                c_name = fields[0]
3680                if c_name.endswith(':'):
3681                    name += ':'
3682                    c_name = c_name[:-1]
3683                fields[0] = name
3684                line = ' '.join(fields)
3685
3686        base, equals, default = line.rpartition('=')
3687        if not equals:
3688            base = default
3689            default = None
3690
3691        module = None
3692        try:
3693            ast_input = "def x({}): pass".format(base)
3694            module = ast.parse(ast_input)
3695        except SyntaxError:
3696            try:
3697                # the last = was probably inside a function call, like
3698                #   c: int(accept={str})
3699                # so assume there was no actual default value.
3700                default = None
3701                ast_input = "def x({}): pass".format(line)
3702                module = ast.parse(ast_input)
3703            except SyntaxError:
3704                pass
3705        if not module:
3706            fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
3707
3708        function_args = module.body[0].args
3709
3710        if len(function_args.args) > 1:
3711            fail("Function " + self.function.name + " has an invalid parameter declaration (comma?):\n\t" + line)
3712        if function_args.defaults or function_args.kw_defaults:
3713            fail("Function " + self.function.name + " has an invalid parameter declaration (default value?):\n\t" + line)
3714        if function_args.vararg or function_args.kwarg:
3715            fail("Function " + self.function.name + " has an invalid parameter declaration (*args? **kwargs?):\n\t" + line)
3716
3717        parameter = function_args.args[0]
3718
3719        parameter_name = parameter.arg
3720        name, legacy, kwargs = self.parse_converter(parameter.annotation)
3721
3722        if not default:
3723            if self.parameter_state == self.ps_optional:
3724                fail("Can't have a parameter without a default (" + repr(parameter_name) + ")\nafter a parameter with a default!")
3725            value = unspecified
3726            if 'py_default' in kwargs:
3727                fail("You can't specify py_default without specifying a default value!")
3728        else:
3729            if self.parameter_state == self.ps_required:
3730                self.parameter_state = self.ps_optional
3731            default = default.strip()
3732            bad = False
3733            ast_input = "x = {}".format(default)
3734            bad = False
3735            try:
3736                module = ast.parse(ast_input)
3737
3738                if 'c_default' not in kwargs:
3739                    # we can only represent very simple data values in C.
3740                    # detect whether default is okay, via a blacklist
3741                    # of disallowed ast nodes.
3742                    class DetectBadNodes(ast.NodeVisitor):
3743                        bad = False
3744                        def bad_node(self, node):
3745                            self.bad = True
3746
3747                        # inline function call
3748                        visit_Call = bad_node
3749                        # inline if statement ("x = 3 if y else z")
3750                        visit_IfExp = bad_node
3751
3752                        # comprehensions and generator expressions
3753                        visit_ListComp = visit_SetComp = bad_node
3754                        visit_DictComp = visit_GeneratorExp = bad_node
3755
3756                        # literals for advanced types
3757                        visit_Dict = visit_Set = bad_node
3758                        visit_List = visit_Tuple = bad_node
3759
3760                        # "starred": "a = [1, 2, 3]; *a"
3761                        visit_Starred = bad_node
3762
3763                        # allow ellipsis, for now
3764                        # visit_Ellipsis = bad_node
3765
3766                    blacklist = DetectBadNodes()
3767                    blacklist.visit(module)
3768                    bad = blacklist.bad
3769                else:
3770                    # if they specify a c_default, we can be more lenient about the default value.
3771                    # but at least make an attempt at ensuring it's a valid expression.
3772                    try:
3773                        value = eval(default)
3774                        if value == unspecified:
3775                            fail("'unspecified' is not a legal default value!")
3776                    except NameError:
3777                        pass # probably a named constant
3778                    except Exception as e:
3779                        fail("Malformed expression given as default value\n"
3780                             "{!r} caused {!r}".format(default, e))
3781                if bad:
3782                    fail("Unsupported expression as default value: " + repr(default))
3783
3784                expr = module.body[0].value
3785                # mild hack: explicitly support NULL as a default value
3786                if isinstance(expr, ast.Name) and expr.id == 'NULL':
3787                    value = NULL
3788                    py_default = 'None'
3789                    c_default = "NULL"
3790                elif (isinstance(expr, ast.BinOp) or
3791                    (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3792                    c_default = kwargs.get("c_default")
3793                    if not (isinstance(c_default, str) and c_default):
3794                        fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3795                    py_default = default
3796                    value = unknown
3797                elif isinstance(expr, ast.Attribute):
3798                    a = []
3799                    n = expr
3800                    while isinstance(n, ast.Attribute):
3801                        a.append(n.attr)
3802                        n = n.value
3803                    if not isinstance(n, ast.Name):
3804                        fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3805                    a.append(n.id)
3806                    py_default = ".".join(reversed(a))
3807
3808                    c_default = kwargs.get("c_default")
3809                    if not (isinstance(c_default, str) and c_default):
3810                        fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3811
3812                    try:
3813                        value = eval(py_default)
3814                    except NameError:
3815                        value = unknown
3816                else:
3817                    value = ast.literal_eval(expr)
3818                    py_default = repr(value)
3819                    if isinstance(value, (bool, None.__class__)):
3820                        c_default = "Py_" + py_default
3821                    elif isinstance(value, str):
3822                        c_default = c_repr(value)
3823                    else:
3824                        c_default = py_default
3825
3826            except SyntaxError as e:
3827                fail("Syntax error: " + repr(e.text))
3828            except (ValueError, AttributeError):
3829                value = unknown
3830                c_default = kwargs.get("c_default")
3831                py_default = default
3832                if not (isinstance(c_default, str) and c_default):
3833                    fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3834
3835            kwargs.setdefault('c_default', c_default)
3836            kwargs.setdefault('py_default', py_default)
3837
3838        dict = legacy_converters if legacy else converters
3839        legacy_str = "legacy " if legacy else ""
3840        if name not in dict:
3841            fail('{} is not a valid {}converter'.format(name, legacy_str))
3842        # if you use a c_name for the parameter, we just give that name to the converter
3843        # but the parameter object gets the python name
3844        converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
3845
3846        kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
3847
3848        if isinstance(converter, self_converter):
3849            if len(self.function.parameters) == 1:
3850                if (self.parameter_state != self.ps_required):
3851                    fail("A 'self' parameter cannot be marked optional.")
3852                if value is not unspecified:
3853                    fail("A 'self' parameter cannot have a default value.")
3854                if self.group:
3855                    fail("A 'self' parameter cannot be in an optional group.")
3856                kind = inspect.Parameter.POSITIONAL_ONLY
3857                self.parameter_state = self.ps_start
3858                self.function.parameters.clear()
3859            else:
3860                fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3861
3862        p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
3863
3864        if parameter_name in self.function.parameters:
3865            fail("You can't have two parameters named " + repr(parameter_name) + "!")
3866        self.function.parameters[parameter_name] = p
3867
3868    def parse_converter(self, annotation):
3869        if isinstance(annotation, ast.Str):
3870            return annotation.s, True, {}
3871
3872        if isinstance(annotation, ast.Name):
3873            return annotation.id, False, {}
3874
3875        if not isinstance(annotation, ast.Call):
3876            fail("Annotations must be either a name, a function call, or a string.")
3877
3878        name = annotation.func.id
3879        symbols = globals()
3880
3881        kwargs = {node.arg: eval_ast_expr(node.value, symbols) for node in annotation.keywords}
3882        return name, False, kwargs
3883
3884    def parse_special_symbol(self, symbol):
3885        if symbol == '*':
3886            if self.keyword_only:
3887                fail("Function " + self.function.name + " uses '*' more than once.")
3888            self.keyword_only = True
3889        elif symbol == '[':
3890            if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3891                self.parameter_state = self.ps_left_square_before
3892            elif self.parameter_state in (self.ps_required, self.ps_group_after):
3893                self.parameter_state = self.ps_group_after
3894            else:
3895                fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
3896            self.group += 1
3897            self.function.docstring_only = True
3898        elif symbol == ']':
3899            if not self.group:
3900                fail("Function " + self.function.name + " has a ] without a matching [.")
3901            if not any(p.group == self.group for p in self.function.parameters.values()):
3902                fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3903            self.group -= 1
3904            if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3905                self.parameter_state = self.ps_group_before
3906            elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3907                self.parameter_state = self.ps_right_square_after
3908            else:
3909                fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
3910        elif symbol == '/':
3911            if self.positional_only:
3912                fail("Function " + self.function.name + " uses '/' more than once.")
3913            self.positional_only = True
3914            # ps_required and ps_optional are allowed here, that allows positional-only without option groups
3915            # to work (and have default values!)
3916            if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
3917                fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
3918            if self.keyword_only:
3919                fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3920            # fixup preceding parameters
3921            for p in self.function.parameters.values():
3922                if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
3923                    fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3924                p.kind = inspect.Parameter.POSITIONAL_ONLY
3925
3926    def state_parameter_docstring_start(self, line):
3927        self.parameter_docstring_indent = len(self.indent.margin)
3928        assert self.indent.depth == 3
3929        return self.next(self.state_parameter_docstring, line)
3930
3931    # every line of the docstring must start with at least F spaces,
3932    # where F > P.
3933    # these F spaces will be stripped.
3934    def state_parameter_docstring(self, line):
3935        stripped = line.strip()
3936        if stripped.startswith('#'):
3937            return
3938
3939        indent = self.indent.measure(line)
3940        if indent < self.parameter_docstring_indent:
3941            self.indent.infer(line)
3942            assert self.indent.depth < 3
3943            if self.indent.depth == 2:
3944                # back to a parameter
3945                return self.next(self.state_parameter, line)
3946            assert self.indent.depth == 1
3947            return self.next(self.state_function_docstring, line)
3948
3949        assert self.function.parameters
3950        last_parameter = next(reversed(list(self.function.parameters.values())))
3951
3952        new_docstring = last_parameter.docstring
3953
3954        if new_docstring:
3955            new_docstring += '\n'
3956        if stripped:
3957            new_docstring += self.indent.dedent(line)
3958
3959        last_parameter.docstring = new_docstring
3960
3961    # the final stanza of the DSL is the docstring.
3962    def state_function_docstring(self, line):
3963        if self.group:
3964            fail("Function " + self.function.name + " has a ] without a matching [.")
3965
3966        stripped = line.strip()
3967        if stripped.startswith('#'):
3968            return
3969
3970        new_docstring = self.function.docstring
3971        if new_docstring:
3972            new_docstring += "\n"
3973        if stripped:
3974            line = self.indent.dedent(line).rstrip()
3975        else:
3976            line = ''
3977        new_docstring += line
3978        self.function.docstring = new_docstring
3979
3980    def format_docstring(self):
3981        f = self.function
3982
3983        new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3984        if new_or_init and not f.docstring:
3985            # don't render a docstring at all, no signature, nothing.
3986            return f.docstring
3987
3988        text, add, output = _text_accumulator()
3989        parameters = f.render_parameters
3990
3991        ##
3992        ## docstring first line
3993        ##
3994
3995        if new_or_init:
3996            # classes get *just* the name of the class
3997            # not __new__, not __init__, and not module.classname
3998            assert f.cls
3999            add(f.cls.name)
4000        else:
4001            add(f.name)
4002        add('(')
4003
4004        # populate "right_bracket_count" field for every parameter
4005        assert parameters, "We should always have a self parameter. " + repr(f)
4006        assert isinstance(parameters[0].converter, self_converter)
4007        # self is always positional-only.
4008        assert parameters[0].is_positional_only()
4009        parameters[0].right_bracket_count = 0
4010        positional_only = True
4011        for p in parameters[1:]:
4012            if not p.is_positional_only():
4013                positional_only = False
4014            else:
4015                assert positional_only
4016            if positional_only:
4017                p.right_bracket_count = abs(p.group)
4018            else:
4019                # don't put any right brackets around non-positional-only parameters, ever.
4020                p.right_bracket_count = 0
4021
4022        right_bracket_count = 0
4023
4024        def fix_right_bracket_count(desired):
4025            nonlocal right_bracket_count
4026            s = ''
4027            while right_bracket_count < desired:
4028                s += '['
4029                right_bracket_count += 1
4030            while right_bracket_count > desired:
4031                s += ']'
4032                right_bracket_count -= 1
4033            return s
4034
4035        need_slash = False
4036        added_slash = False
4037        need_a_trailing_slash = False
4038
4039        # we only need a trailing slash:
4040        #   * if this is not a "docstring_only" signature
4041        #   * and if the last *shown* parameter is
4042        #     positional only
4043        if not f.docstring_only:
4044            for p in reversed(parameters):
4045                if not p.converter.show_in_signature:
4046                    continue
4047                if p.is_positional_only():
4048                    need_a_trailing_slash = True
4049                break
4050
4051
4052        added_star = False
4053
4054        first_parameter = True
4055        last_p = parameters[-1]
4056        line_length = len(''.join(text))
4057        indent = " " * line_length
4058        def add_parameter(text):
4059            nonlocal line_length
4060            nonlocal first_parameter
4061            if first_parameter:
4062                s = text
4063                first_parameter = False
4064            else:
4065                s = ' ' + text
4066                if line_length + len(s) >= 72:
4067                    add('\n')
4068                    add(indent)
4069                    line_length = len(indent)
4070                    s = text
4071            line_length += len(s)
4072            add(s)
4073
4074        for p in parameters:
4075            if not p.converter.show_in_signature:
4076                continue
4077            assert p.name
4078
4079            is_self = isinstance(p.converter, self_converter)
4080            if is_self and f.docstring_only:
4081                # this isn't a real machine-parsable signature,
4082                # so let's not print the "self" parameter
4083                continue
4084
4085            if p.is_positional_only():
4086                need_slash = not f.docstring_only
4087            elif need_slash and not (added_slash or p.is_positional_only()):
4088                added_slash = True
4089                add_parameter('/,')
4090
4091            if p.is_keyword_only() and not added_star:
4092                added_star = True
4093                add_parameter('*,')
4094
4095            p_add, p_output = text_accumulator()
4096            p_add(fix_right_bracket_count(p.right_bracket_count))
4097
4098            if isinstance(p.converter, self_converter):
4099                # annotate first parameter as being a "self".
4100                #
4101                # if inspect.Signature gets this function,
4102                # and it's already bound, the self parameter
4103                # will be stripped off.
4104                #
4105                # if it's not bound, it should be marked
4106                # as positional-only.
4107                #
4108                # note: we don't print "self" for __init__,
4109                # because this isn't actually the signature
4110                # for __init__.  (it can't be, __init__ doesn't
4111                # have a docstring.)  if this is an __init__
4112                # (or __new__), then this signature is for
4113                # calling the class to construct a new instance.
4114                p_add('$')
4115
4116            name = p.converter.signature_name or p.name
4117            p_add(name)
4118
4119            if p.converter.is_optional():
4120                p_add('=')
4121                value = p.converter.py_default
4122                if not value:
4123                    value = repr(p.converter.default)
4124                p_add(value)
4125
4126            if (p != last_p) or need_a_trailing_slash:
4127                p_add(',')
4128
4129            add_parameter(p_output())
4130
4131        add(fix_right_bracket_count(0))
4132        if need_a_trailing_slash:
4133            add_parameter('/')
4134        add(')')
4135
4136        # PEP 8 says:
4137        #
4138        #     The Python standard library will not use function annotations
4139        #     as that would result in a premature commitment to a particular
4140        #     annotation style. Instead, the annotations are left for users
4141        #     to discover and experiment with useful annotation styles.
4142        #
4143        # therefore this is commented out:
4144        #
4145        # if f.return_converter.py_default:
4146        #     add(' -> ')
4147        #     add(f.return_converter.py_default)
4148
4149        if not f.docstring_only:
4150            add("\n" + sig_end_marker + "\n")
4151
4152        docstring_first_line = output()
4153
4154        # now fix up the places where the brackets look wrong
4155        docstring_first_line = docstring_first_line.replace(', ]', ',] ')
4156
4157        # okay.  now we're officially building the "parameters" section.
4158        # create substitution text for {parameters}
4159        spacer_line = False
4160        for p in parameters:
4161            if not p.docstring.strip():
4162                continue
4163            if spacer_line:
4164                add('\n')
4165            else:
4166                spacer_line = True
4167            add("  ")
4168            add(p.name)
4169            add('\n')
4170            add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), "    "))
4171        parameters = output()
4172        if parameters:
4173            parameters += '\n'
4174
4175        ##
4176        ## docstring body
4177        ##
4178
4179        docstring = f.docstring.rstrip()
4180        lines = [line.rstrip() for line in docstring.split('\n')]
4181
4182        # Enforce the summary line!
4183        # The first line of a docstring should be a summary of the function.
4184        # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
4185        # by itself.
4186        #
4187        # Argument Clinic enforces the following rule:
4188        #  * either the docstring is empty,
4189        #  * or it must have a summary line.
4190        #
4191        # Guido said Clinic should enforce this:
4192        # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
4193
4194        if len(lines) >= 2:
4195            if lines[1]:
4196                fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
4197                    "Every non-blank function docstring must start with\n" +
4198                    "a single line summary followed by an empty line.")
4199        elif len(lines) == 1:
4200            # the docstring is only one line right now--the summary line.
4201            # add an empty line after the summary line so we have space
4202            # between it and the {parameters} we're about to add.
4203            lines.append('')
4204
4205        parameters_marker_count = len(docstring.split('{parameters}')) - 1
4206        if parameters_marker_count > 1:
4207            fail('You may not specify {parameters} more than once in a docstring!')
4208
4209        if not parameters_marker_count:
4210            # insert after summary line
4211            lines.insert(2, '{parameters}')
4212
4213        # insert at front of docstring
4214        lines.insert(0, docstring_first_line)
4215
4216        docstring = "\n".join(lines)
4217
4218        add(docstring)
4219        docstring = output()
4220
4221        docstring = linear_format(docstring, parameters=parameters)
4222        docstring = docstring.rstrip()
4223
4224        return docstring
4225
4226    def state_terminal(self, line):
4227        """
4228        Called when processing the block is done.
4229        """
4230        assert not line
4231
4232        if not self.function:
4233            return
4234
4235        if self.keyword_only:
4236            values = self.function.parameters.values()
4237            if not values:
4238                no_parameter_after_star = True
4239            else:
4240                last_parameter = next(reversed(list(values)))
4241                no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
4242            if no_parameter_after_star:
4243                fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
4244
4245        # remove trailing whitespace from all parameter docstrings
4246        for name, value in self.function.parameters.items():
4247            if not value:
4248                continue
4249            value.docstring = value.docstring.rstrip()
4250
4251        self.function.docstring = self.format_docstring()
4252
4253
4254
4255
4256# maps strings to callables.
4257# the callable should return an object
4258# that implements the clinic parser
4259# interface (__init__ and parse).
4260#
4261# example parsers:
4262#   "clinic", handles the Clinic DSL
4263#   "python", handles running Python code
4264#
4265parsers = {'clinic' : DSLParser, 'python': PythonParser}
4266
4267
4268clinic = None
4269
4270
4271def main(argv):
4272    import sys
4273
4274    if sys.version_info.major < 3 or sys.version_info.minor < 3:
4275        sys.exit("Error: clinic.py requires Python 3.3 or greater.")
4276
4277    import argparse
4278    cmdline = argparse.ArgumentParser()
4279    cmdline.add_argument("-f", "--force", action='store_true')
4280    cmdline.add_argument("-o", "--output", type=str)
4281    cmdline.add_argument("-v", "--verbose", action='store_true')
4282    cmdline.add_argument("--converters", action='store_true')
4283    cmdline.add_argument("--make", action='store_true')
4284    cmdline.add_argument("filename", type=str, nargs="*")
4285    ns = cmdline.parse_args(argv)
4286
4287    if ns.converters:
4288        if ns.filename:
4289            print("Usage error: can't specify --converters and a filename at the same time.")
4290            print()
4291            cmdline.print_usage()
4292            sys.exit(-1)
4293        converters = []
4294        return_converters = []
4295        ignored = set("""
4296            add_c_converter
4297            add_c_return_converter
4298            add_default_legacy_c_converter
4299            add_legacy_c_converter
4300            """.strip().split())
4301        module = globals()
4302        for name in module:
4303            for suffix, ids in (
4304                ("_return_converter", return_converters),
4305                ("_converter", converters),
4306            ):
4307                if name in ignored:
4308                    continue
4309                if name.endswith(suffix):
4310                    ids.append((name, name[:-len(suffix)]))
4311                    break
4312        print()
4313
4314        print("Legacy converters:")
4315        legacy = sorted(legacy_converters)
4316        print('    ' + ' '.join(c for c in legacy if c[0].isupper()))
4317        print('    ' + ' '.join(c for c in legacy if c[0].islower()))
4318        print()
4319
4320        for title, attribute, ids in (
4321            ("Converters", 'converter_init', converters),
4322            ("Return converters", 'return_converter_init', return_converters),
4323        ):
4324            print(title + ":")
4325            longest = -1
4326            for name, short_name in ids:
4327                longest = max(longest, len(short_name))
4328            for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
4329                cls = module[name]
4330                callable = getattr(cls, attribute, None)
4331                if not callable:
4332                    continue
4333                signature = inspect.signature(callable)
4334                parameters = []
4335                for parameter_name, parameter in signature.parameters.items():
4336                    if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
4337                        if parameter.default != inspect.Parameter.empty:
4338                            s = '{}={!r}'.format(parameter_name, parameter.default)
4339                        else:
4340                            s = parameter_name
4341                        parameters.append(s)
4342                print('    {}({})'.format(short_name, ', '.join(parameters)))
4343            print()
4344        print("All converters also accept (c_default=None, py_default=None, annotation=None).")
4345        print("All return converters also accept (py_default=None).")
4346        sys.exit(0)
4347
4348    if ns.make:
4349        if ns.output or ns.filename:
4350            print("Usage error: can't use -o or filenames with --make.")
4351            print()
4352            cmdline.print_usage()
4353            sys.exit(-1)
4354        for root, dirs, files in os.walk('.'):
4355            for rcs_dir in ('.svn', '.git', '.hg', 'build', 'externals'):
4356                if rcs_dir in dirs:
4357                    dirs.remove(rcs_dir)
4358            for filename in files:
4359                if not (filename.endswith('.c') or filename.endswith('.h')):
4360                    continue
4361                path = os.path.join(root, filename)
4362                if ns.verbose:
4363                    print(path)
4364                parse_file(path, force=ns.force, verify=not ns.force)
4365        return
4366
4367    if not ns.filename:
4368        cmdline.print_usage()
4369        sys.exit(-1)
4370
4371    if ns.output and len(ns.filename) > 1:
4372        print("Usage error: can't use -o with multiple filenames.")
4373        print()
4374        cmdline.print_usage()
4375        sys.exit(-1)
4376
4377    for filename in ns.filename:
4378        if ns.verbose:
4379            print(filename)
4380        parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
4381
4382
4383if __name__ == "__main__":
4384    sys.exit(main(sys.argv[1:]))
4385