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