blob: 8bf89777e79ffcbc6062f1f5ec34a3a520d87f0f [file] [log] [blame]
Larry Hastings31826802013-10-19 00:09:25 -07001#!/usr/bin/env python3
2#
3# Argument Clinic
4# Copyright 2012-2013 by Larry Hastings.
5# Licensed to the PSF under a contributor agreement.
6#
7
8import abc
9import ast
10import atexit
Larry Hastings31826802013-10-19 00:09:25 -070011import collections
12import contextlib
13import functools
14import hashlib
15import inspect
16import io
17import itertools
18import os
Larry Hastingsbebf7352014-01-17 17:47:17 -080019import pprint
Larry Hastings31826802013-10-19 00:09:25 -070020import re
21import shlex
22import sys
23import tempfile
24import textwrap
Georg Brandlaabebde2014-01-16 06:53:54 +010025import traceback
Larry Hastingsbebf7352014-01-17 17:47:17 -080026import uuid
Larry Hastings31826802013-10-19 00:09:25 -070027
Larry Hastings31826802013-10-19 00:09:25 -070028# TODO:
Larry Hastings31826802013-10-19 00:09:25 -070029#
30# soon:
31#
32# * allow mixing any two of {positional-only, positional-or-keyword,
33# keyword-only}
34# * dict constructor uses positional-only and keyword-only
35# * max and min use positional only with an optional group
36# and keyword-only
37#
Larry Hastings31826802013-10-19 00:09:25 -070038
Larry Hastingsebdcb502013-11-23 14:54:00 -080039version = '1'
40
Larry Hastings31826802013-10-19 00:09:25 -070041_empty = inspect._empty
42_void = inspect._void
43
Larry Hastings4a55fc52014-01-12 11:09:57 -080044NoneType = type(None)
Larry Hastings31826802013-10-19 00:09:25 -070045
46class Unspecified:
47 def __repr__(self):
48 return '<Unspecified>'
49
50unspecified = Unspecified()
51
52
53class Null:
54 def __repr__(self):
55 return '<Null>'
56
57NULL = Null()
58
59
Larry Hastings2a727912014-01-16 11:32:01 -080060class Unknown:
61 def __repr__(self):
62 return '<Unknown>'
63
64unknown = Unknown()
65
66
Larry Hastings31826802013-10-19 00:09:25 -070067def _text_accumulator():
68 text = []
69 def output():
70 s = ''.join(text)
71 text.clear()
72 return s
73 return text, text.append, output
74
75
76def text_accumulator():
77 """
78 Creates a simple text accumulator / joiner.
79
80 Returns a pair of callables:
81 append, output
82 "append" appends a string to the accumulator.
83 "output" returns the contents of the accumulator
84 joined together (''.join(accumulator)) and
85 empties the accumulator.
86 """
87 text, append, output = _text_accumulator()
88 return append, output
89
90
Larry Hastingsbebf7352014-01-17 17:47:17 -080091def warn_or_fail(fail=False, *args, filename=None, line_number=None):
Larry Hastings31826802013-10-19 00:09:25 -070092 joined = " ".join([str(a) for a in args])
93 add, output = text_accumulator()
Larry Hastingsbebf7352014-01-17 17:47:17 -080094 if fail:
95 add("Error")
96 else:
97 add("Warning")
Larry Hastings31826802013-10-19 00:09:25 -070098 if clinic:
99 if filename is None:
100 filename = clinic.filename
101 if clinic.block_parser and (line_number is None):
102 line_number = clinic.block_parser.line_number
103 if filename is not None:
104 add(' in file "' + filename + '"')
105 if line_number is not None:
106 add(" on line " + str(line_number))
107 add(':\n')
108 add(joined)
109 print(output())
Larry Hastingsbebf7352014-01-17 17:47:17 -0800110 if fail:
111 sys.exit(-1)
Larry Hastings31826802013-10-19 00:09:25 -0700112
113
Larry Hastingsbebf7352014-01-17 17:47:17 -0800114def warn(*args, filename=None, line_number=None):
115 return warn_or_fail(False, *args, filename=filename, line_number=line_number)
116
117def fail(*args, filename=None, line_number=None):
118 return warn_or_fail(True, *args, filename=filename, line_number=line_number)
119
Larry Hastings31826802013-10-19 00:09:25 -0700120
121def quoted_for_c_string(s):
122 for old, new in (
123 ('"', '\\"'),
124 ("'", "\\'"),
125 ):
126 s = s.replace(old, new)
127 return s
128
Larry Hastings4903e002014-01-18 00:26:16 -0800129def c_repr(s):
130 return '"' + s + '"'
131
132
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700133is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
134
135def is_legal_py_identifier(s):
136 return all(is_legal_c_identifier(field) for field in s.split('.'))
137
Larry Hastingsbebf7352014-01-17 17:47:17 -0800138# identifiers that are okay in Python but aren't a good idea in C.
139# so if they're used Argument Clinic will add "_value" to the end
140# of the name in C.
Larry Hastings31826802013-10-19 00:09:25 -0700141c_keywords = set("""
Larry Hastings5c661892014-01-24 06:17:25 -0800142asm auto break case char const continue default do double
143else enum extern float for goto if inline int long
144register return short signed sizeof static struct switch
Larry Hastingsbebf7352014-01-17 17:47:17 -0800145typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700146""".strip().split())
147
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700148def ensure_legal_c_identifier(s):
149 # for now, just complain if what we're given isn't legal
150 if not is_legal_c_identifier(s):
151 fail("Illegal C identifier: {}".format(s))
152 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700153 if s in c_keywords:
154 return s + "_value"
155 return s
156
157def rstrip_lines(s):
158 text, add, output = _text_accumulator()
159 for line in s.split('\n'):
160 add(line.rstrip())
161 add('\n')
162 text.pop()
163 return output()
164
165def linear_format(s, **kwargs):
166 """
167 Perform str.format-like substitution, except:
168 * The strings substituted must be on lines by
169 themselves. (This line is the "source line".)
170 * If the substitution text is empty, the source line
171 is removed in the output.
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800172 * If the field is not recognized, the original line
173 is passed unmodified through to the output.
Larry Hastings31826802013-10-19 00:09:25 -0700174 * If the substitution text is not empty:
175 * Each line of the substituted text is indented
176 by the indent of the source line.
177 * A newline will be added to the end.
178 """
179
180 add, output = text_accumulator()
181 for line in s.split('\n'):
182 indent, curly, trailing = line.partition('{')
183 if not curly:
184 add(line)
185 add('\n')
186 continue
187
188 name, curl, trailing = trailing.partition('}')
189 if not curly or name not in kwargs:
190 add(line)
191 add('\n')
192 continue
193
194 if trailing:
195 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
196 if indent.strip():
197 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
198
199 value = kwargs[name]
200 if not value:
201 continue
202
203 value = textwrap.indent(rstrip_lines(value), indent)
204 add(value)
205 add('\n')
206
207 return output()[:-1]
208
Larry Hastingsbebf7352014-01-17 17:47:17 -0800209def indent_all_lines(s, prefix):
210 """
211 Returns 's', with 'prefix' prepended to all lines.
212
213 If the last line is empty, prefix is not prepended
214 to it. (If s is blank, returns s unchanged.)
215
216 (textwrap.indent only adds to non-blank lines.)
217 """
218 split = s.split('\n')
219 last = split.pop()
220 final = []
221 for line in split:
222 final.append(prefix)
223 final.append(line)
224 final.append('\n')
225 if last:
226 final.append(prefix)
227 final.append(last)
228 return ''.join(final)
229
230def suffix_all_lines(s, suffix):
231 """
232 Returns 's', with 'suffix' appended to all lines.
233
234 If the last line is empty, suffix is not appended
235 to it. (If s is blank, returns s unchanged.)
236 """
237 split = s.split('\n')
238 last = split.pop()
239 final = []
240 for line in split:
241 final.append(line)
242 final.append(suffix)
243 final.append('\n')
244 if last:
245 final.append(last)
246 final.append(suffix)
247 return ''.join(final)
248
249
Larry Hastingsebdcb502013-11-23 14:54:00 -0800250def version_splitter(s):
251 """Splits a version string into a tuple of integers.
252
253 The following ASCII characters are allowed, and employ
254 the following conversions:
255 a -> -3
256 b -> -2
257 c -> -1
258 (This permits Python-style version strings such as "1.4b3".)
259 """
260 version = []
261 accumulator = []
262 def flush():
263 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800264 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800265 version.append(int(''.join(accumulator)))
266 accumulator.clear()
267
268 for c in s:
269 if c.isdigit():
270 accumulator.append(c)
271 elif c == '.':
272 flush()
273 elif c in 'abc':
274 flush()
275 version.append('abc'.index(c) - 3)
276 else:
277 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
278 flush()
279 return tuple(version)
280
281def version_comparitor(version1, version2):
282 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
283 for i, (a, b) in enumerate(iterator):
284 if a < b:
285 return -1
286 if a > b:
287 return 1
288 return 0
289
Larry Hastings31826802013-10-19 00:09:25 -0700290
291class CRenderData:
292 def __init__(self):
293
294 # The C statements to declare variables.
295 # Should be full lines with \n eol characters.
296 self.declarations = []
297
298 # The C statements required to initialize the variables before the parse call.
299 # Should be full lines with \n eol characters.
300 self.initializers = []
301
302 # The entries for the "keywords" array for PyArg_ParseTuple.
303 # Should be individual strings representing the names.
304 self.keywords = []
305
306 # The "format units" for PyArg_ParseTuple.
307 # Should be individual strings that will get
308 self.format_units = []
309
310 # The varargs arguments for PyArg_ParseTuple.
311 self.parse_arguments = []
312
313 # The parameter declarations for the impl function.
314 self.impl_parameters = []
315
316 # The arguments to the impl function at the time it's called.
317 self.impl_arguments = []
318
319 # For return converters: the name of the variable that
320 # should receive the value returned by the impl.
321 self.return_value = "return_value"
322
323 # For return converters: the code to convert the return
324 # value from the parse function. This is also where
325 # you should check the _return_value for errors, and
326 # "goto exit" if there are any.
327 self.return_conversion = []
328
329 # The C statements required to clean up after the impl call.
330 self.cleanup = []
331
332
333class Language(metaclass=abc.ABCMeta):
334
335 start_line = ""
336 body_prefix = ""
337 stop_line = ""
338 checksum_line = ""
339
340 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800341 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700342 pass
343
344 def validate(self):
345 def assert_only_one(field, token='dsl_name'):
346 line = getattr(self, field)
347 token = '{' + token + '}'
348 if len(line.split(token)) != 2:
349 fail(self.__class__.__name__ + " " + field + " must contain " + token + " exactly once!")
350 assert_only_one('start_line')
351 assert_only_one('stop_line')
352 assert_only_one('checksum_line')
353 assert_only_one('checksum_line', 'checksum')
354
355 if len(self.body_prefix.split('{dsl_name}')) >= 3:
356 fail(self.__class__.__name__ + " body_prefix may contain " + token + " once at most!")
357
358
359
360class PythonLanguage(Language):
361
362 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800363 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700364 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800365 stop_line = "#[{dsl_name} start generated code]*/"
366 checksum_line = "#/*[{dsl_name} end generated code: checksum={checksum}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700367
368
369def permute_left_option_groups(l):
370 """
371 Given [1, 2, 3], should yield:
372 ()
373 (3,)
374 (2, 3)
375 (1, 2, 3)
376 """
377 yield tuple()
378 accumulator = []
379 for group in reversed(l):
380 accumulator = list(group) + accumulator
381 yield tuple(accumulator)
382
383
384def permute_right_option_groups(l):
385 """
386 Given [1, 2, 3], should yield:
387 ()
388 (1,)
389 (1, 2)
390 (1, 2, 3)
391 """
392 yield tuple()
393 accumulator = []
394 for group in l:
395 accumulator.extend(group)
396 yield tuple(accumulator)
397
398
399def permute_optional_groups(left, required, right):
400 """
401 Generator function that computes the set of acceptable
402 argument lists for the provided iterables of
403 argument groups. (Actually it generates a tuple of tuples.)
404
405 Algorithm: prefer left options over right options.
406
407 If required is empty, left must also be empty.
408 """
409 required = tuple(required)
410 result = []
411
412 if not required:
413 assert not left
414
415 accumulator = []
416 counts = set()
417 for r in permute_right_option_groups(right):
418 for l in permute_left_option_groups(left):
419 t = l + required + r
420 if len(t) in counts:
421 continue
422 counts.add(len(t))
423 accumulator.append(t)
424
425 accumulator.sort(key=len)
426 return tuple(accumulator)
427
428
429class CLanguage(Language):
430
Larry Hastings61272b72014-01-07 12:41:53 -0800431 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700432 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800433 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700434 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800435 stop_line = "[{dsl_name} start generated code]*/"
436 checksum_line = "/*[{dsl_name} end generated code: checksum={checksum}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700437
Larry Hastingsbebf7352014-01-17 17:47:17 -0800438 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700439 function = None
440 for o in signatures:
441 if isinstance(o, Function):
442 if function:
443 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
444 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800445 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700446
447 def docstring_for_c_string(self, f):
448 text, add, output = _text_accumulator()
449 # turn docstring into a properly quoted C string
450 for line in f.docstring.split('\n'):
451 add('"')
452 add(quoted_for_c_string(line))
453 add('\\n"\n')
454
455 text.pop()
456 add('"')
457 return ''.join(text)
458
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800459 _templates = {}
460 # the templates will be run through str.format(),
461 # so actual curly-braces need to be doubled up.
462 templates_source = """
463__________________________________________________
464
465docstring_prototype
466
467PyDoc_VAR({c_basename}__doc__);
468__________________________________________________
469
470docstring_definition
471
472PyDoc_STRVAR({c_basename}__doc__,
473{docstring});
474__________________________________________________
475
476impl_definition
477
478static {impl_return_type}
479{c_basename}_impl({impl_parameters})
480__________________________________________________
481
482parser_prototype_noargs
483
484static PyObject *
485{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
486__________________________________________________
487
488parser_prototype_meth_o
489
490# SLIGHT HACK
491# METH_O uses {impl_parameters} for the parser!
492
493static PyObject *
494{c_basename}({impl_parameters})
495__________________________________________________
496
497parser_prototype_varargs
498
499static PyObject *
500{c_basename}({self_type}{self_name}, PyObject *args)
501__________________________________________________
502
503parser_prototype_keyword
504
505static PyObject *
506{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
507__________________________________________________
508
509parser_prototype_init
510
511static int
512{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
513__________________________________________________
514
515parser_definition_simple_no_parsing
516
517{{
518 return {c_basename}_impl({impl_arguments});
519}}
520__________________________________________________
521
522parser_definition_start
523
524{{
525 {return_value_declaration}
526 {declarations}
527 {initializers}
528{empty line}
529__________________________________________________
530
531parser_definition_end
532
533 {return_conversion}
534
535{exit_label}
536 {cleanup}
537 return return_value;
538}}
539__________________________________________________
540
541parser_definition_impl_call
542
543 {return_value} = {c_basename}_impl({impl_arguments});
544__________________________________________________
545
546parser_definition_unpack_tuple
547
548 if (!PyArg_UnpackTuple(args, "{name}",
549 {unpack_min}, {unpack_max},
550 {parse_arguments}))
551 goto exit;
552__________________________________________________
553
554parser_definition_parse_tuple
555
556 if (!PyArg_ParseTuple(args,
557 "{format_units}:{name}",
558 {parse_arguments}))
559 goto exit;
560__________________________________________________
561
562parser_definition_option_groups
563 {option_group_parsing}
564
565__________________________________________________
566
567parser_definition_parse_tuple_and_keywords
568
569 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
570 "{format_units}:{name}", _keywords,
571 {parse_arguments}))
572 goto exit;
573__________________________________________________
574
575parser_definition_no_positional
576
577 if (!_PyArg_NoPositional("{name}", args))
578 goto exit;
579
580__________________________________________________
581
582parser_definition_no_keywords
583
584 if (!_PyArg_NoKeywords("{name}", kwargs))
585 goto exit;
586
587__________________________________________________
588
589methoddef_define
590
591#define {methoddef_name} \\
592 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
593__________________________________________________
594""".rstrip()
595
596 title = ''
597 buffer = []
598 line = None
599 for line in templates_source.split('\n'):
600 line = line.rstrip()
601 if line.startswith('# '):
602 # comment
603 continue
604 if line.startswith("_____"):
605 if not buffer:
606 continue
607 assert title not in _templates, "defined template twice: " + repr(title)
608 buffer = '\n'.join(buffer).rstrip()
609 buffer = buffer.replace('{empty line}', '')
610 _templates[title] = buffer
611 buffer = []
612 title = ''
613 continue
614 if not title:
615 if not line:
616 continue
617 title = line
618 continue
619 if not (line or buffer):
620 # throw away leading blank lines
621 continue
622 buffer.append(line)
623
624 assert not title, 'ensure templates_source ends with ______ (still adding to ' + repr(title) + ")"
625
626 del templates_source
627 del title
628 del buffer
629 del line
630
631 # for name, value in _templates.items():
632 # print(name + ":")
633 # pprint.pprint(value)
634 # print()
Larry Hastings31826802013-10-19 00:09:25 -0700635
Larry Hastingsbebf7352014-01-17 17:47:17 -0800636 def output_templates(self, f):
637 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800638 assert parameters
639 assert isinstance(parameters[0].converter, self_converter)
640 del parameters[0]
Larry Hastingsbebf7352014-01-17 17:47:17 -0800641 converters = [p.converter for p in parameters]
642
643 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
644 default_return_converter = (not f.return_converter or
645 f.return_converter.type == 'PyObject *')
646
647 positional = parameters and (parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY)
648 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
649 first_optional = len(parameters)
650 for i, p in enumerate(parameters):
651 c = p.converter
652 if type(c) != object_converter:
653 break
654 if c.format_unit != 'O':
655 break
656 if p.default is not unspecified:
657 first_optional = min(first_optional, i)
658 else:
659 all_boring_objects = True
660
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800661 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
662
Larry Hastingsbebf7352014-01-17 17:47:17 -0800663 meth_o = (len(parameters) == 1 and
664 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
665 not converters[0].is_optional() and
666 isinstance(converters[0], object_converter) and
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800667 converters[0].format_unit == 'O' and
668 not new_or_init)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800669
670 # we have to set seven things before we're done:
671 #
672 # docstring_prototype
673 # docstring_definition
674 # impl_prototype
675 # methoddef_define
676 # parser_prototype
677 # parser_definition
678 # impl_definition
Larry Hastingsbebf7352014-01-17 17:47:17 -0800679
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800680 templates = self._templates
Larry Hastingsbebf7352014-01-17 17:47:17 -0800681
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800682 return_value_declaration = "PyObject *return_value = NULL;"
Larry Hastings31826802013-10-19 00:09:25 -0700683
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800684 methoddef_define = templates['methoddef_define']
Larry Hastings5c661892014-01-24 06:17:25 -0800685 if new_or_init and not f.docstring:
686 docstring_prototype = docstring_definition = ''
687 else:
688 docstring_prototype = templates['docstring_prototype']
689 docstring_definition = templates['docstring_definition']
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800690 impl_definition = templates['impl_definition']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800691 impl_prototype = parser_prototype = parser_definition = None
692
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800693 parser_body_fields = None
694 def parser_body(prototype, *fields):
695 nonlocal parser_body_fields
696 add, output = text_accumulator()
697 add(prototype)
698 parser_body_fields = fields
699 fields = list(fields)
700 fields.insert(0, 'parser_definition_start')
701 fields.append('parser_definition_impl_call')
702 fields.append('parser_definition_end')
703 for field in fields:
704 add('\n')
705 add(templates[field])
706 return output()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800707
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800708 def insert_keywords(s):
709 return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
Larry Hastingsbebf7352014-01-17 17:47:17 -0800710
711 if not parameters:
712 # no parameters, METH_NOARGS
713
714 flags = "METH_NOARGS"
715
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800716 parser_prototype = templates['parser_prototype_noargs']
717 parser_definition = parser_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800718
719 if default_return_converter:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800720 parser_definition = parser_prototype + '\n' + templates['parser_definition_simple_no_parsing']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800721 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800722 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700723
Larry Hastingsbebf7352014-01-17 17:47:17 -0800724 elif meth_o:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800725 flags = "METH_O"
726 # impl_definition = templates['parser_prototype_meth_o']
727
Larry Hastingsbebf7352014-01-17 17:47:17 -0800728 if default_return_converter:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800729 # maps perfectly to METH_O, doesn't need a return converter.
730 # so we skip making a parse function
731 # and call directly into the impl function.
Larry Hastingsbebf7352014-01-17 17:47:17 -0800732 impl_prototype = parser_prototype = parser_definition = ''
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800733 impl_definition = templates['parser_prototype_meth_o']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800734 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800735 parser_prototype = templates['parser_prototype_meth_o']
736 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700737
Larry Hastingsbebf7352014-01-17 17:47:17 -0800738 elif has_option_groups:
739 # positional parameters with option groups
740 # (we have to generate lots of PyArg_ParseTuple calls
741 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700742
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800743 flags = "METH_VARARGS"
744 parser_prototype = templates['parser_prototype_varargs']
Larry Hastings31826802013-10-19 00:09:25 -0700745
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800746 parser_definition = parser_body(parser_prototype, 'parser_definition_option_groups')
Larry Hastings31826802013-10-19 00:09:25 -0700747
Larry Hastingsbebf7352014-01-17 17:47:17 -0800748 elif positional and all_boring_objects:
749 # positional-only, but no option groups,
750 # and nothing but normal objects:
751 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700752
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800753 flags = "METH_VARARGS"
754 parser_prototype = templates['parser_prototype_varargs']
Larry Hastings31826802013-10-19 00:09:25 -0700755
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800756 parser_definition = parser_body(parser_prototype, 'parser_definition_unpack_tuple')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800757
758 elif positional:
759 # positional-only, but no option groups
760 # we only need one call to PyArg_ParseTuple
761
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800762 flags = "METH_VARARGS"
763 parser_prototype = templates['parser_prototype_varargs']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800764
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800765 parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800766
767 else:
768 # positional-or-keyword arguments
769 flags = "METH_VARARGS|METH_KEYWORDS"
770
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800771 parser_prototype = templates['parser_prototype_keyword']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800772
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800773 parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple_and_keywords')
774 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700775
Larry Hastings31826802013-10-19 00:09:25 -0700776
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800777 if new_or_init:
778 methoddef_define = ''
779
780 if f.kind == METHOD_NEW:
781 parser_prototype = templates['parser_prototype_keyword']
782 else:
783 return_value_declaration = "int return_value = -1;"
784 parser_prototype = templates['parser_prototype_init']
785
786 fields = list(parser_body_fields)
787 parses_positional = 'METH_NOARGS' not in flags
788 parses_keywords = 'METH_KEYWORDS' in flags
789 if parses_keywords:
790 assert parses_positional
791
792 if not parses_keywords:
793 fields.insert(0, 'parser_definition_no_keywords')
794 if not parses_positional:
795 fields.insert(0, 'parser_definition_no_positional')
796
797 parser_definition = parser_body(parser_prototype, *fields)
798 if parses_keywords:
799 parser_definition = insert_keywords(parser_definition)
800
Larry Hastings31826802013-10-19 00:09:25 -0700801
Larry Hastingsbebf7352014-01-17 17:47:17 -0800802 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800803 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700804
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800805 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700806
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800807 # add ';' to the end of parser_prototype and impl_prototype
808 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800809 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800810 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800811 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800812 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700813
Larry Hastingsbebf7352014-01-17 17:47:17 -0800814 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800815 impl_prototype = impl_definition
816 if impl_prototype:
817 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700818
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800819 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800820
821 d = {
822 "docstring_prototype" : docstring_prototype,
823 "docstring_definition" : docstring_definition,
824 "impl_prototype" : impl_prototype,
825 "methoddef_define" : methoddef_define,
826 "parser_prototype" : parser_prototype,
827 "parser_definition" : parser_definition,
828 "impl_definition" : impl_definition,
829 }
830
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800831 # make sure we didn't forget to assign something,
832 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -0800833 d2 = {}
834 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800835 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800836 if value:
837 value = '\n' + value + '\n'
838 d2[name] = value
839 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700840
841 @staticmethod
842 def group_to_variable_name(group):
843 adjective = "left_" if group < 0 else "right_"
844 return "group_" + adjective + str(abs(group))
845
846 def render_option_group_parsing(self, f, template_dict):
847 # positional only, grouped, optional arguments!
848 # can be optional on the left or right.
849 # here's an example:
850 #
851 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
852 #
853 # Here group D are required, and all other groups are optional.
854 # (Group D's "group" is actually None.)
855 # We can figure out which sets of arguments we have based on
856 # how many arguments are in the tuple.
857 #
858 # Note that you need to count up on both sides. For example,
859 # you could have groups C+D, or C+D+E, or C+D+E+F.
860 #
861 # What if the number of arguments leads us to an ambiguous result?
862 # Clinic prefers groups on the left. So in the above example,
863 # five arguments would map to B+C, not C+D.
864
865 add, output = text_accumulator()
866 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800867 if isinstance(parameters[0].converter, self_converter):
868 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -0700869
870 groups = []
871 group = None
872 left = []
873 right = []
874 required = []
875 last = unspecified
876
877 for p in parameters:
878 group_id = p.group
879 if group_id != last:
880 last = group_id
881 group = []
882 if group_id < 0:
883 left.append(group)
884 elif group_id == 0:
885 group = required
886 else:
887 right.append(group)
888 group.append(p)
889
890 count_min = sys.maxsize
891 count_max = -1
892
Larry Hastings2a727912014-01-16 11:32:01 -0800893 add("switch (PyTuple_GET_SIZE(args)) {{\n")
Larry Hastings31826802013-10-19 00:09:25 -0700894 for subset in permute_optional_groups(left, required, right):
895 count = len(subset)
896 count_min = min(count_min, count)
897 count_max = max(count_max, count)
898
Larry Hastings583baa82014-01-12 08:49:30 -0800899 if count == 0:
900 add(""" case 0:
901 break;
902""")
903 continue
904
Larry Hastings31826802013-10-19 00:09:25 -0700905 group_ids = {p.group for p in subset} # eliminate duplicates
906 d = {}
907 d['count'] = count
908 d['name'] = f.name
909 d['groups'] = sorted(group_ids)
910 d['format_units'] = "".join(p.converter.format_unit for p in subset)
911
912 parse_arguments = []
913 for p in subset:
914 p.converter.parse_argument(parse_arguments)
915 d['parse_arguments'] = ", ".join(parse_arguments)
916
917 group_ids.discard(0)
918 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
919 lines = "\n".join(lines)
920
921 s = """
922 case {count}:
923 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
Larry Hastings46258262014-01-22 03:05:49 -0800924 goto exit;
Larry Hastings31826802013-10-19 00:09:25 -0700925 {group_booleans}
926 break;
927"""[1:]
928 s = linear_format(s, group_booleans=lines)
929 s = s.format_map(d)
930 add(s)
931
932 add(" default:\n")
933 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
934 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -0800935 add(' goto exit;\n')
Larry Hastings31826802013-10-19 00:09:25 -0700936 add("}}")
937 template_dict['option_group_parsing'] = output()
938
Larry Hastingsbebf7352014-01-17 17:47:17 -0800939 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -0700940 if not f:
941 return ""
942
943 add, output = text_accumulator()
944 data = CRenderData()
945
Larry Hastings31826802013-10-19 00:09:25 -0700946 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800947 assert parameters, "We should always have a 'self' at this point!"
948
Larry Hastings31826802013-10-19 00:09:25 -0700949 converters = [p.converter for p in parameters]
950
Larry Hastings5c661892014-01-24 06:17:25 -0800951 templates = self.output_templates(f)
952
953 f_self = parameters[0]
954 selfless = parameters[1:]
955 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
956
957 last_group = 0
958 first_optional = len(selfless)
959 positional = selfless and selfless[-1].kind == inspect.Parameter.POSITIONAL_ONLY
960 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
961 default_return_converter = (not f.return_converter or
962 f.return_converter.type == 'PyObject *')
963 has_option_groups = False
964
965 # offset i by -1 because first_optional needs to ignore self
966 for i, p in enumerate(parameters, -1):
967 c = p.converter
968
969 if (i != -1) and (p.default is not unspecified):
970 first_optional = min(first_optional, i)
971
972 # insert group variable
973 group = p.group
974 if last_group != group:
975 last_group = group
976 if group:
977 group_name = self.group_to_variable_name(group)
978 data.impl_arguments.append(group_name)
979 data.declarations.append("int " + group_name + " = 0;")
980 data.impl_parameters.append("int " + group_name)
981 has_option_groups = True
982
983 c.render(p, data)
984
985 if has_option_groups and (not positional):
986 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
987
988 # HACK
989 # when we're METH_O, but have a custom return converter,
990 # we use "impl_parameters" for the parsing function
991 # because that works better. but that means we must
992 # supress actually declaring the impl's parameters
993 # as variables in the parsing function. but since it's
994 # METH_O, we have exactly one anyway, so we know exactly
995 # where it is.
996 if ("METH_O" in templates['methoddef_define'] and
997 not default_return_converter):
998 data.declarations.pop(0)
999
Larry Hastings31826802013-10-19 00:09:25 -07001000 template_dict = {}
1001
1002 full_name = f.full_name
1003 template_dict['full_name'] = full_name
1004
Larry Hastings5c661892014-01-24 06:17:25 -08001005 if new_or_init:
1006 name = f.cls.name
1007 else:
1008 name = f.name
1009
Larry Hastings31826802013-10-19 00:09:25 -07001010 template_dict['name'] = name
1011
Larry Hastings8666e652014-01-12 14:12:59 -08001012 if f.c_basename:
1013 c_basename = f.c_basename
1014 else:
1015 fields = full_name.split(".")
1016 if fields[-1] == '__new__':
1017 fields.pop()
1018 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001019
Larry Hastings31826802013-10-19 00:09:25 -07001020 template_dict['c_basename'] = c_basename
1021
1022 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1023 template_dict['methoddef_name'] = methoddef_name
1024
1025 template_dict['docstring'] = self.docstring_for_c_string(f)
1026
Larry Hastings5c661892014-01-24 06:17:25 -08001027 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001028
Larry Hastings31826802013-10-19 00:09:25 -07001029 f.return_converter.render(f, data)
1030 template_dict['impl_return_type'] = f.return_converter.type
1031
1032 template_dict['declarations'] = "\n".join(data.declarations)
1033 template_dict['initializers'] = "\n\n".join(data.initializers)
1034 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1035 template_dict['format_units'] = ''.join(data.format_units)
1036 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1037 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1038 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
1039 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
1040 template_dict['cleanup'] = "".join(data.cleanup)
1041 template_dict['return_value'] = data.return_value
1042
Larry Hastings5c661892014-01-24 06:17:25 -08001043 # used by unpack tuple code generator
1044 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1045 unpack_min = first_optional
1046 unpack_max = len(selfless)
1047 template_dict['unpack_min'] = str(unpack_min)
1048 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001049
Larry Hastingsbebf7352014-01-17 17:47:17 -08001050 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001051 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001052
Larry Hastingsbebf7352014-01-17 17:47:17 -08001053 for name, destination in clinic.field_destinations.items():
1054 template = templates[name]
1055 if has_option_groups:
1056 template = linear_format(template,
1057 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001058 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001059 declarations=template_dict['declarations'],
1060 return_conversion=template_dict['return_conversion'],
1061 initializers=template_dict['initializers'],
1062 cleanup=template_dict['cleanup'],
1063 )
Larry Hastings31826802013-10-19 00:09:25 -07001064
Larry Hastingsbebf7352014-01-17 17:47:17 -08001065 # Only generate the "exit:" label
1066 # if we have any gotos
1067 need_exit_label = "goto exit;" in template
1068 template = linear_format(template,
1069 exit_label="exit:" if need_exit_label else ''
1070 )
Larry Hastings31826802013-10-19 00:09:25 -07001071
Larry Hastingsbebf7352014-01-17 17:47:17 -08001072 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001073
Larry Hastingsbebf7352014-01-17 17:47:17 -08001074 if clinic.line_prefix:
1075 s = indent_all_lines(s, clinic.line_prefix)
1076 if clinic.line_suffix:
1077 s = suffix_all_lines(s, clinic.line_suffix)
1078
1079 destination.append(s)
1080
1081 return clinic.get_destination('block').dump()
1082
Larry Hastings31826802013-10-19 00:09:25 -07001083
1084
Larry Hastings5c661892014-01-24 06:17:25 -08001085
Larry Hastings31826802013-10-19 00:09:25 -07001086@contextlib.contextmanager
1087def OverrideStdioWith(stdout):
1088 saved_stdout = sys.stdout
1089 sys.stdout = stdout
1090 try:
1091 yield
1092 finally:
1093 assert sys.stdout is stdout
1094 sys.stdout = saved_stdout
1095
1096
1097def create_regex(before, after):
1098 """Create an re object for matching marker lines."""
1099 pattern = r'^{}(\w+){}$'
1100 return re.compile(pattern.format(re.escape(before), re.escape(after)))
1101
1102
1103class Block:
1104 r"""
1105 Represents a single block of text embedded in
1106 another file. If dsl_name is None, the block represents
1107 verbatim text, raw original text from the file, in
1108 which case "input" will be the only non-false member.
1109 If dsl_name is not None, the block represents a Clinic
1110 block.
1111
1112 input is always str, with embedded \n characters.
1113 input represents the original text from the file;
1114 if it's a Clinic block, it is the original text with
1115 the body_prefix and redundant leading whitespace removed.
1116
1117 dsl_name is either str or None. If str, it's the text
1118 found on the start line of the block between the square
1119 brackets.
1120
1121 signatures is either list or None. If it's a list,
1122 it may only contain clinic.Module, clinic.Class, and
1123 clinic.Function objects. At the moment it should
1124 contain at most one of each.
1125
1126 output is either str or None. If str, it's the output
1127 from this block, with embedded '\n' characters.
1128
1129 indent is either str or None. It's the leading whitespace
1130 that was found on every line of input. (If body_prefix is
1131 not empty, this is the indent *after* removing the
1132 body_prefix.)
1133
1134 preindent is either str or None. It's the whitespace that
1135 was found in front of every line of input *before* the
1136 "body_prefix" (see the Language object). If body_prefix
1137 is empty, preindent must always be empty too.
1138
1139 To illustrate indent and preindent: Assume that '_'
1140 represents whitespace. If the block processed was in a
1141 Python file, and looked like this:
1142 ____#/*[python]
1143 ____#__for a in range(20):
1144 ____#____print(a)
1145 ____#[python]*/
1146 "preindent" would be "____" and "indent" would be "__".
1147
1148 """
1149 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1150 assert isinstance(input, str)
1151 self.input = input
1152 self.dsl_name = dsl_name
1153 self.signatures = signatures or []
1154 self.output = output
1155 self.indent = indent
1156 self.preindent = preindent
1157
1158
1159class BlockParser:
1160 """
1161 Block-oriented parser for Argument Clinic.
1162 Iterator, yields Block objects.
1163 """
1164
1165 def __init__(self, input, language, *, verify=True):
1166 """
1167 "input" should be a str object
1168 with embedded \n characters.
1169
1170 "language" should be a Language object.
1171 """
1172 language.validate()
1173
1174 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1175 self.block_start_line_number = self.line_number = 0
1176
1177 self.language = language
1178 before, _, after = language.start_line.partition('{dsl_name}')
1179 assert _ == '{dsl_name}'
1180 self.start_re = create_regex(before, after)
1181 self.verify = verify
1182 self.last_checksum_re = None
1183 self.last_dsl_name = None
1184 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001185 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001186
1187 def __iter__(self):
1188 return self
1189
1190 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001191 while True:
1192 if not self.input:
1193 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001194
Larry Hastingsbebf7352014-01-17 17:47:17 -08001195 if self.dsl_name:
1196 return_value = self.parse_clinic_block(self.dsl_name)
1197 self.dsl_name = None
1198 self.first_block = False
1199 return return_value
1200 block = self.parse_verbatim_block()
1201 if self.first_block and not block.input:
1202 continue
1203 self.first_block = False
1204 return block
1205
Larry Hastings31826802013-10-19 00:09:25 -07001206
1207 def is_start_line(self, line):
1208 match = self.start_re.match(line.lstrip())
1209 return match.group(1) if match else None
1210
1211 def _line(self):
1212 self.line_number += 1
1213 return self.input.pop()
1214
1215 def parse_verbatim_block(self):
1216 add, output = text_accumulator()
1217 self.block_start_line_number = self.line_number
1218
1219 while self.input:
1220 line = self._line()
1221 dsl_name = self.is_start_line(line)
1222 if dsl_name:
1223 self.dsl_name = dsl_name
1224 break
1225 add(line)
1226
1227 return Block(output())
1228
1229 def parse_clinic_block(self, dsl_name):
1230 input_add, input_output = text_accumulator()
1231 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001232 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001233 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1234
Larry Hastings90261132014-01-07 12:21:08 -08001235 def is_stop_line(line):
1236 # make sure to recognize stop line even if it
1237 # doesn't end with EOL (it could be the very end of the file)
1238 if not line.startswith(stop_line):
1239 return False
1240 remainder = line[len(stop_line):]
1241 return (not remainder) or remainder.isspace()
1242
Larry Hastings31826802013-10-19 00:09:25 -07001243 # consume body of program
1244 while self.input:
1245 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001246 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001247 break
1248 if body_prefix:
1249 line = line.lstrip()
1250 assert line.startswith(body_prefix)
1251 line = line[len(body_prefix):]
1252 input_add(line)
1253
1254 # consume output and checksum line, if present.
1255 if self.last_dsl_name == dsl_name:
1256 checksum_re = self.last_checksum_re
1257 else:
1258 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, checksum='{checksum}').partition('{checksum}')
1259 assert _ == '{checksum}'
1260 checksum_re = create_regex(before, after)
1261 self.last_dsl_name = dsl_name
1262 self.last_checksum_re = checksum_re
1263
1264 # scan forward for checksum line
1265 output_add, output_output = text_accumulator()
1266 checksum = None
1267 while self.input:
1268 line = self._line()
1269 match = checksum_re.match(line.lstrip())
1270 checksum = match.group(1) if match else None
1271 if checksum:
1272 break
1273 output_add(line)
1274 if self.is_start_line(line):
1275 break
1276
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001277 output = output_output()
Larry Hastings31826802013-10-19 00:09:25 -07001278 if checksum:
Larry Hastings31826802013-10-19 00:09:25 -07001279 if self.verify:
1280 computed = compute_checksum(output)
1281 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001282 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1283 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001284 "the end marker,\n"
1285 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001286 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001287 else:
1288 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001289 output_lines = output.splitlines(keepends=True)
1290 self.line_number -= len(output_lines)
1291 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001292 output = None
1293
1294 return Block(input_output(), dsl_name, output=output)
1295
1296
1297class BlockPrinter:
1298
1299 def __init__(self, language, f=None):
1300 self.language = language
1301 self.f = f or io.StringIO()
1302
1303 def print_block(self, block):
1304 input = block.input
1305 output = block.output
1306 dsl_name = block.dsl_name
1307 write = self.f.write
1308
Larry Hastings31826802013-10-19 00:09:25 -07001309 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1310
1311 if not dsl_name:
1312 write(input)
1313 return
1314
1315 write(self.language.start_line.format(dsl_name=dsl_name))
1316 write("\n")
1317
1318 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1319 if not body_prefix:
1320 write(input)
1321 else:
1322 for line in input.split('\n'):
1323 write(body_prefix)
1324 write(line)
1325 write("\n")
1326
1327 write(self.language.stop_line.format(dsl_name=dsl_name))
1328 write("\n")
1329
Larry Hastingsbebf7352014-01-17 17:47:17 -08001330 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001331 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001332 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001333 output += '\n'
1334 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001335
1336 write(self.language.checksum_line.format(dsl_name=dsl_name, checksum=compute_checksum(output)))
1337 write("\n")
1338
Larry Hastingsbebf7352014-01-17 17:47:17 -08001339 def write(self, text):
1340 self.f.write(text)
1341
1342
1343class Destination:
1344 def __init__(self, name, type, clinic, *args):
1345 self.name = name
1346 self.type = type
1347 self.clinic = clinic
1348 valid_types = ('buffer', 'file', 'suppress', 'two-pass')
1349 if type not in valid_types:
1350 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1351 extra_arguments = 1 if type == "file" else 0
1352 if len(args) < extra_arguments:
1353 fail("Not enough arguments for destination " + name + " new " + type)
1354 if len(args) > extra_arguments:
1355 fail("Too many arguments for destination " + name + " new " + type)
1356 if type =='file':
1357 d = {}
1358 d['filename'] = filename = clinic.filename
1359 d['basename'], d['extension'] = os.path.splitext(filename)
1360 self.filename = args[0].format_map(d)
1361 if type == 'two-pass':
1362 self.id = None
1363
1364 self.text, self.append, self._dump = _text_accumulator()
1365
1366 def __repr__(self):
1367 if self.type == 'file':
1368 file_repr = " " + repr(self.filename)
1369 else:
1370 file_repr = ''
1371 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1372
1373 def clear(self):
1374 if self.type != 'buffer':
1375 fail("Can't clear destination" + self.name + " , it's not of type buffer")
1376 self.text.clear()
1377
1378 def dump(self):
1379 if self.type == 'two-pass':
1380 if self.id is None:
1381 self.id = str(uuid.uuid4())
1382 return self.id
1383 fail("You can only dump a two-pass buffer exactly once!")
1384 return self._dump()
1385
Larry Hastings31826802013-10-19 00:09:25 -07001386
1387# maps strings to Language objects.
1388# "languages" maps the name of the language ("C", "Python").
1389# "extensions" maps the file extension ("c", "py").
1390languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001391extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1392extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001393
1394
1395# maps strings to callables.
1396# these callables must be of the form:
1397# def foo(name, default, *, ...)
1398# The callable may have any number of keyword-only parameters.
1399# The callable must return a CConverter object.
1400# The callable should not call builtins.print.
1401converters = {}
1402
1403# maps strings to callables.
1404# these callables follow the same rules as those for "converters" above.
1405# note however that they will never be called with keyword-only parameters.
1406legacy_converters = {}
1407
1408
1409# maps strings to callables.
1410# these callables must be of the form:
1411# def foo(*, ...)
1412# The callable may have any number of keyword-only parameters.
1413# The callable must return a CConverter object.
1414# The callable should not call builtins.print.
1415return_converters = {}
1416
1417class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001418
1419 presets_text = """
1420preset original
1421everything block
1422docstring_prototype suppress
1423parser_prototype suppress
1424
1425preset file
1426everything file
1427docstring_prototype suppress
1428parser_prototype suppress
1429impl_definition block
1430
1431preset buffer
1432everything buffer
1433docstring_prototype suppress
1434impl_prototype suppress
1435parser_prototype suppress
1436impl_definition block
1437
1438preset partial-buffer
1439everything buffer
1440docstring_prototype block
1441impl_prototype suppress
1442methoddef_define block
1443parser_prototype block
1444impl_definition block
1445
1446preset two-pass
1447everything buffer
1448docstring_prototype two-pass
1449impl_prototype suppress
1450methoddef_define two-pass
1451parser_prototype two-pass
1452impl_definition block
1453
1454"""
1455
Larry Hastings31826802013-10-19 00:09:25 -07001456 def __init__(self, language, printer=None, *, verify=True, filename=None):
1457 # maps strings to Parser objects.
1458 # (instantiated from the "parsers" global.)
1459 self.parsers = {}
1460 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001461 if printer:
1462 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001463 self.printer = printer or BlockPrinter(language)
1464 self.verify = verify
1465 self.filename = filename
1466 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001467 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001468 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001469
Larry Hastingsbebf7352014-01-17 17:47:17 -08001470 self.line_prefix = self.line_suffix = ''
1471
1472 self.destinations = {}
1473 self.add_destination("block", "buffer")
1474 self.add_destination("suppress", "suppress")
1475 self.add_destination("buffer", "buffer")
1476 self.add_destination("two-pass", "two-pass")
1477 if filename:
1478 self.add_destination("file", "file", "{basename}.clinic{extension}")
1479
1480 d = self.destinations.get
1481 self.field_destinations = collections.OrderedDict((
1482 ('docstring_prototype', d('suppress')),
1483 ('docstring_definition', d('block')),
1484 ('methoddef_define', d('block')),
1485 ('impl_prototype', d('block')),
1486 ('parser_prototype', d('suppress')),
1487 ('parser_definition', d('block')),
1488 ('impl_definition', d('block')),
1489 ))
1490
1491 self.field_destinations_stack = []
1492
1493 self.presets = {}
1494 preset = None
1495 for line in self.presets_text.strip().split('\n'):
1496 line = line.strip()
1497 if not line:
1498 continue
1499 name, value = line.split()
1500 if name == 'preset':
1501 self.presets[value] = preset = collections.OrderedDict()
1502 continue
1503
1504 destination = self.get_destination(value)
1505
1506 if name == 'everything':
1507 for name in self.field_destinations:
1508 preset[name] = destination
1509 continue
1510
1511 assert name in self.field_destinations
1512 preset[name] = destination
1513
Larry Hastings31826802013-10-19 00:09:25 -07001514 global clinic
1515 clinic = self
1516
Larry Hastingsbebf7352014-01-17 17:47:17 -08001517 def get_destination(self, name, default=unspecified):
1518 d = self.destinations.get(name)
1519 if not d:
1520 if default is not unspecified:
1521 return default
1522 fail("Destination does not exist: " + repr(name))
1523 return d
1524
1525 def add_destination(self, name, type, *args):
1526 if name in self.destinations:
1527 fail("Destination already exists: " + repr(name))
1528 self.destinations[name] = Destination(name, type, self, *args)
1529
Larry Hastings31826802013-10-19 00:09:25 -07001530 def parse(self, input):
1531 printer = self.printer
1532 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1533 for block in self.block_parser:
1534 dsl_name = block.dsl_name
1535 if dsl_name:
1536 if dsl_name not in self.parsers:
1537 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1538 self.parsers[dsl_name] = parsers[dsl_name](self)
1539 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001540 try:
1541 parser.parse(block)
1542 except Exception:
1543 fail('Exception raised during parsing:\n' +
1544 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001545 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001546
1547 second_pass_replacements = {}
1548
1549 for name, destination in self.destinations.items():
1550 if destination.type == 'suppress':
1551 continue
1552 output = destination._dump()
1553
1554 if destination.type == 'two-pass':
1555 if destination.id:
1556 second_pass_replacements[destination.id] = output
1557 elif output:
1558 fail("Two-pass buffer " + repr(name) + " not empty at end of file!")
1559 continue
1560
1561 if output:
1562
1563 block = Block("", dsl_name="clinic", output=output)
1564
1565 if destination.type == 'buffer':
1566 block.input = "dump " + name + "\n"
1567 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1568 printer.write("\n")
1569 printer.print_block(block)
1570 continue
1571
1572 if destination.type == 'file':
1573 try:
1574 with open(destination.filename, "rt") as f:
1575 parser_2 = BlockParser(f.read(), language=self.language)
1576 blocks = list(parser_2)
1577 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1578 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
1579 except FileNotFoundError:
1580 pass
1581
1582 block.input = 'preserve\n'
1583 printer_2 = BlockPrinter(self.language)
1584 printer_2.print_block(block)
1585 with open(destination.filename, "wt") as f:
1586 f.write(printer_2.f.getvalue())
1587 continue
1588 text = printer.f.getvalue()
1589
1590 if second_pass_replacements:
1591 printer_2 = BlockPrinter(self.language)
1592 parser_2 = BlockParser(text, self.language)
1593 changed = False
1594 for block in parser_2:
1595 if block.dsl_name:
1596 for id, replacement in second_pass_replacements.items():
1597 if id in block.output:
1598 changed = True
1599 block.output = block.output.replace(id, replacement)
1600 printer_2.print_block(block)
1601 if changed:
1602 text = printer_2.f.getvalue()
1603
1604 return text
1605
Larry Hastings31826802013-10-19 00:09:25 -07001606
1607 def _module_and_class(self, fields):
1608 """
1609 fields should be an iterable of field names.
1610 returns a tuple of (module, class).
1611 the module object could actually be self (a clinic object).
1612 this function is only ever used to find the parent of where
1613 a new class/module should go.
1614 """
1615 in_classes = False
1616 parent = module = self
1617 cls = None
1618 so_far = []
1619
1620 for field in fields:
1621 so_far.append(field)
1622 if not in_classes:
1623 child = parent.modules.get(field)
1624 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001625 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001626 continue
1627 in_classes = True
1628 if not hasattr(parent, 'classes'):
1629 return module, cls
1630 child = parent.classes.get(field)
1631 if not child:
1632 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1633 cls = parent = child
1634
1635 return module, cls
1636
1637
1638def parse_file(filename, *, verify=True, output=None, encoding='utf-8'):
1639 extension = os.path.splitext(filename)[1][1:]
1640 if not extension:
1641 fail("Can't extract file type for file " + repr(filename))
1642
1643 try:
1644 language = extensions[extension]()
1645 except KeyError:
1646 fail("Can't identify file type for file " + repr(filename))
1647
1648 clinic = Clinic(language, verify=verify, filename=filename)
1649
1650 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001651 raw = f.read()
1652
1653 cooked = clinic.parse(raw)
1654 if cooked == raw:
1655 return
Larry Hastings31826802013-10-19 00:09:25 -07001656
1657 directory = os.path.dirname(filename) or '.'
1658
1659 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001660 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001661 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1662 with open(tmpfilename, "wb") as f:
1663 f.write(bytes)
1664 os.replace(tmpfilename, output or filename)
1665
1666
1667def compute_checksum(input):
1668 input = input or ''
1669 return hashlib.sha1(input.encode('utf-8')).hexdigest()
1670
1671
1672
1673
1674class PythonParser:
1675 def __init__(self, clinic):
1676 pass
1677
1678 def parse(self, block):
1679 s = io.StringIO()
1680 with OverrideStdioWith(s):
1681 exec(block.input)
1682 block.output = s.getvalue()
1683
1684
1685class Module:
1686 def __init__(self, name, module=None):
1687 self.name = name
1688 self.module = self.parent = module
1689
1690 self.modules = collections.OrderedDict()
1691 self.classes = collections.OrderedDict()
1692 self.functions = []
1693
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001694 def __repr__(self):
1695 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1696
Larry Hastings31826802013-10-19 00:09:25 -07001697class Class:
1698 def __init__(self, name, module=None, cls=None):
1699 self.name = name
1700 self.module = module
1701 self.cls = cls
1702 self.parent = cls or module
1703
1704 self.classes = collections.OrderedDict()
1705 self.functions = []
1706
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001707 def __repr__(self):
1708 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1709
Larry Hastings8666e652014-01-12 14:12:59 -08001710unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001711
Larry Hastings8666e652014-01-12 14:12:59 -08001712__abs__
1713__add__
1714__and__
1715__bytes__
1716__call__
1717__complex__
1718__delitem__
1719__divmod__
1720__eq__
1721__float__
1722__floordiv__
1723__ge__
1724__getattr__
1725__getattribute__
1726__getitem__
1727__gt__
1728__hash__
1729__iadd__
1730__iand__
1731__idivmod__
1732__ifloordiv__
1733__ilshift__
1734__imod__
1735__imul__
1736__index__
1737__int__
1738__invert__
1739__ior__
1740__ipow__
1741__irshift__
1742__isub__
1743__iter__
1744__itruediv__
1745__ixor__
1746__le__
1747__len__
1748__lshift__
1749__lt__
1750__mod__
1751__mul__
1752__neg__
1753__new__
1754__next__
1755__or__
1756__pos__
1757__pow__
1758__radd__
1759__rand__
1760__rdivmod__
1761__repr__
1762__rfloordiv__
1763__rlshift__
1764__rmod__
1765__rmul__
1766__ror__
1767__round__
1768__rpow__
1769__rrshift__
1770__rshift__
1771__rsub__
1772__rtruediv__
1773__rxor__
1774__setattr__
1775__setitem__
1776__str__
1777__sub__
1778__truediv__
1779__xor__
1780
1781""".strip().split())
1782
1783
Larry Hastings5c661892014-01-24 06:17:25 -08001784INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
1785INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
1786""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07001787
1788class Function:
1789 """
1790 Mutable duck type for inspect.Function.
1791
1792 docstring - a str containing
1793 * embedded line breaks
1794 * text outdented to the left margin
1795 * no trailing whitespace.
1796 It will always be true that
1797 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
1798 """
1799
1800 def __init__(self, parameters=None, *, name,
1801 module, cls=None, c_basename=None,
1802 full_name=None,
1803 return_converter, return_annotation=_empty,
1804 docstring=None, kind=CALLABLE, coexist=False):
1805 self.parameters = parameters or collections.OrderedDict()
1806 self.return_annotation = return_annotation
1807 self.name = name
1808 self.full_name = full_name
1809 self.module = module
1810 self.cls = cls
1811 self.parent = cls or module
1812 self.c_basename = c_basename
1813 self.return_converter = return_converter
1814 self.docstring = docstring or ''
1815 self.kind = kind
1816 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08001817 self.self_converter = None
1818
1819 @property
1820 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08001821 if self.kind in (METHOD_INIT, METHOD_NEW):
1822 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001823 flags = []
1824 if self.kind == CLASS_METHOD:
1825 flags.append('METH_CLASS')
1826 elif self.kind == STATIC_METHOD:
1827 flags.append('METH_STATIC')
1828 else:
1829 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
1830 if self.coexist:
1831 flags.append('METH_COEXIST')
1832 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07001833
1834 def __repr__(self):
1835 return '<clinic.Function ' + self.name + '>'
1836
1837
1838class Parameter:
1839 """
1840 Mutable duck type of inspect.Parameter.
1841 """
1842
1843 def __init__(self, name, kind, *, default=_empty,
1844 function, converter, annotation=_empty,
1845 docstring=None, group=0):
1846 self.name = name
1847 self.kind = kind
1848 self.default = default
1849 self.function = function
1850 self.converter = converter
1851 self.annotation = annotation
1852 self.docstring = docstring or ''
1853 self.group = group
1854
1855 def __repr__(self):
1856 return '<clinic.Parameter ' + self.name + '>'
1857
1858 def is_keyword_only(self):
1859 return self.kind == inspect.Parameter.KEYWORD_ONLY
1860
Larry Hastings31826802013-10-19 00:09:25 -07001861
Larry Hastings31826802013-10-19 00:09:25 -07001862
1863def add_c_converter(f, name=None):
1864 if not name:
1865 name = f.__name__
1866 if not name.endswith('_converter'):
1867 return f
1868 name = name[:-len('_converter')]
1869 converters[name] = f
1870 return f
1871
1872def add_default_legacy_c_converter(cls):
1873 # automatically add converter for default format unit
1874 # (but without stomping on the existing one if it's already
1875 # set, in case you subclass)
1876 if ((cls.format_unit != 'O&') and
1877 (cls.format_unit not in legacy_converters)):
1878 legacy_converters[cls.format_unit] = cls
1879 return cls
1880
1881def add_legacy_c_converter(format_unit, **kwargs):
1882 """
1883 Adds a legacy converter.
1884 """
1885 def closure(f):
1886 if not kwargs:
1887 added_f = f
1888 else:
1889 added_f = functools.partial(f, **kwargs)
1890 legacy_converters[format_unit] = added_f
1891 return f
1892 return closure
1893
1894class CConverterAutoRegister(type):
1895 def __init__(cls, name, bases, classdict):
1896 add_c_converter(cls)
1897 add_default_legacy_c_converter(cls)
1898
1899class CConverter(metaclass=CConverterAutoRegister):
1900 """
1901 For the init function, self, name, function, and default
1902 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08001903 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07001904 """
1905
Larry Hastings78cf85c2014-01-04 12:44:57 -08001906 # The C type to use for this variable.
1907 # 'type' should be a Python string specifying the type, e.g. "int".
1908 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07001909 type = None
Larry Hastings31826802013-10-19 00:09:25 -07001910
1911 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08001912 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08001913 # Or the magic value "unknown" if this value is a cannot be evaluated
1914 # at Argument-Clinic-preprocessing time (but is presumed to be valid
1915 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07001916 default = unspecified
1917
Larry Hastings4a55fc52014-01-12 11:09:57 -08001918 # If not None, default must be isinstance() of this type.
1919 # (You can also specify a tuple of types.)
1920 default_type = None
1921
Larry Hastings31826802013-10-19 00:09:25 -07001922 # "default" converted into a C value, as a string.
1923 # Or None if there is no default.
1924 c_default = None
1925
Larry Hastings2a727912014-01-16 11:32:01 -08001926 # "default" converted into a Python value, as a string.
1927 # Or None if there is no default.
1928 py_default = None
1929
Larry Hastingsabc716b2013-11-20 09:13:52 -08001930 # The default value used to initialize the C variable when
1931 # there is no default, but not specifying a default may
1932 # result in an "uninitialized variable" warning. This can
1933 # easily happen when using option groups--although
1934 # properly-written code won't actually use the variable,
1935 # the variable does get passed in to the _impl. (Ah, if
1936 # only dataflow analysis could inline the static function!)
1937 #
1938 # This value is specified as a string.
1939 # Every non-abstract subclass should supply a valid value.
1940 c_ignored_default = 'NULL'
1941
Larry Hastings31826802013-10-19 00:09:25 -07001942 # The C converter *function* to be used, if any.
1943 # (If this is not None, format_unit must be 'O&'.)
1944 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001945
Larry Hastings78cf85c2014-01-04 12:44:57 -08001946 # Should Argument Clinic add a '&' before the name of
1947 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07001948 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08001949
1950 # Should Argument Clinic add a '&' before the name of
1951 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07001952 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08001953
1954 #############################################################
1955 #############################################################
1956 ## You shouldn't need to read anything below this point to ##
1957 ## write your own converter functions. ##
1958 #############################################################
1959 #############################################################
1960
1961 # The "format unit" to specify for this variable when
1962 # parsing arguments using PyArg_ParseTuple (AndKeywords).
1963 # Custom converters should always use the default value of 'O&'.
1964 format_unit = 'O&'
1965
1966 # What encoding do we want for this variable? Only used
1967 # by format units starting with 'e'.
1968 encoding = None
1969
Larry Hastings77561cc2014-01-07 12:13:13 -08001970 # Should this object be required to be a subclass of a specific type?
1971 # If not None, should be a string representing a pointer to a
1972 # PyTypeObject (e.g. "&PyUnicode_Type").
1973 # Only used by the 'O!' format unit (and the "object" converter).
1974 subclass_of = None
1975
Larry Hastings78cf85c2014-01-04 12:44:57 -08001976 # Do we want an adjacent '_length' variable for this variable?
1977 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07001978 length = False
1979
Larry Hastings5c661892014-01-24 06:17:25 -08001980 # Should we show this parameter in the generated
1981 # __text_signature__? This is *almost* always True.
1982 show_in_signature = True
1983
1984 # Overrides the name used in a text signature.
1985 # The name used for a "self" parameter must be one of
1986 # self, type, or module; however users can set their own.
1987 # This lets the self_converter overrule the user-settable
1988 # name, *just* for the text signature.
1989 # Only set by self_converter.
1990 signature_name = None
1991
1992 # keep in sync with self_converter.__init__!
Larry Hastings2a727912014-01-16 11:32:01 -08001993 def __init__(self, name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs):
Larry Hastings31826802013-10-19 00:09:25 -07001994 self.function = function
1995 self.name = name
1996
1997 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08001998 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08001999 if isinstance(self.default_type, type):
2000 types_str = self.default_type.__name__
2001 else:
2002 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2003 fail("{}: default value {!r} for field {} is not of type {}".format(
2004 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002005 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002006
Larry Hastingsb4705752014-01-18 21:54:15 -08002007 if c_default:
2008 self.c_default = c_default
2009 if py_default:
2010 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002011
Larry Hastings31826802013-10-19 00:09:25 -07002012 if annotation != unspecified:
2013 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings31826802013-10-19 00:09:25 -07002014 self.converter_init(**kwargs)
2015
2016 def converter_init(self):
2017 pass
2018
2019 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002020 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002021
Larry Hastings5c661892014-01-24 06:17:25 -08002022 def _render_self(self, parameter, data):
2023 self.parameter = parameter
2024 original_name = self.name
2025 name = ensure_legal_c_identifier(original_name)
2026
2027 # impl_arguments
2028 s = ("&" if self.impl_by_reference else "") + name
2029 data.impl_arguments.append(s)
2030 if self.length:
2031 data.impl_arguments.append(self.length_name())
2032
2033 # impl_parameters
2034 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2035 if self.length:
2036 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2037
2038 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002039 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002040 original_name = self.name
2041 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002042
2043 # declarations
2044 d = self.declaration()
2045 data.declarations.append(d)
2046
2047 # initializers
2048 initializers = self.initialize()
2049 if initializers:
2050 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2051
Larry Hastings31826802013-10-19 00:09:25 -07002052 # keywords
Larry Hastings90261132014-01-07 12:21:08 -08002053 data.keywords.append(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002054
2055 # format_units
2056 if self.is_optional() and '|' not in data.format_units:
2057 data.format_units.append('|')
2058 if parameter.is_keyword_only() and '$' not in data.format_units:
2059 data.format_units.append('$')
2060 data.format_units.append(self.format_unit)
2061
2062 # parse_arguments
2063 self.parse_argument(data.parse_arguments)
2064
Larry Hastings31826802013-10-19 00:09:25 -07002065 # cleanup
2066 cleanup = self.cleanup()
2067 if cleanup:
2068 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2069
Larry Hastings5c661892014-01-24 06:17:25 -08002070 def render(self, parameter, data):
2071 """
2072 parameter is a clinic.Parameter instance.
2073 data is a CRenderData instance.
2074 """
2075 self._render_self(parameter, data)
2076 self._render_non_self(parameter, data)
2077
Larry Hastingsebdcb502013-11-23 14:54:00 -08002078 def length_name(self):
2079 """Computes the name of the associated "length" variable."""
2080 if not self.length:
2081 return None
2082 return ensure_legal_c_identifier(self.name) + "_length"
2083
Larry Hastings31826802013-10-19 00:09:25 -07002084 # Why is this one broken out separately?
2085 # For "positional-only" function parsing,
2086 # which generates a bunch of PyArg_ParseTuple calls.
2087 def parse_argument(self, list):
2088 assert not (self.converter and self.encoding)
2089 if self.format_unit == 'O&':
2090 assert self.converter
2091 list.append(self.converter)
2092
2093 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002094 list.append(c_repr(self.encoding))
2095 elif self.subclass_of:
2096 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002097
Larry Hastingsebdcb502013-11-23 14:54:00 -08002098 legal_name = ensure_legal_c_identifier(self.name)
2099 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002100 list.append(s)
2101
Larry Hastingsebdcb502013-11-23 14:54:00 -08002102 if self.length:
2103 list.append("&" + self.length_name())
2104
Larry Hastings31826802013-10-19 00:09:25 -07002105 #
2106 # All the functions after here are intended as extension points.
2107 #
2108
2109 def simple_declaration(self, by_reference=False):
2110 """
2111 Computes the basic declaration of the variable.
2112 Used in computing the prototype declaration and the
2113 variable declaration.
2114 """
2115 prototype = [self.type]
2116 if by_reference or not self.type.endswith('*'):
2117 prototype.append(" ")
2118 if by_reference:
2119 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002120 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002121 return "".join(prototype)
2122
2123 def declaration(self):
2124 """
2125 The C statement to declare this variable.
2126 """
2127 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002128 default = self.c_default
2129 if not default and self.parameter.group:
2130 default = self.c_ignored_default
2131 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002132 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002133 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002134 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002135 if self.length:
2136 declaration.append('\nPy_ssize_clean_t ')
2137 declaration.append(self.length_name())
2138 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002139 s = "".join(declaration)
2140 # double up curly-braces, this string will be used
2141 # as part of a format_map() template later
2142 s = s.replace("{", "{{")
2143 s = s.replace("}", "}}")
2144 return s
Larry Hastings31826802013-10-19 00:09:25 -07002145
2146 def initialize(self):
2147 """
2148 The C statements required to set up this variable before parsing.
2149 Returns a string containing this code indented at column 0.
2150 If no initialization is necessary, returns an empty string.
2151 """
2152 return ""
2153
2154 def cleanup(self):
2155 """
2156 The C statements required to clean up after this variable.
2157 Returns a string containing this code indented at column 0.
2158 If no cleanup is necessary, returns an empty string.
2159 """
2160 return ""
2161
2162
2163class bool_converter(CConverter):
2164 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002165 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002166 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002167 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002168
2169 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002170 if self.default is not unspecified:
2171 self.default = bool(self.default)
2172 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002173
2174class char_converter(CConverter):
2175 type = 'char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002176 default_type = str
Larry Hastings31826802013-10-19 00:09:25 -07002177 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002178 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002179
Larry Hastings4a55fc52014-01-12 11:09:57 -08002180 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002181 if isinstance(self.default, str) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002182 fail("char_converter: illegal default value " + repr(self.default))
2183
2184
Larry Hastings31826802013-10-19 00:09:25 -07002185@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002186class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002187 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002188 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002189 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002190 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002191
2192 def converter_init(self, *, bitwise=False):
2193 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002194 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002195
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002196class byte_converter(unsigned_char_converter): pass
2197
Larry Hastings31826802013-10-19 00:09:25 -07002198class short_converter(CConverter):
2199 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002200 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002201 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002202 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002203
2204class unsigned_short_converter(CConverter):
2205 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002206 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002207 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002208 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002209
2210 def converter_init(self, *, bitwise=False):
2211 if not bitwise:
2212 fail("Unsigned shorts must be bitwise (for now).")
2213
Larry Hastingsebdcb502013-11-23 14:54:00 -08002214@add_legacy_c_converter('C', types='str')
Larry Hastings31826802013-10-19 00:09:25 -07002215class int_converter(CConverter):
2216 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002217 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002218 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002219 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002220
Larry Hastingsebdcb502013-11-23 14:54:00 -08002221 def converter_init(self, *, types='int'):
2222 if types == 'str':
2223 self.format_unit = 'C'
2224 elif types != 'int':
2225 fail("int_converter: illegal 'types' argument")
Larry Hastings31826802013-10-19 00:09:25 -07002226
2227class unsigned_int_converter(CConverter):
2228 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002229 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002230 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002231 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002232
2233 def converter_init(self, *, bitwise=False):
2234 if not bitwise:
2235 fail("Unsigned ints must be bitwise (for now).")
2236
2237class long_converter(CConverter):
2238 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002239 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002240 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002241 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002242
2243class unsigned_long_converter(CConverter):
2244 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002245 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002246 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002247 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002248
2249 def converter_init(self, *, bitwise=False):
2250 if not bitwise:
2251 fail("Unsigned longs must be bitwise (for now).")
2252
2253class PY_LONG_LONG_converter(CConverter):
2254 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002255 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002256 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002257 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002258
2259class unsigned_PY_LONG_LONG_converter(CConverter):
2260 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002261 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002262 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002263 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002264
2265 def converter_init(self, *, bitwise=False):
2266 if not bitwise:
2267 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2268
2269class Py_ssize_t_converter(CConverter):
2270 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002271 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002272 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002273 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002274
2275
2276class float_converter(CConverter):
2277 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002278 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002279 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002280 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002281
2282class double_converter(CConverter):
2283 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002284 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002285 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002286 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002287
2288
2289class Py_complex_converter(CConverter):
2290 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002291 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002292 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002293 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002294
2295
2296class object_converter(CConverter):
2297 type = 'PyObject *'
2298 format_unit = 'O'
2299
Larry Hastings4a55fc52014-01-12 11:09:57 -08002300 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2301 if converter:
2302 if subclass_of:
2303 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2304 self.format_unit = 'O&'
2305 self.converter = converter
2306 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002307 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002308 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002309
Larry Hastings77561cc2014-01-07 12:13:13 -08002310 if type is not None:
2311 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002312
2313
Larry Hastingsebdcb502013-11-23 14:54:00 -08002314@add_legacy_c_converter('s#', length=True)
Larry Hastings2a727912014-01-16 11:32:01 -08002315@add_legacy_c_converter('y', types="bytes")
2316@add_legacy_c_converter('y#', types="bytes", length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002317@add_legacy_c_converter('z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002318@add_legacy_c_converter('z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002319class str_converter(CConverter):
2320 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002321 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002322 format_unit = 's'
2323
Larry Hastingsebdcb502013-11-23 14:54:00 -08002324 def converter_init(self, *, encoding=None, types="str",
2325 length=False, nullable=False, zeroes=False):
2326
2327 types = set(types.strip().split())
2328 bytes_type = set(("bytes",))
2329 str_type = set(("str",))
2330 all_3_type = set(("bytearray",)) | bytes_type | str_type
2331 is_bytes = types == bytes_type
2332 is_str = types == str_type
2333 is_all_3 = types == all_3_type
2334
2335 self.length = bool(length)
2336 format_unit = None
2337
2338 if encoding:
2339 self.encoding = encoding
2340
2341 if is_str and not (length or zeroes or nullable):
2342 format_unit = 'es'
2343 elif is_all_3 and not (length or zeroes or nullable):
2344 format_unit = 'et'
2345 elif is_str and length and zeroes and not nullable:
2346 format_unit = 'es#'
2347 elif is_all_3 and length and not (nullable or zeroes):
2348 format_unit = 'et#'
2349
2350 if format_unit.endswith('#'):
Larry Hastings5c661892014-01-24 06:17:25 -08002351 fail("Sorry: code using format unit ", repr(format_unit), "probably doesn't work properly yet.\nGive Larry your test case and he'll it.")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002352 # TODO set pointer to NULL
2353 # TODO add cleanup for buffer
2354 pass
2355
2356 else:
2357 if zeroes:
2358 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
2359
2360 if is_bytes and not (nullable or length):
2361 format_unit = 'y'
2362 elif is_bytes and length and not nullable:
2363 format_unit = 'y#'
2364 elif is_str and not (nullable or length):
2365 format_unit = 's'
2366 elif is_str and length and not nullable:
2367 format_unit = 's#'
2368 elif is_str and nullable and not length:
2369 format_unit = 'z'
2370 elif is_str and nullable and length:
2371 format_unit = 'z#'
2372
2373 if not format_unit:
2374 fail("str_converter: illegal combination of arguments")
2375 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002376
2377
2378class PyBytesObject_converter(CConverter):
2379 type = 'PyBytesObject *'
2380 format_unit = 'S'
2381
2382class PyByteArrayObject_converter(CConverter):
2383 type = 'PyByteArrayObject *'
2384 format_unit = 'Y'
2385
2386class unicode_converter(CConverter):
2387 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002388 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002389 format_unit = 'U'
2390
Larry Hastingsebdcb502013-11-23 14:54:00 -08002391@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002392@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002393@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002394class Py_UNICODE_converter(CConverter):
2395 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002396 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002397 format_unit = 'u'
2398
Larry Hastingsebdcb502013-11-23 14:54:00 -08002399 def converter_init(self, *, nullable=False, length=False):
2400 format_unit = 'Z' if nullable else 'u'
2401 if length:
2402 format_unit += '#'
2403 self.length = True
2404 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002405
Larry Hastingsebdcb502013-11-23 14:54:00 -08002406#
2407# We define three string conventions for buffer types in the 'types' argument:
2408# 'buffer' : any object supporting the buffer interface
2409# 'rwbuffer': any object supporting the buffer interface, but must be writeable
2410# 'robuffer': any object supporting the buffer interface, but must not be writeable
2411#
2412@add_legacy_c_converter('s*', types='str bytes bytearray buffer')
2413@add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True)
2414@add_legacy_c_converter('w*', types='bytearray rwbuffer')
Larry Hastings31826802013-10-19 00:09:25 -07002415class Py_buffer_converter(CConverter):
2416 type = 'Py_buffer'
2417 format_unit = 'y*'
2418 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002419 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002420
Larry Hastingsebdcb502013-11-23 14:54:00 -08002421 def converter_init(self, *, types='bytes bytearray buffer', nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002422 if self.default not in (unspecified, None):
2423 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08002424 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002425 types = set(types.strip().split())
2426 bytes_type = set(('bytes',))
2427 bytearray_type = set(('bytearray',))
2428 buffer_type = set(('buffer',))
2429 rwbuffer_type = set(('rwbuffer',))
2430 robuffer_type = set(('robuffer',))
2431 str_type = set(('str',))
2432 bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type
2433
2434 format_unit = None
2435 if types == (str_type | bytes_bytearray_buffer_type):
2436 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07002437 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002438 if nullable:
2439 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
2440 elif types == (bytes_bytearray_buffer_type):
2441 format_unit = 'y*'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002442 elif types == (bytearray_type | rwbuffer_type):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002443 format_unit = 'w*'
2444 if not format_unit:
2445 fail("Py_buffer_converter: illegal combination of arguments")
2446
2447 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002448
2449 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002450 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002451 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002452
2453
Larry Hastings5c661892014-01-24 06:17:25 -08002454def correct_name_for_self(f):
2455 if f.kind in (CALLABLE, METHOD_INIT):
2456 if f.cls:
2457 return "PyObject *", "self"
2458 return "PyModuleDef *", "module"
2459 if f.kind == STATIC_METHOD:
2460 return "void *", "null"
2461 if f.kind in (CLASS_METHOD, METHOD_NEW):
2462 return "PyTypeObject *", "type"
2463 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2464
2465
Larry Hastingsebdcb502013-11-23 14:54:00 -08002466class self_converter(CConverter):
2467 """
2468 A special-case converter:
2469 this is the default converter used for "self".
2470 """
Larry Hastings5c661892014-01-24 06:17:25 -08002471 type = None
2472 format_unit = ''
2473
2474
Larry Hastings78cf85c2014-01-04 12:44:57 -08002475 def converter_init(self, *, type=None):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002476 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002477 default_type, default_name = correct_name_for_self(f)
2478 self.signature_name = default_name
2479 self.type = type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002480
Larry Hastings5c661892014-01-24 06:17:25 -08002481 kind = self.function.kind
2482 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2483
2484 if (kind == STATIC_METHOD) or new_or_init:
2485 self.show_in_signature = False
2486
2487 # tp_new (METHOD_NEW) functions are of type newfunc:
2488 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2489 # PyTypeObject is a typedef for struct _typeobject.
2490 #
2491 # tp_init (METHOD_INIT) functions are of type initproc:
2492 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2493 #
2494 # All other functions generated by Argument Clinic are stored in
2495 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2496 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2497 # However! We habitually cast these functions to PyCFunction,
2498 # since functions that accept keyword arguments don't fit this signature
2499 # but are stored there anyway. So strict type equality isn't important
2500 # for these functions.
2501 #
2502 # So:
2503 #
2504 # * The name of the first parameter to the impl and the parsing function will always
2505 # be self.name.
2506 #
2507 # * The type of the first parameter to the impl will always be of self.type.
2508 #
2509 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2510 # * The type of the first parameter to the parsing function is also self.type.
2511 # This means that if you step into the parsing function, your "self" parameter
2512 # is of the correct type, which may make debugging more pleasant.
2513 #
2514 # * Else if the function is tp_new (METHOD_NEW):
2515 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2516 # so the type signature of the function call is an exact match.
2517 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2518 # in the impl call.
2519 #
2520 # * Else if the function is tp_init (METHOD_INIT):
2521 # * The type of the first parameter to the parsing function is "PyObject *",
2522 # so the type signature of the function call is an exact match.
2523 # * If self.type != "PyObject *", we cast the first parameter to self.type
2524 # in the impl call.
2525
2526 @property
2527 def parser_type(self):
2528 kind = self.function.kind
2529 if kind == METHOD_NEW:
2530 return "PyTypeObject *"
2531 if kind == METHOD_INIT:
2532 return "PyObject *"
2533 return self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002534
Larry Hastingsebdcb502013-11-23 14:54:00 -08002535 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002536 """
2537 parameter is a clinic.Parameter instance.
2538 data is a CRenderData instance.
2539 """
2540 if self.function.kind == STATIC_METHOD:
2541 return
2542
2543 self._render_self(parameter, data)
2544
2545 if self.type != self.parser_type:
2546 # insert cast to impl_argument[0], aka self.
2547 # we know we're in the first slot in all the CRenderData lists,
2548 # because we render parameters in order, and self is always first.
2549 assert len(data.impl_arguments) == 1
2550 assert data.impl_arguments[0] == self.name
2551 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2552
2553 def set_template_dict(self, template_dict):
2554 template_dict['self_name'] = self.name
2555 template_dict['self_type'] = self.parser_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002556
Larry Hastings31826802013-10-19 00:09:25 -07002557
2558
2559def add_c_return_converter(f, name=None):
2560 if not name:
2561 name = f.__name__
2562 if not name.endswith('_return_converter'):
2563 return f
2564 name = name[:-len('_return_converter')]
2565 return_converters[name] = f
2566 return f
2567
2568
2569class CReturnConverterAutoRegister(type):
2570 def __init__(cls, name, bases, classdict):
2571 add_c_return_converter(cls)
2572
2573class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2574
Larry Hastings78cf85c2014-01-04 12:44:57 -08002575 # The C type to use for this variable.
2576 # 'type' should be a Python string specifying the type, e.g. "int".
2577 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002578 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002579
2580 # The Python default value for this parameter, as a Python value.
2581 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002582 default = None
2583
Larry Hastings2a727912014-01-16 11:32:01 -08002584 def __init__(self, *, py_default=None, **kwargs):
2585 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002586 try:
2587 self.return_converter_init(**kwargs)
2588 except TypeError as e:
2589 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2590 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2591
2592 def return_converter_init(self):
2593 pass
2594
2595 def declare(self, data, name="_return_value"):
2596 line = []
2597 add = line.append
2598 add(self.type)
2599 if not self.type.endswith('*'):
2600 add(' ')
2601 add(name + ';')
2602 data.declarations.append(''.join(line))
2603 data.return_value = name
2604
2605 def err_occurred_if(self, expr, data):
2606 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2607
2608 def err_occurred_if_null_pointer(self, variable, data):
2609 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2610
2611 def render(self, function, data):
2612 """
2613 function is a clinic.Function instance.
2614 data is a CRenderData instance.
2615 """
2616 pass
2617
2618add_c_return_converter(CReturnConverter, 'object')
2619
Larry Hastings78cf85c2014-01-04 12:44:57 -08002620class NoneType_return_converter(CReturnConverter):
2621 def render(self, function, data):
2622 self.declare(data)
2623 data.return_conversion.append('''
2624if (_return_value != Py_None)
2625 goto exit;
2626return_value = Py_None;
2627Py_INCREF(Py_None);
2628'''.strip())
2629
Larry Hastings4a55fc52014-01-12 11:09:57 -08002630class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002631 type = 'int'
2632
2633 def render(self, function, data):
2634 self.declare(data)
2635 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002636 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002637
2638class long_return_converter(CReturnConverter):
2639 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002640 conversion_fn = 'PyLong_FromLong'
2641 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002642
2643 def render(self, function, data):
2644 self.declare(data)
2645 self.err_occurred_if("_return_value == -1", data)
2646 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002647 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002648
Larry Hastings4a55fc52014-01-12 11:09:57 -08002649class int_return_converter(long_return_converter):
2650 type = 'int'
2651 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002652
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002653class init_return_converter(long_return_converter):
2654 """
2655 Special return converter for __init__ functions.
2656 """
2657 type = 'int'
2658 cast = '(long)'
2659
2660 def render(self, function, data):
2661 pass
2662
Larry Hastings4a55fc52014-01-12 11:09:57 -08002663class unsigned_long_return_converter(long_return_converter):
2664 type = 'unsigned long'
2665 conversion_fn = 'PyLong_FromUnsignedLong'
2666
2667class unsigned_int_return_converter(unsigned_long_return_converter):
2668 type = 'unsigned int'
2669 cast = '(unsigned long)'
2670
2671class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07002672 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002673 conversion_fn = 'PyLong_FromSsize_t'
2674
2675class size_t_return_converter(long_return_converter):
2676 type = 'size_t'
2677 conversion_fn = 'PyLong_FromSize_t'
2678
2679
2680class double_return_converter(CReturnConverter):
2681 type = 'double'
2682 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002683
2684 def render(self, function, data):
2685 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002686 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07002687 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002688 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
2689
2690class float_return_converter(double_return_converter):
2691 type = 'float'
2692 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07002693
2694
2695class DecodeFSDefault_return_converter(CReturnConverter):
2696 type = 'char *'
2697
2698 def render(self, function, data):
2699 self.declare(data)
2700 self.err_occurred_if_null_pointer("_return_value", data)
2701 data.return_conversion.append(
2702 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
2703
2704
2705class IndentStack:
2706 def __init__(self):
2707 self.indents = []
2708 self.margin = None
2709
2710 def _ensure(self):
2711 if not self.indents:
2712 fail('IndentStack expected indents, but none are defined.')
2713
2714 def measure(self, line):
2715 """
2716 Returns the length of the line's margin.
2717 """
2718 if '\t' in line:
2719 fail('Tab characters are illegal in the Clinic DSL.')
2720 stripped = line.lstrip()
2721 if not len(stripped):
2722 # we can't tell anything from an empty line
2723 # so just pretend it's indented like our current indent
2724 self._ensure()
2725 return self.indents[-1]
2726 return len(line) - len(stripped)
2727
2728 def infer(self, line):
2729 """
2730 Infer what is now the current margin based on this line.
2731 Returns:
2732 1 if we have indented (or this is the first margin)
2733 0 if the margin has not changed
2734 -N if we have dedented N times
2735 """
2736 indent = self.measure(line)
2737 margin = ' ' * indent
2738 if not self.indents:
2739 self.indents.append(indent)
2740 self.margin = margin
2741 return 1
2742 current = self.indents[-1]
2743 if indent == current:
2744 return 0
2745 if indent > current:
2746 self.indents.append(indent)
2747 self.margin = margin
2748 return 1
2749 # indent < current
2750 if indent not in self.indents:
2751 fail("Illegal outdent.")
2752 outdent_count = 0
2753 while indent != current:
2754 self.indents.pop()
2755 current = self.indents[-1]
2756 outdent_count -= 1
2757 self.margin = margin
2758 return outdent_count
2759
2760 @property
2761 def depth(self):
2762 """
2763 Returns how many margins are currently defined.
2764 """
2765 return len(self.indents)
2766
2767 def indent(self, line):
2768 """
2769 Indents a line by the currently defined margin.
2770 """
2771 return self.margin + line
2772
2773 def dedent(self, line):
2774 """
2775 Dedents a line by the currently defined margin.
2776 (The inverse of 'indent'.)
2777 """
2778 margin = self.margin
2779 indent = self.indents[-1]
2780 if not line.startswith(margin):
2781 fail('Cannot dedent, line does not start with the previous margin:')
2782 return line[indent:]
2783
2784
2785class DSLParser:
2786 def __init__(self, clinic):
2787 self.clinic = clinic
2788
2789 self.directives = {}
2790 for name in dir(self):
2791 # functions that start with directive_ are added to directives
2792 _, s, key = name.partition("directive_")
2793 if s:
2794 self.directives[key] = getattr(self, name)
2795
2796 # functions that start with at_ are too, with an @ in front
2797 _, s, key = name.partition("at_")
2798 if s:
2799 self.directives['@' + key] = getattr(self, name)
2800
2801 self.reset()
2802
2803 def reset(self):
2804 self.function = None
2805 self.state = self.state_dsl_start
2806 self.parameter_indent = None
2807 self.keyword_only = False
2808 self.group = 0
2809 self.parameter_state = self.ps_start
2810 self.indent = IndentStack()
2811 self.kind = CALLABLE
2812 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08002813 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08002814 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07002815
Larry Hastingsebdcb502013-11-23 14:54:00 -08002816 def directive_version(self, required):
2817 global version
2818 if version_comparitor(version, required) < 0:
2819 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
2820
Larry Hastings31826802013-10-19 00:09:25 -07002821 def directive_module(self, name):
2822 fields = name.split('.')
2823 new = fields.pop()
2824 module, cls = self.clinic._module_and_class(fields)
2825 if cls:
2826 fail("Can't nest a module inside a class!")
2827 m = Module(name, module)
2828 module.modules[name] = m
2829 self.block.signatures.append(m)
2830
2831 def directive_class(self, name):
2832 fields = name.split('.')
2833 in_classes = False
2834 parent = self
2835 name = fields.pop()
2836 so_far = []
2837 module, cls = self.clinic._module_and_class(fields)
2838
Larry Hastings31826802013-10-19 00:09:25 -07002839 c = Class(name, module, cls)
Larry Hastings31826802013-10-19 00:09:25 -07002840 if cls:
2841 cls.classes[name] = c
Larry Hastingsed4a1c52013-11-18 09:32:13 -08002842 else:
2843 module.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07002844 self.block.signatures.append(c)
2845
Larry Hastingsbebf7352014-01-17 17:47:17 -08002846 def directive_set(self, name, value):
2847 if name not in ("line_prefix", "line_suffix"):
2848 fail("unknown variable", repr(name))
2849
2850 value = value.format_map({
2851 'block comment start': '/*',
2852 'block comment end': '*/',
2853 })
2854
2855 self.clinic.__dict__[name] = value
2856
2857 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06002858 if command == 'new':
2859 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08002860 return
2861
Zachary Ware071baa62014-01-21 23:07:12 -06002862 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08002863 self.clinic.get_destination(name).clear()
2864 fail("unknown destination command", repr(command))
2865
2866
2867 def directive_output(self, field, destination=''):
2868 fd = self.clinic.field_destinations
2869
2870 if field == "preset":
2871 preset = self.clinic.presets.get(destination)
2872 if not preset:
2873 fail("Unknown preset " + repr(destination) + "!")
2874 fd.update(preset)
2875 return
2876
2877 if field == "push":
2878 self.clinic.field_destinations_stack.append(fd.copy())
2879 return
2880
2881 if field == "pop":
2882 if not self.clinic.field_destinations_stack:
2883 fail("Can't 'output pop', stack is empty!")
2884 previous_fd = self.clinic.field_destinations_stack.pop()
2885 fd.update(previous_fd)
2886 return
2887
2888 # secret command for debugging!
2889 if field == "print":
2890 self.block.output.append(pprint.pformat(fd))
2891 self.block.output.append('\n')
2892 return
2893
2894 d = self.clinic.get_destination(destination)
2895
2896 if field == "everything":
2897 for name in list(fd):
2898 fd[name] = d
2899 return
2900
2901 if field not in fd:
2902 fail("Invalid field " + repr(field) + ", must be one of:\n " + ", ".join(valid_fields))
2903 fd[field] = d
2904
2905 def directive_dump(self, name):
2906 self.block.output.append(self.clinic.get_destination(name).dump())
2907
2908 def directive_print(self, *args):
2909 self.block.output.append(' '.join(args))
2910 self.block.output.append('\n')
2911
2912 def directive_preserve(self):
2913 if self.preserve_output:
2914 fail("Can't have preserve twice in one block!")
2915 self.preserve_output = True
2916
Larry Hastings31826802013-10-19 00:09:25 -07002917 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002918 if self.kind is not CALLABLE:
2919 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07002920 self.kind = CLASS_METHOD
2921
2922 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002923 if self.kind is not CALLABLE:
2924 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07002925 self.kind = STATIC_METHOD
2926
2927 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002928 if self.coexist:
2929 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07002930 self.coexist = True
2931
2932 def parse(self, block):
2933 self.reset()
2934 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08002935 self.saved_output = self.block.output
2936 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07002937 block_start = self.clinic.block_parser.line_number
2938 lines = block.input.split('\n')
2939 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
2940 if '\t' in line:
2941 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
2942 self.state(line)
2943
2944 self.next(self.state_terminal)
2945 self.state(None)
2946
Larry Hastingsbebf7352014-01-17 17:47:17 -08002947 block.output.extend(self.clinic.language.render(clinic, block.signatures))
2948
2949 if self.preserve_output:
2950 if block.output:
2951 fail("'preserve' only works for blocks that don't produce any output!")
2952 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07002953
2954 @staticmethod
2955 def ignore_line(line):
2956 # ignore comment-only lines
2957 if line.lstrip().startswith('#'):
2958 return True
2959
2960 # Ignore empty lines too
2961 # (but not in docstring sections!)
2962 if not line.strip():
2963 return True
2964
2965 return False
2966
2967 @staticmethod
2968 def calculate_indent(line):
2969 return len(line) - len(line.strip())
2970
2971 def next(self, state, line=None):
2972 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
2973 self.state = state
2974 if line is not None:
2975 self.state(line)
2976
2977 def state_dsl_start(self, line):
2978 # self.block = self.ClinicOutputBlock(self)
2979 if self.ignore_line(line):
2980 return
2981 self.next(self.state_modulename_name, line)
2982
2983 def state_modulename_name(self, line):
2984 # looking for declaration, which establishes the leftmost column
2985 # line should be
2986 # modulename.fnname [as c_basename] [-> return annotation]
2987 # square brackets denote optional syntax.
2988 #
Larry Hastings4a714d42014-01-14 22:22:41 -08002989 # alternatively:
2990 # modulename.fnname [as c_basename] = modulename.existing_fn_name
2991 # clones the parameters and return converter from that
2992 # function. you can't modify them. you must enter a
2993 # new docstring.
2994 #
Larry Hastings31826802013-10-19 00:09:25 -07002995 # (but we might find a directive first!)
2996 #
2997 # this line is permitted to start with whitespace.
2998 # we'll call this number of spaces F (for "function").
2999
3000 if not line.strip():
3001 return
3002
3003 self.indent.infer(line)
3004
3005 # is it a directive?
3006 fields = shlex.split(line)
3007 directive_name = fields[0]
3008 directive = self.directives.get(directive_name, None)
3009 if directive:
Larry Hastingsbebf7352014-01-17 17:47:17 -08003010 try:
3011 directive(*fields[1:])
3012 except TypeError as e:
3013 fail(str(e))
Larry Hastings31826802013-10-19 00:09:25 -07003014 return
3015
Larry Hastings4a714d42014-01-14 22:22:41 -08003016 # are we cloning?
3017 before, equals, existing = line.rpartition('=')
3018 if equals:
3019 full_name, _, c_basename = before.partition(' as ')
3020 full_name = full_name.strip()
3021 c_basename = c_basename.strip()
3022 existing = existing.strip()
3023 if (is_legal_py_identifier(full_name) and
3024 (not c_basename or is_legal_c_identifier(c_basename)) and
3025 is_legal_py_identifier(existing)):
3026 # we're cloning!
3027 fields = [x.strip() for x in existing.split('.')]
3028 function_name = fields.pop()
3029 module, cls = self.clinic._module_and_class(fields)
3030
3031 for existing_function in (cls or module).functions:
3032 if existing_function.name == function_name:
3033 break
3034 else:
3035 existing_function = None
3036 if not existing_function:
3037 fail("Couldn't find existing function " + repr(existing) + "!")
3038
3039 fields = [x.strip() for x in full_name.split('.')]
3040 function_name = fields.pop()
3041 module, cls = self.clinic._module_and_class(fields)
3042
3043 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3044 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
3045 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3046 return_converter=existing_function.return_converter, kind=existing_function.kind, coexist=existing_function.coexist)
3047
3048 self.function.parameters = existing_function.parameters.copy()
3049
3050 self.block.signatures.append(self.function)
3051 (cls or module).functions.append(self.function)
3052 self.next(self.state_function_docstring)
3053 return
3054
Larry Hastings31826802013-10-19 00:09:25 -07003055 line, _, returns = line.partition('->')
3056
3057 full_name, _, c_basename = line.partition(' as ')
3058 full_name = full_name.strip()
3059 c_basename = c_basename.strip() or None
3060
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003061 if not is_legal_py_identifier(full_name):
3062 fail("Illegal function name: {}".format(full_name))
3063 if c_basename and not is_legal_c_identifier(c_basename):
3064 fail("Illegal C basename: {}".format(c_basename))
3065
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003066 return_converter = None
3067 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003068 ast_input = "def x() -> {}: pass".format(returns)
3069 module = None
3070 try:
3071 module = ast.parse(ast_input)
3072 except SyntaxError:
3073 pass
3074 if not module:
3075 fail("Badly-formed annotation for " + full_name + ": " + returns)
3076 try:
3077 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003078 if legacy:
3079 fail("Legacy converter {!r} not allowed as a return converter"
3080 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003081 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003082 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003083 return_converter = return_converters[name](**kwargs)
3084 except ValueError:
3085 fail("Badly-formed annotation for " + full_name + ": " + returns)
3086
3087 fields = [x.strip() for x in full_name.split('.')]
3088 function_name = fields.pop()
3089 module, cls = self.clinic._module_and_class(fields)
3090
Larry Hastings8666e652014-01-12 14:12:59 -08003091 fields = full_name.split('.')
3092 if fields[-1] == '__new__':
3093 if (self.kind != CLASS_METHOD) or (not cls):
3094 fail("__new__ must be a class method!")
3095 self.kind = METHOD_NEW
3096 elif fields[-1] == '__init__':
3097 if (self.kind != CALLABLE) or (not cls):
3098 fail("__init__ must be a normal method, not a class or static method!")
3099 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003100 if not return_converter:
3101 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003102 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003103 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003104
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003105 if not return_converter:
3106 return_converter = CReturnConverter()
3107
Larry Hastings31826802013-10-19 00:09:25 -07003108 if not module:
3109 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3110 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3111 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3112 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003113
3114 # insert a self converter automatically
3115 _, name = correct_name_for_self(self.function)
3116 sc = self.function.self_converter = self_converter(name, self.function)
3117 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3118 self.function.parameters[sc.name] = p_self
3119
Larry Hastings4a714d42014-01-14 22:22:41 -08003120 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003121 self.next(self.state_parameters_start)
3122
3123 # Now entering the parameters section. The rules, formally stated:
3124 #
3125 # * All lines must be indented with spaces only.
3126 # * The first line must be a parameter declaration.
3127 # * The first line must be indented.
3128 # * This first line establishes the indent for parameters.
3129 # * We'll call this number of spaces P (for "parameter").
3130 # * Thenceforth:
3131 # * Lines indented with P spaces specify a parameter.
3132 # * Lines indented with > P spaces are docstrings for the previous
3133 # parameter.
3134 # * We'll call this number of spaces D (for "docstring").
3135 # * All subsequent lines indented with >= D spaces are stored as
3136 # part of the per-parameter docstring.
3137 # * All lines will have the first D spaces of the indent stripped
3138 # before they are stored.
3139 # * It's illegal to have a line starting with a number of spaces X
3140 # such that P < X < D.
3141 # * A line with < P spaces is the first line of the function
3142 # docstring, which ends processing for parameters and per-parameter
3143 # docstrings.
3144 # * The first line of the function docstring must be at the same
3145 # indent as the function declaration.
3146 # * It's illegal to have any line in the parameters section starting
3147 # with X spaces such that F < X < P. (As before, F is the indent
3148 # of the function declaration.)
3149 #
Larry Hastings31826802013-10-19 00:09:25 -07003150 # Also, currently Argument Clinic places the following restrictions on groups:
3151 # * Each group must contain at least one parameter.
3152 # * Each group may contain at most one group, which must be the furthest
3153 # thing in the group from the required parameters. (The nested group
3154 # must be the first in the group when it's before the required
3155 # parameters, and the last thing in the group when after the required
3156 # parameters.)
3157 # * There may be at most one (top-level) group to the left or right of
3158 # the required parameters.
3159 # * You must specify a slash, and it must be after all parameters.
3160 # (In other words: either all parameters are positional-only,
3161 # or none are.)
3162 #
3163 # Said another way:
3164 # * Each group must contain at least one parameter.
3165 # * All left square brackets before the required parameters must be
3166 # consecutive. (You can't have a left square bracket followed
3167 # by a parameter, then another left square bracket. You can't
3168 # have a left square bracket, a parameter, a right square bracket,
3169 # and then a left square bracket.)
3170 # * All right square brackets after the required parameters must be
3171 # consecutive.
3172 #
3173 # These rules are enforced with a single state variable:
3174 # "parameter_state". (Previously the code was a miasma of ifs and
3175 # separate boolean state variables.) The states are:
3176 #
3177 # [ [ a, b, ] c, ] d, e, f, [ g, h, [ i ] ] / <- line
3178 # 01 2 3 4 5 6 <- state transitions
3179 #
3180 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3181 # 1: ps_left_square_before. left square brackets before required parameters.
3182 # 2: ps_group_before. in a group, before required parameters.
3183 # 3: ps_required. required parameters. (renumber left groups!)
3184 # 4: ps_group_after. in a group, after required parameters.
3185 # 5: ps_right_square_after. right square brackets after required parameters.
3186 # 6: ps_seen_slash. seen slash.
3187 ps_start, ps_left_square_before, ps_group_before, ps_required, \
3188 ps_group_after, ps_right_square_after, ps_seen_slash = range(7)
3189
3190 def state_parameters_start(self, line):
3191 if self.ignore_line(line):
3192 return
3193
3194 # if this line is not indented, we have no parameters
3195 if not self.indent.infer(line):
3196 return self.next(self.state_function_docstring, line)
3197
Larry Hastings2a727912014-01-16 11:32:01 -08003198 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003199 return self.next(self.state_parameter, line)
3200
3201
3202 def to_required(self):
3203 """
3204 Transition to the "required" parameter state.
3205 """
3206 if self.parameter_state != self.ps_required:
3207 self.parameter_state = self.ps_required
3208 for p in self.function.parameters.values():
3209 p.group = -p.group
3210
3211 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003212 if self.parameter_continuation:
3213 line = self.parameter_continuation + ' ' + line.lstrip()
3214 self.parameter_continuation = ''
3215
Larry Hastings31826802013-10-19 00:09:25 -07003216 if self.ignore_line(line):
3217 return
3218
3219 assert self.indent.depth == 2
3220 indent = self.indent.infer(line)
3221 if indent == -1:
3222 # we outdented, must be to definition column
3223 return self.next(self.state_function_docstring, line)
3224
3225 if indent == 1:
3226 # we indented, must be to new parameter docstring column
3227 return self.next(self.state_parameter_docstring_start, line)
3228
Larry Hastings2a727912014-01-16 11:32:01 -08003229 line = line.rstrip()
3230 if line.endswith('\\'):
3231 self.parameter_continuation = line[:-1]
3232 return
3233
Larry Hastings31826802013-10-19 00:09:25 -07003234 line = line.lstrip()
3235
3236 if line in ('*', '/', '[', ']'):
3237 self.parse_special_symbol(line)
3238 return
3239
3240 if self.parameter_state in (self.ps_start, self.ps_required):
3241 self.to_required()
3242 elif self.parameter_state == self.ps_left_square_before:
3243 self.parameter_state = self.ps_group_before
3244 elif self.parameter_state == self.ps_group_before:
3245 if not self.group:
3246 self.to_required()
3247 elif self.parameter_state == self.ps_group_after:
3248 pass
3249 else:
3250 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3251
Larry Hastings2a727912014-01-16 11:32:01 -08003252 base, equals, default = line.rpartition('=')
3253 if not equals:
3254 base = default
3255 default = None
Larry Hastings31826802013-10-19 00:09:25 -07003256 module = None
3257 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003258 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003259 module = ast.parse(ast_input)
3260 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003261 try:
3262 default = None
3263 ast_input = "def x({}): pass".format(line)
3264 module = ast.parse(ast_input)
3265 except SyntaxError:
3266 pass
Larry Hastings31826802013-10-19 00:09:25 -07003267 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003268 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003269
3270 function_args = module.body[0].args
3271 parameter = function_args.args[0]
3272
Larry Hastings16c51912014-01-07 11:53:01 -08003273 parameter_name = parameter.arg
3274 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3275
Larry Hastings2a727912014-01-16 11:32:01 -08003276 if not default:
3277 value = unspecified
3278 if 'py_default' in kwargs:
3279 fail("You can't specify py_default without specifying a default value!")
3280 else:
3281 default = default.strip()
3282 ast_input = "x = {}".format(default)
3283 try:
3284 module = ast.parse(ast_input)
3285
Larry Hastings5c661892014-01-24 06:17:25 -08003286 bad = False
3287 if 'c_default' not in kwargs:
3288 # we can only represent very simple data values in C.
3289 # detect whether default is okay, via a blacklist
3290 # of disallowed ast nodes.
3291 class DetectBadNodes(ast.NodeVisitor):
3292 bad = False
3293 def bad_node(self, node):
3294 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003295
Larry Hastings5c661892014-01-24 06:17:25 -08003296 # inline function call
3297 visit_Call = bad_node
3298 # inline if statement ("x = 3 if y else z")
3299 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003300
Larry Hastings5c661892014-01-24 06:17:25 -08003301 # comprehensions and generator expressions
3302 visit_ListComp = visit_SetComp = bad_node
3303 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003304
Larry Hastings5c661892014-01-24 06:17:25 -08003305 # literals for advanced types
3306 visit_Dict = visit_Set = bad_node
3307 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003308
Larry Hastings5c661892014-01-24 06:17:25 -08003309 # "starred": "a = [1, 2, 3]; *a"
3310 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003311
Larry Hastings5c661892014-01-24 06:17:25 -08003312 # allow ellipsis, for now
3313 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003314
Larry Hastings5c661892014-01-24 06:17:25 -08003315 blacklist = DetectBadNodes()
3316 blacklist.visit(module)
3317 bad = blacklist.bad
3318 else:
3319 # if they specify a c_default, we can be more lenient about the default value.
3320 # but at least ensure that we can turn it into text and reconstitute it correctly.
3321 bad = default != repr(eval(default))
3322 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003323 fail("Unsupported expression as default value: " + repr(default))
3324
3325 expr = module.body[0].value
3326 # mild hack: explicitly support NULL as a default value
3327 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3328 value = NULL
3329 py_default = 'None'
3330 c_default = "NULL"
3331 elif (isinstance(expr, ast.BinOp) or
3332 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3333 c_default = kwargs.get("c_default")
3334 if not (isinstance(c_default, str) and c_default):
3335 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3336 py_default = default
3337 value = unknown
3338 elif isinstance(expr, ast.Attribute):
3339 a = []
3340 n = expr
3341 while isinstance(n, ast.Attribute):
3342 a.append(n.attr)
3343 n = n.value
3344 if not isinstance(n, ast.Name):
3345 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3346 a.append(n.id)
3347 py_default = ".".join(reversed(a))
3348
3349 c_default = kwargs.get("c_default")
3350 if not (isinstance(c_default, str) and c_default):
3351 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3352
3353 try:
3354 value = eval(py_default)
3355 except NameError:
3356 value = unknown
3357 else:
3358 value = ast.literal_eval(expr)
3359 py_default = repr(value)
3360 if isinstance(value, (bool, None.__class__)):
3361 c_default = "Py_" + py_default
3362 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003363 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003364 else:
3365 c_default = py_default
3366
3367 except SyntaxError as e:
3368 fail("Syntax error: " + repr(e.text))
3369 except (ValueError, AttributeError):
3370 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003371 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003372 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003373 if not (isinstance(c_default, str) and c_default):
3374 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3375
Larry Hastings2a727912014-01-16 11:32:01 -08003376 kwargs.setdefault('c_default', c_default)
3377 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003378
Larry Hastings31826802013-10-19 00:09:25 -07003379 dict = legacy_converters if legacy else converters
3380 legacy_str = "legacy " if legacy else ""
3381 if name not in dict:
3382 fail('{} is not a valid {}converter'.format(name, legacy_str))
3383 converter = dict[name](parameter_name, self.function, value, **kwargs)
3384
3385 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003386
3387 if isinstance(converter, self_converter):
3388 if len(self.function.parameters) == 1:
3389 if (self.parameter_state != self.ps_required):
3390 fail("A 'self' parameter cannot be marked optional.")
3391 if value is not unspecified:
3392 fail("A 'self' parameter cannot have a default value.")
3393 if self.group:
3394 fail("A 'self' parameter cannot be in an optional group.")
3395 kind = inspect.Parameter.POSITIONAL_ONLY
3396 self.parameter_state = self.ps_start
3397 self.function.parameters.clear()
3398 else:
3399 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3400
Larry Hastings31826802013-10-19 00:09:25 -07003401 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003402
3403 if parameter_name in self.function.parameters:
3404 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003405 self.function.parameters[parameter_name] = p
3406
3407 def parse_converter(self, annotation):
3408 if isinstance(annotation, ast.Str):
3409 return annotation.s, True, {}
3410
3411 if isinstance(annotation, ast.Name):
3412 return annotation.id, False, {}
3413
Larry Hastings4a55fc52014-01-12 11:09:57 -08003414 if not isinstance(annotation, ast.Call):
3415 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003416
3417 name = annotation.func.id
3418 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
3419 return name, False, kwargs
3420
3421 def parse_special_symbol(self, symbol):
3422 if self.parameter_state == self.ps_seen_slash:
3423 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3424
3425 if symbol == '*':
3426 if self.keyword_only:
3427 fail("Function " + self.function.name + " uses '*' more than once.")
3428 self.keyword_only = True
3429 elif symbol == '[':
3430 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3431 self.parameter_state = self.ps_left_square_before
3432 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3433 self.parameter_state = self.ps_group_after
3434 else:
3435 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3436 self.group += 1
3437 elif symbol == ']':
3438 if not self.group:
3439 fail("Function " + self.function.name + " has a ] without a matching [.")
3440 if not any(p.group == self.group for p in self.function.parameters.values()):
3441 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3442 self.group -= 1
3443 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3444 self.parameter_state = self.ps_group_before
3445 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3446 self.parameter_state = self.ps_right_square_after
3447 else:
3448 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3449 elif symbol == '/':
3450 # ps_required is allowed here, that allows positional-only without option groups
3451 # to work (and have default values!)
3452 if (self.parameter_state not in (self.ps_required, self.ps_right_square_after, self.ps_group_before)) or self.group:
3453 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3454 if self.keyword_only:
3455 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3456 self.parameter_state = self.ps_seen_slash
3457 # fixup preceeding parameters
3458 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003459 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003460 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3461 p.kind = inspect.Parameter.POSITIONAL_ONLY
3462
3463 def state_parameter_docstring_start(self, line):
3464 self.parameter_docstring_indent = len(self.indent.margin)
3465 assert self.indent.depth == 3
3466 return self.next(self.state_parameter_docstring, line)
3467
3468 # every line of the docstring must start with at least F spaces,
3469 # where F > P.
3470 # these F spaces will be stripped.
3471 def state_parameter_docstring(self, line):
3472 stripped = line.strip()
3473 if stripped.startswith('#'):
3474 return
3475
3476 indent = self.indent.measure(line)
3477 if indent < self.parameter_docstring_indent:
3478 self.indent.infer(line)
3479 assert self.indent.depth < 3
3480 if self.indent.depth == 2:
3481 # back to a parameter
3482 return self.next(self.state_parameter, line)
3483 assert self.indent.depth == 1
3484 return self.next(self.state_function_docstring, line)
3485
3486 assert self.function.parameters
3487 last_parameter = next(reversed(list(self.function.parameters.values())))
3488
3489 new_docstring = last_parameter.docstring
3490
3491 if new_docstring:
3492 new_docstring += '\n'
3493 if stripped:
3494 new_docstring += self.indent.dedent(line)
3495
3496 last_parameter.docstring = new_docstring
3497
3498 # the final stanza of the DSL is the docstring.
3499 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003500 if self.group:
3501 fail("Function " + self.function.name + " has a ] without a matching [.")
3502
3503 stripped = line.strip()
3504 if stripped.startswith('#'):
3505 return
3506
3507 new_docstring = self.function.docstring
3508 if new_docstring:
3509 new_docstring += "\n"
3510 if stripped:
3511 line = self.indent.dedent(line).rstrip()
3512 else:
3513 line = ''
3514 new_docstring += line
3515 self.function.docstring = new_docstring
3516
3517 def format_docstring(self):
3518 f = self.function
3519
Larry Hastings5c661892014-01-24 06:17:25 -08003520 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3521 if new_or_init and not f.docstring:
3522 # don't render a docstring at all, no signature, nothing.
3523 return f.docstring
3524
Larry Hastings31826802013-10-19 00:09:25 -07003525 add, output = text_accumulator()
3526 parameters = list(f.parameters.values())
3527
3528 ##
3529 ## docstring first line
3530 ##
3531
Larry Hastings5c661892014-01-24 06:17:25 -08003532 if new_or_init:
Larry Hastings46258262014-01-22 03:05:49 -08003533 assert f.cls
3534 add(f.cls.name)
3535 else:
3536 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003537 add('(')
3538
3539 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003540 assert parameters, "We should always have a self parameter. " + repr(f)
3541 assert isinstance(parameters[0].converter, self_converter)
3542 parameters[0].right_bracket_count = 0
3543 parameters_after_self = parameters[1:]
3544 if parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003545 # for now, the only way Clinic supports positional-only parameters
Larry Hastings5c661892014-01-24 06:17:25 -08003546 # is if all of them are positional-only...
3547 #
3548 # ... except for self! self is always positional-only.
3549
3550 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters_after_self]
3551 if parameters_after_self[0].kind == inspect.Parameter.POSITIONAL_ONLY:
Larry Hastings31826802013-10-19 00:09:25 -07003552 assert all(positional_only_parameters)
3553 for p in parameters:
3554 p.right_bracket_count = abs(p.group)
3555 else:
3556 # don't put any right brackets around non-positional-only parameters, ever.
Larry Hastings5c661892014-01-24 06:17:25 -08003557 for p in parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003558 p.right_bracket_count = 0
3559
3560 right_bracket_count = 0
3561
3562 def fix_right_bracket_count(desired):
3563 nonlocal right_bracket_count
3564 s = ''
3565 while right_bracket_count < desired:
3566 s += '['
3567 right_bracket_count += 1
3568 while right_bracket_count > desired:
3569 s += ']'
3570 right_bracket_count -= 1
3571 return s
3572
3573 added_star = False
3574 add_comma = False
3575
3576 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08003577 if not p.converter.show_in_signature:
3578 continue
3579
Larry Hastings31826802013-10-19 00:09:25 -07003580 assert p.name
3581
3582 if p.is_keyword_only() and not added_star:
3583 added_star = True
3584 if add_comma:
3585 add(', ')
3586 add('*')
Larry Hastings5c661892014-01-24 06:17:25 -08003587 add_comma = True
Larry Hastings31826802013-10-19 00:09:25 -07003588
Larry Hastings5c661892014-01-24 06:17:25 -08003589 name = p.converter.signature_name or p.name
3590 a = [name]
Larry Hastings31826802013-10-19 00:09:25 -07003591 if p.converter.is_optional():
3592 a.append('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08003593 value = p.converter.py_default
3594 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08003595 value = repr(p.converter.default)
Larry Hastingsc4fe0922014-01-19 02:27:34 -08003596 a.append(value)
Larry Hastings31826802013-10-19 00:09:25 -07003597 s = fix_right_bracket_count(p.right_bracket_count)
3598 s += "".join(a)
3599 if add_comma:
3600 add(', ')
3601 add(s)
3602 add_comma = True
3603
3604 add(fix_right_bracket_count(0))
3605 add(')')
3606
Larry Hastings2a727912014-01-16 11:32:01 -08003607 # PEP 8 says:
3608 #
3609 # The Python standard library will not use function annotations
3610 # as that would result in a premature commitment to a particular
3611 # annotation style. Instead, the annotations are left for users
3612 # to discover and experiment with useful annotation styles.
3613 #
3614 # therefore this is commented out:
3615 #
3616 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003617 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08003618 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003619
3620 docstring_first_line = output()
3621
3622 # now fix up the places where the brackets look wrong
3623 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
3624
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003625 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07003626 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003627 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07003628 for p in parameters:
3629 if not p.docstring.strip():
3630 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003631 if spacer_line:
3632 add('\n')
3633 else:
3634 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07003635 add(" ")
3636 add(p.name)
3637 add('\n')
3638 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003639 parameters = output()
3640 if parameters:
3641 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07003642
3643 ##
3644 ## docstring body
3645 ##
3646
3647 docstring = f.docstring.rstrip()
3648 lines = [line.rstrip() for line in docstring.split('\n')]
3649
3650 # Enforce the summary line!
3651 # The first line of a docstring should be a summary of the function.
3652 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
3653 # by itself.
3654 #
3655 # Argument Clinic enforces the following rule:
3656 # * either the docstring is empty,
3657 # * or it must have a summary line.
3658 #
3659 # Guido said Clinic should enforce this:
3660 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
3661
3662 if len(lines) >= 2:
3663 if lines[1]:
3664 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
3665 "Every non-blank function docstring must start with\n" +
3666 "a single line summary followed by an empty line.")
3667 elif len(lines) == 1:
3668 # the docstring is only one line right now--the summary line.
3669 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003670 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07003671 lines.append('')
3672
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003673 parameters_marker_count = len(docstring.split('{parameters}')) - 1
3674 if parameters_marker_count > 1:
3675 fail('You may not specify {parameters} more than once in a docstring!')
3676
3677 if not parameters_marker_count:
3678 # insert after summary line
3679 lines.insert(2, '{parameters}')
3680
3681 # insert at front of docstring
3682 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07003683
3684 docstring = "\n".join(lines)
3685
3686 add(docstring)
3687 docstring = output()
3688
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003689 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07003690 docstring = docstring.rstrip()
3691
3692 return docstring
3693
3694 def state_terminal(self, line):
3695 """
3696 Called when processing the block is done.
3697 """
3698 assert not line
3699
3700 if not self.function:
3701 return
3702
3703 if self.keyword_only:
3704 values = self.function.parameters.values()
3705 if not values:
3706 no_parameter_after_star = True
3707 else:
3708 last_parameter = next(reversed(list(values)))
3709 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
3710 if no_parameter_after_star:
3711 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
3712
3713 # remove trailing whitespace from all parameter docstrings
3714 for name, value in self.function.parameters.items():
3715 if not value:
3716 continue
3717 value.docstring = value.docstring.rstrip()
3718
3719 self.function.docstring = self.format_docstring()
3720
3721
Larry Hastings5c661892014-01-24 06:17:25 -08003722
3723
Larry Hastings31826802013-10-19 00:09:25 -07003724# maps strings to callables.
3725# the callable should return an object
3726# that implements the clinic parser
3727# interface (__init__ and parse).
3728#
3729# example parsers:
3730# "clinic", handles the Clinic DSL
3731# "python", handles running Python code
3732#
3733parsers = {'clinic' : DSLParser, 'python': PythonParser}
3734
3735
3736clinic = None
3737
3738
3739def main(argv):
3740 import sys
3741
3742 if sys.version_info.major < 3 or sys.version_info.minor < 3:
3743 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
3744
3745 import argparse
3746 cmdline = argparse.ArgumentParser()
3747 cmdline.add_argument("-f", "--force", action='store_true')
3748 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08003749 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07003750 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003751 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07003752 cmdline.add_argument("filename", type=str, nargs="*")
3753 ns = cmdline.parse_args(argv)
3754
3755 if ns.converters:
3756 if ns.filename:
3757 print("Usage error: can't specify --converters and a filename at the same time.")
3758 print()
3759 cmdline.print_usage()
3760 sys.exit(-1)
3761 converters = []
3762 return_converters = []
3763 ignored = set("""
3764 add_c_converter
3765 add_c_return_converter
3766 add_default_legacy_c_converter
3767 add_legacy_c_converter
3768 """.strip().split())
3769 module = globals()
3770 for name in module:
3771 for suffix, ids in (
3772 ("_return_converter", return_converters),
3773 ("_converter", converters),
3774 ):
3775 if name in ignored:
3776 continue
3777 if name.endswith(suffix):
3778 ids.append((name, name[:-len(suffix)]))
3779 break
3780 print()
3781
3782 print("Legacy converters:")
3783 legacy = sorted(legacy_converters)
3784 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
3785 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
3786 print()
3787
3788 for title, attribute, ids in (
3789 ("Converters", 'converter_init', converters),
3790 ("Return converters", 'return_converter_init', return_converters),
3791 ):
3792 print(title + ":")
3793 longest = -1
3794 for name, short_name in ids:
3795 longest = max(longest, len(short_name))
3796 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
3797 cls = module[name]
3798 callable = getattr(cls, attribute, None)
3799 if not callable:
3800 continue
3801 signature = inspect.signature(callable)
3802 parameters = []
3803 for parameter_name, parameter in signature.parameters.items():
3804 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
3805 if parameter.default != inspect.Parameter.empty:
3806 s = '{}={!r}'.format(parameter_name, parameter.default)
3807 else:
3808 s = parameter_name
3809 parameters.append(s)
3810 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07003811 print()
Larry Hastings2a727912014-01-16 11:32:01 -08003812 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
3813 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07003814 sys.exit(0)
3815
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003816 if ns.make:
3817 if ns.output or ns.filename:
3818 print("Usage error: can't use -o or filenames with --make.")
3819 print()
3820 cmdline.print_usage()
3821 sys.exit(-1)
3822 for root, dirs, files in os.walk('.'):
Larry Hastings5c661892014-01-24 06:17:25 -08003823 for rcs_dir in ('.svn', '.git', '.hg', 'build'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003824 if rcs_dir in dirs:
3825 dirs.remove(rcs_dir)
3826 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08003827 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003828 continue
3829 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08003830 if ns.verbose:
3831 print(path)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003832 parse_file(path, verify=not ns.force)
3833 return
3834
Larry Hastings31826802013-10-19 00:09:25 -07003835 if not ns.filename:
3836 cmdline.print_usage()
3837 sys.exit(-1)
3838
3839 if ns.output and len(ns.filename) > 1:
3840 print("Usage error: can't use -o with multiple filenames.")
3841 print()
3842 cmdline.print_usage()
3843 sys.exit(-1)
3844
3845 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08003846 if ns.verbose:
3847 print(filename)
Larry Hastings31826802013-10-19 00:09:25 -07003848 parse_file(filename, output=ns.output, verify=not ns.force)
3849
3850
3851if __name__ == "__main__":
3852 sys.exit(main(sys.argv[1:]))