blob: 7f1b059e805c63c1159418fc0c429defb2c0d4c1 [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 (
Zachary Ware9d7849f2014-01-25 03:26:20 -0600123 ('\\', '\\\\'), # must be first!
Larry Hastings31826802013-10-19 00:09:25 -0700124 ('"', '\\"'),
125 ("'", "\\'"),
126 ):
127 s = s.replace(old, new)
128 return s
129
Larry Hastings4903e002014-01-18 00:26:16 -0800130def c_repr(s):
131 return '"' + s + '"'
132
133
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700134is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
135
136def is_legal_py_identifier(s):
137 return all(is_legal_c_identifier(field) for field in s.split('.'))
138
Larry Hastingsbebf7352014-01-17 17:47:17 -0800139# identifiers that are okay in Python but aren't a good idea in C.
140# so if they're used Argument Clinic will add "_value" to the end
141# of the name in C.
Larry Hastings31826802013-10-19 00:09:25 -0700142c_keywords = set("""
Larry Hastings5c661892014-01-24 06:17:25 -0800143asm auto break case char const continue default do double
144else enum extern float for goto if inline int long
145register return short signed sizeof static struct switch
Larry Hastingsbebf7352014-01-17 17:47:17 -0800146typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700147""".strip().split())
148
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700149def ensure_legal_c_identifier(s):
150 # for now, just complain if what we're given isn't legal
151 if not is_legal_c_identifier(s):
152 fail("Illegal C identifier: {}".format(s))
153 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700154 if s in c_keywords:
155 return s + "_value"
156 return s
157
158def rstrip_lines(s):
159 text, add, output = _text_accumulator()
160 for line in s.split('\n'):
161 add(line.rstrip())
162 add('\n')
163 text.pop()
164 return output()
165
166def linear_format(s, **kwargs):
167 """
168 Perform str.format-like substitution, except:
169 * The strings substituted must be on lines by
170 themselves. (This line is the "source line".)
171 * If the substitution text is empty, the source line
172 is removed in the output.
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800173 * If the field is not recognized, the original line
174 is passed unmodified through to the output.
Larry Hastings31826802013-10-19 00:09:25 -0700175 * If the substitution text is not empty:
176 * Each line of the substituted text is indented
177 by the indent of the source line.
178 * A newline will be added to the end.
179 """
180
181 add, output = text_accumulator()
182 for line in s.split('\n'):
183 indent, curly, trailing = line.partition('{')
184 if not curly:
185 add(line)
186 add('\n')
187 continue
188
189 name, curl, trailing = trailing.partition('}')
190 if not curly or name not in kwargs:
191 add(line)
192 add('\n')
193 continue
194
195 if trailing:
196 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
197 if indent.strip():
198 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
199
200 value = kwargs[name]
201 if not value:
202 continue
203
204 value = textwrap.indent(rstrip_lines(value), indent)
205 add(value)
206 add('\n')
207
208 return output()[:-1]
209
Larry Hastingsbebf7352014-01-17 17:47:17 -0800210def indent_all_lines(s, prefix):
211 """
212 Returns 's', with 'prefix' prepended to all lines.
213
214 If the last line is empty, prefix is not prepended
215 to it. (If s is blank, returns s unchanged.)
216
217 (textwrap.indent only adds to non-blank lines.)
218 """
219 split = s.split('\n')
220 last = split.pop()
221 final = []
222 for line in split:
223 final.append(prefix)
224 final.append(line)
225 final.append('\n')
226 if last:
227 final.append(prefix)
228 final.append(last)
229 return ''.join(final)
230
231def suffix_all_lines(s, suffix):
232 """
233 Returns 's', with 'suffix' appended to all lines.
234
235 If the last line is empty, suffix is not appended
236 to it. (If s is blank, returns s unchanged.)
237 """
238 split = s.split('\n')
239 last = split.pop()
240 final = []
241 for line in split:
242 final.append(line)
243 final.append(suffix)
244 final.append('\n')
245 if last:
246 final.append(last)
247 final.append(suffix)
248 return ''.join(final)
249
250
Larry Hastingsebdcb502013-11-23 14:54:00 -0800251def version_splitter(s):
252 """Splits a version string into a tuple of integers.
253
254 The following ASCII characters are allowed, and employ
255 the following conversions:
256 a -> -3
257 b -> -2
258 c -> -1
259 (This permits Python-style version strings such as "1.4b3".)
260 """
261 version = []
262 accumulator = []
263 def flush():
264 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800265 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800266 version.append(int(''.join(accumulator)))
267 accumulator.clear()
268
269 for c in s:
270 if c.isdigit():
271 accumulator.append(c)
272 elif c == '.':
273 flush()
274 elif c in 'abc':
275 flush()
276 version.append('abc'.index(c) - 3)
277 else:
278 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
279 flush()
280 return tuple(version)
281
282def version_comparitor(version1, version2):
283 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
284 for i, (a, b) in enumerate(iterator):
285 if a < b:
286 return -1
287 if a > b:
288 return 1
289 return 0
290
Larry Hastings31826802013-10-19 00:09:25 -0700291
292class CRenderData:
293 def __init__(self):
294
295 # The C statements to declare variables.
296 # Should be full lines with \n eol characters.
297 self.declarations = []
298
299 # The C statements required to initialize the variables before the parse call.
300 # Should be full lines with \n eol characters.
301 self.initializers = []
302
303 # The entries for the "keywords" array for PyArg_ParseTuple.
304 # Should be individual strings representing the names.
305 self.keywords = []
306
307 # The "format units" for PyArg_ParseTuple.
308 # Should be individual strings that will get
309 self.format_units = []
310
311 # The varargs arguments for PyArg_ParseTuple.
312 self.parse_arguments = []
313
314 # The parameter declarations for the impl function.
315 self.impl_parameters = []
316
317 # The arguments to the impl function at the time it's called.
318 self.impl_arguments = []
319
320 # For return converters: the name of the variable that
321 # should receive the value returned by the impl.
322 self.return_value = "return_value"
323
324 # For return converters: the code to convert the return
325 # value from the parse function. This is also where
326 # you should check the _return_value for errors, and
327 # "goto exit" if there are any.
328 self.return_conversion = []
329
330 # The C statements required to clean up after the impl call.
331 self.cleanup = []
332
333
334class Language(metaclass=abc.ABCMeta):
335
336 start_line = ""
337 body_prefix = ""
338 stop_line = ""
339 checksum_line = ""
340
341 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800342 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700343 pass
344
345 def validate(self):
346 def assert_only_one(field, token='dsl_name'):
347 line = getattr(self, field)
348 token = '{' + token + '}'
349 if len(line.split(token)) != 2:
350 fail(self.__class__.__name__ + " " + field + " must contain " + token + " exactly once!")
351 assert_only_one('start_line')
352 assert_only_one('stop_line')
353 assert_only_one('checksum_line')
354 assert_only_one('checksum_line', 'checksum')
355
356 if len(self.body_prefix.split('{dsl_name}')) >= 3:
357 fail(self.__class__.__name__ + " body_prefix may contain " + token + " once at most!")
358
359
360
361class PythonLanguage(Language):
362
363 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800364 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700365 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800366 stop_line = "#[{dsl_name} start generated code]*/"
367 checksum_line = "#/*[{dsl_name} end generated code: checksum={checksum}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700368
369
370def permute_left_option_groups(l):
371 """
372 Given [1, 2, 3], should yield:
373 ()
374 (3,)
375 (2, 3)
376 (1, 2, 3)
377 """
378 yield tuple()
379 accumulator = []
380 for group in reversed(l):
381 accumulator = list(group) + accumulator
382 yield tuple(accumulator)
383
384
385def permute_right_option_groups(l):
386 """
387 Given [1, 2, 3], should yield:
388 ()
389 (1,)
390 (1, 2)
391 (1, 2, 3)
392 """
393 yield tuple()
394 accumulator = []
395 for group in l:
396 accumulator.extend(group)
397 yield tuple(accumulator)
398
399
400def permute_optional_groups(left, required, right):
401 """
402 Generator function that computes the set of acceptable
403 argument lists for the provided iterables of
404 argument groups. (Actually it generates a tuple of tuples.)
405
406 Algorithm: prefer left options over right options.
407
408 If required is empty, left must also be empty.
409 """
410 required = tuple(required)
411 result = []
412
413 if not required:
414 assert not left
415
416 accumulator = []
417 counts = set()
418 for r in permute_right_option_groups(right):
419 for l in permute_left_option_groups(left):
420 t = l + required + r
421 if len(t) in counts:
422 continue
423 counts.add(len(t))
424 accumulator.append(t)
425
426 accumulator.sort(key=len)
427 return tuple(accumulator)
428
429
430class CLanguage(Language):
431
Larry Hastings61272b72014-01-07 12:41:53 -0800432 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700433 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800434 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700435 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800436 stop_line = "[{dsl_name} start generated code]*/"
437 checksum_line = "/*[{dsl_name} end generated code: checksum={checksum}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700438
Larry Hastingsbebf7352014-01-17 17:47:17 -0800439 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700440 function = None
441 for o in signatures:
442 if isinstance(o, Function):
443 if function:
444 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
445 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800446 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700447
448 def docstring_for_c_string(self, f):
449 text, add, output = _text_accumulator()
450 # turn docstring into a properly quoted C string
451 for line in f.docstring.split('\n'):
452 add('"')
453 add(quoted_for_c_string(line))
454 add('\\n"\n')
455
456 text.pop()
457 add('"')
458 return ''.join(text)
459
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800460 _templates = {}
461 # the templates will be run through str.format(),
462 # so actual curly-braces need to be doubled up.
463 templates_source = """
464__________________________________________________
465
466docstring_prototype
467
468PyDoc_VAR({c_basename}__doc__);
469__________________________________________________
470
471docstring_definition
472
473PyDoc_STRVAR({c_basename}__doc__,
474{docstring});
475__________________________________________________
476
477impl_definition
478
479static {impl_return_type}
480{c_basename}_impl({impl_parameters})
481__________________________________________________
482
483parser_prototype_noargs
484
485static PyObject *
486{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
487__________________________________________________
488
489parser_prototype_meth_o
490
491# SLIGHT HACK
492# METH_O uses {impl_parameters} for the parser!
493
494static PyObject *
495{c_basename}({impl_parameters})
496__________________________________________________
497
498parser_prototype_varargs
499
500static PyObject *
501{c_basename}({self_type}{self_name}, PyObject *args)
502__________________________________________________
503
504parser_prototype_keyword
505
506static PyObject *
507{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
508__________________________________________________
509
510parser_prototype_init
511
512static int
513{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
514__________________________________________________
515
516parser_definition_simple_no_parsing
517
518{{
519 return {c_basename}_impl({impl_arguments});
520}}
521__________________________________________________
522
523parser_definition_start
524
525{{
526 {return_value_declaration}
527 {declarations}
528 {initializers}
529{empty line}
530__________________________________________________
531
532parser_definition_end
533
534 {return_conversion}
535
536{exit_label}
537 {cleanup}
538 return return_value;
539}}
540__________________________________________________
541
542parser_definition_impl_call
543
544 {return_value} = {c_basename}_impl({impl_arguments});
545__________________________________________________
546
547parser_definition_unpack_tuple
548
549 if (!PyArg_UnpackTuple(args, "{name}",
550 {unpack_min}, {unpack_max},
551 {parse_arguments}))
552 goto exit;
553__________________________________________________
554
555parser_definition_parse_tuple
556
557 if (!PyArg_ParseTuple(args,
558 "{format_units}:{name}",
559 {parse_arguments}))
560 goto exit;
561__________________________________________________
562
563parser_definition_option_groups
564 {option_group_parsing}
565
566__________________________________________________
567
568parser_definition_parse_tuple_and_keywords
569
570 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
571 "{format_units}:{name}", _keywords,
572 {parse_arguments}))
573 goto exit;
574__________________________________________________
575
576parser_definition_no_positional
577
578 if (!_PyArg_NoPositional("{name}", args))
579 goto exit;
580
581__________________________________________________
582
583parser_definition_no_keywords
584
585 if (!_PyArg_NoKeywords("{name}", kwargs))
586 goto exit;
587
588__________________________________________________
589
590methoddef_define
591
592#define {methoddef_name} \\
593 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
594__________________________________________________
595""".rstrip()
596
597 title = ''
598 buffer = []
599 line = None
600 for line in templates_source.split('\n'):
601 line = line.rstrip()
602 if line.startswith('# '):
603 # comment
604 continue
605 if line.startswith("_____"):
606 if not buffer:
607 continue
608 assert title not in _templates, "defined template twice: " + repr(title)
609 buffer = '\n'.join(buffer).rstrip()
610 buffer = buffer.replace('{empty line}', '')
611 _templates[title] = buffer
612 buffer = []
613 title = ''
614 continue
615 if not title:
616 if not line:
617 continue
618 title = line
619 continue
620 if not (line or buffer):
621 # throw away leading blank lines
622 continue
623 buffer.append(line)
624
625 assert not title, 'ensure templates_source ends with ______ (still adding to ' + repr(title) + ")"
626
627 del templates_source
628 del title
629 del buffer
630 del line
631
632 # for name, value in _templates.items():
633 # print(name + ":")
634 # pprint.pprint(value)
635 # print()
Larry Hastings31826802013-10-19 00:09:25 -0700636
Larry Hastingsbebf7352014-01-17 17:47:17 -0800637 def output_templates(self, f):
638 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800639 assert parameters
640 assert isinstance(parameters[0].converter, self_converter)
641 del parameters[0]
Larry Hastingsbebf7352014-01-17 17:47:17 -0800642 converters = [p.converter for p in parameters]
643
644 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
645 default_return_converter = (not f.return_converter or
646 f.return_converter.type == 'PyObject *')
647
648 positional = parameters and (parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY)
649 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
650 first_optional = len(parameters)
651 for i, p in enumerate(parameters):
652 c = p.converter
653 if type(c) != object_converter:
654 break
655 if c.format_unit != 'O':
656 break
657 if p.default is not unspecified:
658 first_optional = min(first_optional, i)
659 else:
660 all_boring_objects = True
661
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800662 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
663
Larry Hastingsbebf7352014-01-17 17:47:17 -0800664 meth_o = (len(parameters) == 1 and
665 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
666 not converters[0].is_optional() and
667 isinstance(converters[0], object_converter) and
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800668 converters[0].format_unit == 'O' and
669 not new_or_init)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800670
671 # we have to set seven things before we're done:
672 #
673 # docstring_prototype
674 # docstring_definition
675 # impl_prototype
676 # methoddef_define
677 # parser_prototype
678 # parser_definition
679 # impl_definition
Larry Hastingsbebf7352014-01-17 17:47:17 -0800680
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800681 templates = self._templates
Larry Hastingsbebf7352014-01-17 17:47:17 -0800682
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800683 return_value_declaration = "PyObject *return_value = NULL;"
Larry Hastings31826802013-10-19 00:09:25 -0700684
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800685 methoddef_define = templates['methoddef_define']
Larry Hastings5c661892014-01-24 06:17:25 -0800686 if new_or_init and not f.docstring:
687 docstring_prototype = docstring_definition = ''
688 else:
689 docstring_prototype = templates['docstring_prototype']
690 docstring_definition = templates['docstring_definition']
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800691 impl_definition = templates['impl_definition']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800692 impl_prototype = parser_prototype = parser_definition = None
693
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800694 parser_body_fields = None
695 def parser_body(prototype, *fields):
696 nonlocal parser_body_fields
697 add, output = text_accumulator()
698 add(prototype)
699 parser_body_fields = fields
700 fields = list(fields)
701 fields.insert(0, 'parser_definition_start')
702 fields.append('parser_definition_impl_call')
703 fields.append('parser_definition_end')
704 for field in fields:
705 add('\n')
706 add(templates[field])
707 return output()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800708
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800709 def insert_keywords(s):
710 return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
Larry Hastingsbebf7352014-01-17 17:47:17 -0800711
712 if not parameters:
713 # no parameters, METH_NOARGS
714
715 flags = "METH_NOARGS"
716
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800717 parser_prototype = templates['parser_prototype_noargs']
718 parser_definition = parser_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800719
720 if default_return_converter:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800721 parser_definition = parser_prototype + '\n' + templates['parser_definition_simple_no_parsing']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800722 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800723 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700724
Larry Hastingsbebf7352014-01-17 17:47:17 -0800725 elif meth_o:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800726 flags = "METH_O"
727 # impl_definition = templates['parser_prototype_meth_o']
728
Larry Hastingsbebf7352014-01-17 17:47:17 -0800729 if default_return_converter:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800730 # maps perfectly to METH_O, doesn't need a return converter.
731 # so we skip making a parse function
732 # and call directly into the impl function.
Larry Hastingsbebf7352014-01-17 17:47:17 -0800733 impl_prototype = parser_prototype = parser_definition = ''
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800734 impl_definition = templates['parser_prototype_meth_o']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800735 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800736 parser_prototype = templates['parser_prototype_meth_o']
737 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700738
Larry Hastingsbebf7352014-01-17 17:47:17 -0800739 elif has_option_groups:
740 # positional parameters with option groups
741 # (we have to generate lots of PyArg_ParseTuple calls
742 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700743
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800744 flags = "METH_VARARGS"
745 parser_prototype = templates['parser_prototype_varargs']
Larry Hastings31826802013-10-19 00:09:25 -0700746
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800747 parser_definition = parser_body(parser_prototype, 'parser_definition_option_groups')
Larry Hastings31826802013-10-19 00:09:25 -0700748
Larry Hastingsbebf7352014-01-17 17:47:17 -0800749 elif positional and all_boring_objects:
750 # positional-only, but no option groups,
751 # and nothing but normal objects:
752 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700753
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800754 flags = "METH_VARARGS"
755 parser_prototype = templates['parser_prototype_varargs']
Larry Hastings31826802013-10-19 00:09:25 -0700756
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800757 parser_definition = parser_body(parser_prototype, 'parser_definition_unpack_tuple')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800758
759 elif positional:
760 # positional-only, but no option groups
761 # we only need one call to PyArg_ParseTuple
762
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800763 flags = "METH_VARARGS"
764 parser_prototype = templates['parser_prototype_varargs']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800765
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800766 parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800767
768 else:
769 # positional-or-keyword arguments
770 flags = "METH_VARARGS|METH_KEYWORDS"
771
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800772 parser_prototype = templates['parser_prototype_keyword']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800773
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800774 parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple_and_keywords')
775 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700776
Larry Hastings31826802013-10-19 00:09:25 -0700777
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800778 if new_or_init:
779 methoddef_define = ''
780
781 if f.kind == METHOD_NEW:
782 parser_prototype = templates['parser_prototype_keyword']
783 else:
784 return_value_declaration = "int return_value = -1;"
785 parser_prototype = templates['parser_prototype_init']
786
787 fields = list(parser_body_fields)
788 parses_positional = 'METH_NOARGS' not in flags
789 parses_keywords = 'METH_KEYWORDS' in flags
790 if parses_keywords:
791 assert parses_positional
792
793 if not parses_keywords:
794 fields.insert(0, 'parser_definition_no_keywords')
795 if not parses_positional:
796 fields.insert(0, 'parser_definition_no_positional')
797
798 parser_definition = parser_body(parser_prototype, *fields)
799 if parses_keywords:
800 parser_definition = insert_keywords(parser_definition)
801
Larry Hastings31826802013-10-19 00:09:25 -0700802
Larry Hastingsbebf7352014-01-17 17:47:17 -0800803 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800804 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700805
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800806 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700807
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800808 # add ';' to the end of parser_prototype and impl_prototype
809 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800810 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800811 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800812 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800813 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700814
Larry Hastingsbebf7352014-01-17 17:47:17 -0800815 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800816 impl_prototype = impl_definition
817 if impl_prototype:
818 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700819
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800820 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800821
822 d = {
823 "docstring_prototype" : docstring_prototype,
824 "docstring_definition" : docstring_definition,
825 "impl_prototype" : impl_prototype,
826 "methoddef_define" : methoddef_define,
827 "parser_prototype" : parser_prototype,
828 "parser_definition" : parser_definition,
829 "impl_definition" : impl_definition,
830 }
831
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800832 # make sure we didn't forget to assign something,
833 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -0800834 d2 = {}
835 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800836 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800837 if value:
838 value = '\n' + value + '\n'
839 d2[name] = value
840 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700841
842 @staticmethod
843 def group_to_variable_name(group):
844 adjective = "left_" if group < 0 else "right_"
845 return "group_" + adjective + str(abs(group))
846
847 def render_option_group_parsing(self, f, template_dict):
848 # positional only, grouped, optional arguments!
849 # can be optional on the left or right.
850 # here's an example:
851 #
852 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
853 #
854 # Here group D are required, and all other groups are optional.
855 # (Group D's "group" is actually None.)
856 # We can figure out which sets of arguments we have based on
857 # how many arguments are in the tuple.
858 #
859 # Note that you need to count up on both sides. For example,
860 # you could have groups C+D, or C+D+E, or C+D+E+F.
861 #
862 # What if the number of arguments leads us to an ambiguous result?
863 # Clinic prefers groups on the left. So in the above example,
864 # five arguments would map to B+C, not C+D.
865
866 add, output = text_accumulator()
867 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800868 if isinstance(parameters[0].converter, self_converter):
869 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -0700870
871 groups = []
872 group = None
873 left = []
874 right = []
875 required = []
876 last = unspecified
877
878 for p in parameters:
879 group_id = p.group
880 if group_id != last:
881 last = group_id
882 group = []
883 if group_id < 0:
884 left.append(group)
885 elif group_id == 0:
886 group = required
887 else:
888 right.append(group)
889 group.append(p)
890
891 count_min = sys.maxsize
892 count_max = -1
893
Larry Hastings2a727912014-01-16 11:32:01 -0800894 add("switch (PyTuple_GET_SIZE(args)) {{\n")
Larry Hastings31826802013-10-19 00:09:25 -0700895 for subset in permute_optional_groups(left, required, right):
896 count = len(subset)
897 count_min = min(count_min, count)
898 count_max = max(count_max, count)
899
Larry Hastings583baa82014-01-12 08:49:30 -0800900 if count == 0:
901 add(""" case 0:
902 break;
903""")
904 continue
905
Larry Hastings31826802013-10-19 00:09:25 -0700906 group_ids = {p.group for p in subset} # eliminate duplicates
907 d = {}
908 d['count'] = count
909 d['name'] = f.name
910 d['groups'] = sorted(group_ids)
911 d['format_units'] = "".join(p.converter.format_unit for p in subset)
912
913 parse_arguments = []
914 for p in subset:
915 p.converter.parse_argument(parse_arguments)
916 d['parse_arguments'] = ", ".join(parse_arguments)
917
918 group_ids.discard(0)
919 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
920 lines = "\n".join(lines)
921
922 s = """
923 case {count}:
924 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
Larry Hastings46258262014-01-22 03:05:49 -0800925 goto exit;
Larry Hastings31826802013-10-19 00:09:25 -0700926 {group_booleans}
927 break;
928"""[1:]
929 s = linear_format(s, group_booleans=lines)
930 s = s.format_map(d)
931 add(s)
932
933 add(" default:\n")
934 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
935 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -0800936 add(' goto exit;\n')
Larry Hastings31826802013-10-19 00:09:25 -0700937 add("}}")
938 template_dict['option_group_parsing'] = output()
939
Larry Hastingsbebf7352014-01-17 17:47:17 -0800940 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -0700941 if not f:
942 return ""
943
944 add, output = text_accumulator()
945 data = CRenderData()
946
Larry Hastings31826802013-10-19 00:09:25 -0700947 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800948 assert parameters, "We should always have a 'self' at this point!"
949
Larry Hastings31826802013-10-19 00:09:25 -0700950 converters = [p.converter for p in parameters]
951
Larry Hastings5c661892014-01-24 06:17:25 -0800952 templates = self.output_templates(f)
953
954 f_self = parameters[0]
955 selfless = parameters[1:]
956 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
957
958 last_group = 0
959 first_optional = len(selfless)
960 positional = selfless and selfless[-1].kind == inspect.Parameter.POSITIONAL_ONLY
961 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
962 default_return_converter = (not f.return_converter or
963 f.return_converter.type == 'PyObject *')
964 has_option_groups = False
965
966 # offset i by -1 because first_optional needs to ignore self
967 for i, p in enumerate(parameters, -1):
968 c = p.converter
969
970 if (i != -1) and (p.default is not unspecified):
971 first_optional = min(first_optional, i)
972
973 # insert group variable
974 group = p.group
975 if last_group != group:
976 last_group = group
977 if group:
978 group_name = self.group_to_variable_name(group)
979 data.impl_arguments.append(group_name)
980 data.declarations.append("int " + group_name + " = 0;")
981 data.impl_parameters.append("int " + group_name)
982 has_option_groups = True
983
984 c.render(p, data)
985
986 if has_option_groups and (not positional):
987 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
988
989 # HACK
990 # when we're METH_O, but have a custom return converter,
991 # we use "impl_parameters" for the parsing function
992 # because that works better. but that means we must
993 # supress actually declaring the impl's parameters
994 # as variables in the parsing function. but since it's
995 # METH_O, we have exactly one anyway, so we know exactly
996 # where it is.
997 if ("METH_O" in templates['methoddef_define'] and
998 not default_return_converter):
999 data.declarations.pop(0)
1000
Larry Hastings31826802013-10-19 00:09:25 -07001001 template_dict = {}
1002
1003 full_name = f.full_name
1004 template_dict['full_name'] = full_name
1005
Larry Hastings5c661892014-01-24 06:17:25 -08001006 if new_or_init:
1007 name = f.cls.name
1008 else:
1009 name = f.name
1010
Larry Hastings31826802013-10-19 00:09:25 -07001011 template_dict['name'] = name
1012
Larry Hastings8666e652014-01-12 14:12:59 -08001013 if f.c_basename:
1014 c_basename = f.c_basename
1015 else:
1016 fields = full_name.split(".")
1017 if fields[-1] == '__new__':
1018 fields.pop()
1019 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001020
Larry Hastings31826802013-10-19 00:09:25 -07001021 template_dict['c_basename'] = c_basename
1022
1023 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1024 template_dict['methoddef_name'] = methoddef_name
1025
1026 template_dict['docstring'] = self.docstring_for_c_string(f)
1027
Larry Hastings5c661892014-01-24 06:17:25 -08001028 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001029
Larry Hastings31826802013-10-19 00:09:25 -07001030 f.return_converter.render(f, data)
1031 template_dict['impl_return_type'] = f.return_converter.type
1032
1033 template_dict['declarations'] = "\n".join(data.declarations)
1034 template_dict['initializers'] = "\n\n".join(data.initializers)
1035 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1036 template_dict['format_units'] = ''.join(data.format_units)
1037 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1038 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1039 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
1040 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
1041 template_dict['cleanup'] = "".join(data.cleanup)
1042 template_dict['return_value'] = data.return_value
1043
Larry Hastings5c661892014-01-24 06:17:25 -08001044 # used by unpack tuple code generator
1045 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1046 unpack_min = first_optional
1047 unpack_max = len(selfless)
1048 template_dict['unpack_min'] = str(unpack_min)
1049 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001050
Larry Hastingsbebf7352014-01-17 17:47:17 -08001051 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001052 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001053
Larry Hastingsbebf7352014-01-17 17:47:17 -08001054 for name, destination in clinic.field_destinations.items():
1055 template = templates[name]
1056 if has_option_groups:
1057 template = linear_format(template,
1058 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001059 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001060 declarations=template_dict['declarations'],
1061 return_conversion=template_dict['return_conversion'],
1062 initializers=template_dict['initializers'],
1063 cleanup=template_dict['cleanup'],
1064 )
Larry Hastings31826802013-10-19 00:09:25 -07001065
Larry Hastingsbebf7352014-01-17 17:47:17 -08001066 # Only generate the "exit:" label
1067 # if we have any gotos
1068 need_exit_label = "goto exit;" in template
1069 template = linear_format(template,
1070 exit_label="exit:" if need_exit_label else ''
1071 )
Larry Hastings31826802013-10-19 00:09:25 -07001072
Larry Hastingsbebf7352014-01-17 17:47:17 -08001073 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001074
Larry Hastingsbebf7352014-01-17 17:47:17 -08001075 if clinic.line_prefix:
1076 s = indent_all_lines(s, clinic.line_prefix)
1077 if clinic.line_suffix:
1078 s = suffix_all_lines(s, clinic.line_suffix)
1079
1080 destination.append(s)
1081
1082 return clinic.get_destination('block').dump()
1083
Larry Hastings31826802013-10-19 00:09:25 -07001084
1085
Larry Hastings5c661892014-01-24 06:17:25 -08001086
Larry Hastings31826802013-10-19 00:09:25 -07001087@contextlib.contextmanager
1088def OverrideStdioWith(stdout):
1089 saved_stdout = sys.stdout
1090 sys.stdout = stdout
1091 try:
1092 yield
1093 finally:
1094 assert sys.stdout is stdout
1095 sys.stdout = saved_stdout
1096
1097
1098def create_regex(before, after):
1099 """Create an re object for matching marker lines."""
1100 pattern = r'^{}(\w+){}$'
1101 return re.compile(pattern.format(re.escape(before), re.escape(after)))
1102
1103
1104class Block:
1105 r"""
1106 Represents a single block of text embedded in
1107 another file. If dsl_name is None, the block represents
1108 verbatim text, raw original text from the file, in
1109 which case "input" will be the only non-false member.
1110 If dsl_name is not None, the block represents a Clinic
1111 block.
1112
1113 input is always str, with embedded \n characters.
1114 input represents the original text from the file;
1115 if it's a Clinic block, it is the original text with
1116 the body_prefix and redundant leading whitespace removed.
1117
1118 dsl_name is either str or None. If str, it's the text
1119 found on the start line of the block between the square
1120 brackets.
1121
1122 signatures is either list or None. If it's a list,
1123 it may only contain clinic.Module, clinic.Class, and
1124 clinic.Function objects. At the moment it should
1125 contain at most one of each.
1126
1127 output is either str or None. If str, it's the output
1128 from this block, with embedded '\n' characters.
1129
1130 indent is either str or None. It's the leading whitespace
1131 that was found on every line of input. (If body_prefix is
1132 not empty, this is the indent *after* removing the
1133 body_prefix.)
1134
1135 preindent is either str or None. It's the whitespace that
1136 was found in front of every line of input *before* the
1137 "body_prefix" (see the Language object). If body_prefix
1138 is empty, preindent must always be empty too.
1139
1140 To illustrate indent and preindent: Assume that '_'
1141 represents whitespace. If the block processed was in a
1142 Python file, and looked like this:
1143 ____#/*[python]
1144 ____#__for a in range(20):
1145 ____#____print(a)
1146 ____#[python]*/
1147 "preindent" would be "____" and "indent" would be "__".
1148
1149 """
1150 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1151 assert isinstance(input, str)
1152 self.input = input
1153 self.dsl_name = dsl_name
1154 self.signatures = signatures or []
1155 self.output = output
1156 self.indent = indent
1157 self.preindent = preindent
1158
1159
1160class BlockParser:
1161 """
1162 Block-oriented parser for Argument Clinic.
1163 Iterator, yields Block objects.
1164 """
1165
1166 def __init__(self, input, language, *, verify=True):
1167 """
1168 "input" should be a str object
1169 with embedded \n characters.
1170
1171 "language" should be a Language object.
1172 """
1173 language.validate()
1174
1175 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1176 self.block_start_line_number = self.line_number = 0
1177
1178 self.language = language
1179 before, _, after = language.start_line.partition('{dsl_name}')
1180 assert _ == '{dsl_name}'
1181 self.start_re = create_regex(before, after)
1182 self.verify = verify
1183 self.last_checksum_re = None
1184 self.last_dsl_name = None
1185 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001186 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001187
1188 def __iter__(self):
1189 return self
1190
1191 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001192 while True:
1193 if not self.input:
1194 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001195
Larry Hastingsbebf7352014-01-17 17:47:17 -08001196 if self.dsl_name:
1197 return_value = self.parse_clinic_block(self.dsl_name)
1198 self.dsl_name = None
1199 self.first_block = False
1200 return return_value
1201 block = self.parse_verbatim_block()
1202 if self.first_block and not block.input:
1203 continue
1204 self.first_block = False
1205 return block
1206
Larry Hastings31826802013-10-19 00:09:25 -07001207
1208 def is_start_line(self, line):
1209 match = self.start_re.match(line.lstrip())
1210 return match.group(1) if match else None
1211
1212 def _line(self):
1213 self.line_number += 1
1214 return self.input.pop()
1215
1216 def parse_verbatim_block(self):
1217 add, output = text_accumulator()
1218 self.block_start_line_number = self.line_number
1219
1220 while self.input:
1221 line = self._line()
1222 dsl_name = self.is_start_line(line)
1223 if dsl_name:
1224 self.dsl_name = dsl_name
1225 break
1226 add(line)
1227
1228 return Block(output())
1229
1230 def parse_clinic_block(self, dsl_name):
1231 input_add, input_output = text_accumulator()
1232 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001233 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001234 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1235
Larry Hastings90261132014-01-07 12:21:08 -08001236 def is_stop_line(line):
1237 # make sure to recognize stop line even if it
1238 # doesn't end with EOL (it could be the very end of the file)
1239 if not line.startswith(stop_line):
1240 return False
1241 remainder = line[len(stop_line):]
1242 return (not remainder) or remainder.isspace()
1243
Larry Hastings31826802013-10-19 00:09:25 -07001244 # consume body of program
1245 while self.input:
1246 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001247 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001248 break
1249 if body_prefix:
1250 line = line.lstrip()
1251 assert line.startswith(body_prefix)
1252 line = line[len(body_prefix):]
1253 input_add(line)
1254
1255 # consume output and checksum line, if present.
1256 if self.last_dsl_name == dsl_name:
1257 checksum_re = self.last_checksum_re
1258 else:
1259 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, checksum='{checksum}').partition('{checksum}')
1260 assert _ == '{checksum}'
1261 checksum_re = create_regex(before, after)
1262 self.last_dsl_name = dsl_name
1263 self.last_checksum_re = checksum_re
1264
1265 # scan forward for checksum line
1266 output_add, output_output = text_accumulator()
1267 checksum = None
1268 while self.input:
1269 line = self._line()
1270 match = checksum_re.match(line.lstrip())
1271 checksum = match.group(1) if match else None
1272 if checksum:
1273 break
1274 output_add(line)
1275 if self.is_start_line(line):
1276 break
1277
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001278 output = output_output()
Larry Hastings31826802013-10-19 00:09:25 -07001279 if checksum:
Larry Hastings31826802013-10-19 00:09:25 -07001280 if self.verify:
1281 computed = compute_checksum(output)
1282 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001283 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1284 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001285 "the end marker,\n"
1286 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001287 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001288 else:
1289 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001290 output_lines = output.splitlines(keepends=True)
1291 self.line_number -= len(output_lines)
1292 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001293 output = None
1294
1295 return Block(input_output(), dsl_name, output=output)
1296
1297
1298class BlockPrinter:
1299
1300 def __init__(self, language, f=None):
1301 self.language = language
1302 self.f = f or io.StringIO()
1303
1304 def print_block(self, block):
1305 input = block.input
1306 output = block.output
1307 dsl_name = block.dsl_name
1308 write = self.f.write
1309
Larry Hastings31826802013-10-19 00:09:25 -07001310 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1311
1312 if not dsl_name:
1313 write(input)
1314 return
1315
1316 write(self.language.start_line.format(dsl_name=dsl_name))
1317 write("\n")
1318
1319 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1320 if not body_prefix:
1321 write(input)
1322 else:
1323 for line in input.split('\n'):
1324 write(body_prefix)
1325 write(line)
1326 write("\n")
1327
1328 write(self.language.stop_line.format(dsl_name=dsl_name))
1329 write("\n")
1330
Larry Hastingsbebf7352014-01-17 17:47:17 -08001331 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001332 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001333 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001334 output += '\n'
1335 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001336
1337 write(self.language.checksum_line.format(dsl_name=dsl_name, checksum=compute_checksum(output)))
1338 write("\n")
1339
Larry Hastingsbebf7352014-01-17 17:47:17 -08001340 def write(self, text):
1341 self.f.write(text)
1342
1343
1344class Destination:
1345 def __init__(self, name, type, clinic, *args):
1346 self.name = name
1347 self.type = type
1348 self.clinic = clinic
1349 valid_types = ('buffer', 'file', 'suppress', 'two-pass')
1350 if type not in valid_types:
1351 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1352 extra_arguments = 1 if type == "file" else 0
1353 if len(args) < extra_arguments:
1354 fail("Not enough arguments for destination " + name + " new " + type)
1355 if len(args) > extra_arguments:
1356 fail("Too many arguments for destination " + name + " new " + type)
1357 if type =='file':
1358 d = {}
1359 d['filename'] = filename = clinic.filename
1360 d['basename'], d['extension'] = os.path.splitext(filename)
1361 self.filename = args[0].format_map(d)
1362 if type == 'two-pass':
1363 self.id = None
1364
1365 self.text, self.append, self._dump = _text_accumulator()
1366
1367 def __repr__(self):
1368 if self.type == 'file':
1369 file_repr = " " + repr(self.filename)
1370 else:
1371 file_repr = ''
1372 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1373
1374 def clear(self):
1375 if self.type != 'buffer':
1376 fail("Can't clear destination" + self.name + " , it's not of type buffer")
1377 self.text.clear()
1378
1379 def dump(self):
1380 if self.type == 'two-pass':
1381 if self.id is None:
1382 self.id = str(uuid.uuid4())
1383 return self.id
1384 fail("You can only dump a two-pass buffer exactly once!")
1385 return self._dump()
1386
Larry Hastings31826802013-10-19 00:09:25 -07001387
1388# maps strings to Language objects.
1389# "languages" maps the name of the language ("C", "Python").
1390# "extensions" maps the file extension ("c", "py").
1391languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001392extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1393extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001394
1395
1396# maps strings to callables.
1397# these callables must be of the form:
1398# def foo(name, default, *, ...)
1399# The callable may have any number of keyword-only parameters.
1400# The callable must return a CConverter object.
1401# The callable should not call builtins.print.
1402converters = {}
1403
1404# maps strings to callables.
1405# these callables follow the same rules as those for "converters" above.
1406# note however that they will never be called with keyword-only parameters.
1407legacy_converters = {}
1408
1409
1410# maps strings to callables.
1411# these callables must be of the form:
1412# def foo(*, ...)
1413# The callable may have any number of keyword-only parameters.
1414# The callable must return a CConverter object.
1415# The callable should not call builtins.print.
1416return_converters = {}
1417
1418class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001419
1420 presets_text = """
1421preset original
1422everything block
1423docstring_prototype suppress
1424parser_prototype suppress
1425
1426preset file
1427everything file
1428docstring_prototype suppress
1429parser_prototype suppress
1430impl_definition block
1431
1432preset buffer
1433everything buffer
1434docstring_prototype suppress
1435impl_prototype suppress
1436parser_prototype suppress
1437impl_definition block
1438
1439preset partial-buffer
1440everything buffer
1441docstring_prototype block
1442impl_prototype suppress
1443methoddef_define block
1444parser_prototype block
1445impl_definition block
1446
1447preset two-pass
1448everything buffer
1449docstring_prototype two-pass
1450impl_prototype suppress
1451methoddef_define two-pass
1452parser_prototype two-pass
1453impl_definition block
1454
1455"""
1456
Larry Hastings31826802013-10-19 00:09:25 -07001457 def __init__(self, language, printer=None, *, verify=True, filename=None):
1458 # maps strings to Parser objects.
1459 # (instantiated from the "parsers" global.)
1460 self.parsers = {}
1461 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001462 if printer:
1463 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001464 self.printer = printer or BlockPrinter(language)
1465 self.verify = verify
1466 self.filename = filename
1467 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001468 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001469 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001470
Larry Hastingsbebf7352014-01-17 17:47:17 -08001471 self.line_prefix = self.line_suffix = ''
1472
1473 self.destinations = {}
1474 self.add_destination("block", "buffer")
1475 self.add_destination("suppress", "suppress")
1476 self.add_destination("buffer", "buffer")
1477 self.add_destination("two-pass", "two-pass")
1478 if filename:
1479 self.add_destination("file", "file", "{basename}.clinic{extension}")
1480
1481 d = self.destinations.get
1482 self.field_destinations = collections.OrderedDict((
1483 ('docstring_prototype', d('suppress')),
1484 ('docstring_definition', d('block')),
1485 ('methoddef_define', d('block')),
1486 ('impl_prototype', d('block')),
1487 ('parser_prototype', d('suppress')),
1488 ('parser_definition', d('block')),
1489 ('impl_definition', d('block')),
1490 ))
1491
1492 self.field_destinations_stack = []
1493
1494 self.presets = {}
1495 preset = None
1496 for line in self.presets_text.strip().split('\n'):
1497 line = line.strip()
1498 if not line:
1499 continue
1500 name, value = line.split()
1501 if name == 'preset':
1502 self.presets[value] = preset = collections.OrderedDict()
1503 continue
1504
1505 destination = self.get_destination(value)
1506
1507 if name == 'everything':
1508 for name in self.field_destinations:
1509 preset[name] = destination
1510 continue
1511
1512 assert name in self.field_destinations
1513 preset[name] = destination
1514
Larry Hastings31826802013-10-19 00:09:25 -07001515 global clinic
1516 clinic = self
1517
Larry Hastingsbebf7352014-01-17 17:47:17 -08001518 def get_destination(self, name, default=unspecified):
1519 d = self.destinations.get(name)
1520 if not d:
1521 if default is not unspecified:
1522 return default
1523 fail("Destination does not exist: " + repr(name))
1524 return d
1525
1526 def add_destination(self, name, type, *args):
1527 if name in self.destinations:
1528 fail("Destination already exists: " + repr(name))
1529 self.destinations[name] = Destination(name, type, self, *args)
1530
Larry Hastings31826802013-10-19 00:09:25 -07001531 def parse(self, input):
1532 printer = self.printer
1533 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1534 for block in self.block_parser:
1535 dsl_name = block.dsl_name
1536 if dsl_name:
1537 if dsl_name not in self.parsers:
1538 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1539 self.parsers[dsl_name] = parsers[dsl_name](self)
1540 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001541 try:
1542 parser.parse(block)
1543 except Exception:
1544 fail('Exception raised during parsing:\n' +
1545 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001546 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001547
1548 second_pass_replacements = {}
1549
1550 for name, destination in self.destinations.items():
1551 if destination.type == 'suppress':
1552 continue
1553 output = destination._dump()
1554
1555 if destination.type == 'two-pass':
1556 if destination.id:
1557 second_pass_replacements[destination.id] = output
1558 elif output:
1559 fail("Two-pass buffer " + repr(name) + " not empty at end of file!")
1560 continue
1561
1562 if output:
1563
1564 block = Block("", dsl_name="clinic", output=output)
1565
1566 if destination.type == 'buffer':
1567 block.input = "dump " + name + "\n"
1568 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1569 printer.write("\n")
1570 printer.print_block(block)
1571 continue
1572
1573 if destination.type == 'file':
1574 try:
1575 with open(destination.filename, "rt") as f:
1576 parser_2 = BlockParser(f.read(), language=self.language)
1577 blocks = list(parser_2)
1578 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1579 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
1580 except FileNotFoundError:
1581 pass
1582
1583 block.input = 'preserve\n'
1584 printer_2 = BlockPrinter(self.language)
1585 printer_2.print_block(block)
1586 with open(destination.filename, "wt") as f:
1587 f.write(printer_2.f.getvalue())
1588 continue
1589 text = printer.f.getvalue()
1590
1591 if second_pass_replacements:
1592 printer_2 = BlockPrinter(self.language)
1593 parser_2 = BlockParser(text, self.language)
1594 changed = False
1595 for block in parser_2:
1596 if block.dsl_name:
1597 for id, replacement in second_pass_replacements.items():
1598 if id in block.output:
1599 changed = True
1600 block.output = block.output.replace(id, replacement)
1601 printer_2.print_block(block)
1602 if changed:
1603 text = printer_2.f.getvalue()
1604
1605 return text
1606
Larry Hastings31826802013-10-19 00:09:25 -07001607
1608 def _module_and_class(self, fields):
1609 """
1610 fields should be an iterable of field names.
1611 returns a tuple of (module, class).
1612 the module object could actually be self (a clinic object).
1613 this function is only ever used to find the parent of where
1614 a new class/module should go.
1615 """
1616 in_classes = False
1617 parent = module = self
1618 cls = None
1619 so_far = []
1620
1621 for field in fields:
1622 so_far.append(field)
1623 if not in_classes:
1624 child = parent.modules.get(field)
1625 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001626 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001627 continue
1628 in_classes = True
1629 if not hasattr(parent, 'classes'):
1630 return module, cls
1631 child = parent.classes.get(field)
1632 if not child:
1633 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1634 cls = parent = child
1635
1636 return module, cls
1637
1638
1639def parse_file(filename, *, verify=True, output=None, encoding='utf-8'):
1640 extension = os.path.splitext(filename)[1][1:]
1641 if not extension:
1642 fail("Can't extract file type for file " + repr(filename))
1643
1644 try:
1645 language = extensions[extension]()
1646 except KeyError:
1647 fail("Can't identify file type for file " + repr(filename))
1648
1649 clinic = Clinic(language, verify=verify, filename=filename)
1650
1651 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001652 raw = f.read()
1653
1654 cooked = clinic.parse(raw)
1655 if cooked == raw:
1656 return
Larry Hastings31826802013-10-19 00:09:25 -07001657
1658 directory = os.path.dirname(filename) or '.'
1659
1660 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001661 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001662 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1663 with open(tmpfilename, "wb") as f:
1664 f.write(bytes)
1665 os.replace(tmpfilename, output or filename)
1666
1667
1668def compute_checksum(input):
1669 input = input or ''
1670 return hashlib.sha1(input.encode('utf-8')).hexdigest()
1671
1672
1673
1674
1675class PythonParser:
1676 def __init__(self, clinic):
1677 pass
1678
1679 def parse(self, block):
1680 s = io.StringIO()
1681 with OverrideStdioWith(s):
1682 exec(block.input)
1683 block.output = s.getvalue()
1684
1685
1686class Module:
1687 def __init__(self, name, module=None):
1688 self.name = name
1689 self.module = self.parent = module
1690
1691 self.modules = collections.OrderedDict()
1692 self.classes = collections.OrderedDict()
1693 self.functions = []
1694
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001695 def __repr__(self):
1696 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1697
Larry Hastings31826802013-10-19 00:09:25 -07001698class Class:
1699 def __init__(self, name, module=None, cls=None):
1700 self.name = name
1701 self.module = module
1702 self.cls = cls
1703 self.parent = cls or module
1704
1705 self.classes = collections.OrderedDict()
1706 self.functions = []
1707
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001708 def __repr__(self):
1709 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1710
Larry Hastings8666e652014-01-12 14:12:59 -08001711unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001712
Larry Hastings8666e652014-01-12 14:12:59 -08001713__abs__
1714__add__
1715__and__
1716__bytes__
1717__call__
1718__complex__
1719__delitem__
1720__divmod__
1721__eq__
1722__float__
1723__floordiv__
1724__ge__
1725__getattr__
1726__getattribute__
1727__getitem__
1728__gt__
1729__hash__
1730__iadd__
1731__iand__
1732__idivmod__
1733__ifloordiv__
1734__ilshift__
1735__imod__
1736__imul__
1737__index__
1738__int__
1739__invert__
1740__ior__
1741__ipow__
1742__irshift__
1743__isub__
1744__iter__
1745__itruediv__
1746__ixor__
1747__le__
1748__len__
1749__lshift__
1750__lt__
1751__mod__
1752__mul__
1753__neg__
1754__new__
1755__next__
1756__or__
1757__pos__
1758__pow__
1759__radd__
1760__rand__
1761__rdivmod__
1762__repr__
1763__rfloordiv__
1764__rlshift__
1765__rmod__
1766__rmul__
1767__ror__
1768__round__
1769__rpow__
1770__rrshift__
1771__rshift__
1772__rsub__
1773__rtruediv__
1774__rxor__
1775__setattr__
1776__setitem__
1777__str__
1778__sub__
1779__truediv__
1780__xor__
1781
1782""".strip().split())
1783
1784
Larry Hastings5c661892014-01-24 06:17:25 -08001785INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
1786INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
1787""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07001788
1789class Function:
1790 """
1791 Mutable duck type for inspect.Function.
1792
1793 docstring - a str containing
1794 * embedded line breaks
1795 * text outdented to the left margin
1796 * no trailing whitespace.
1797 It will always be true that
1798 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
1799 """
1800
1801 def __init__(self, parameters=None, *, name,
1802 module, cls=None, c_basename=None,
1803 full_name=None,
1804 return_converter, return_annotation=_empty,
1805 docstring=None, kind=CALLABLE, coexist=False):
1806 self.parameters = parameters or collections.OrderedDict()
1807 self.return_annotation = return_annotation
1808 self.name = name
1809 self.full_name = full_name
1810 self.module = module
1811 self.cls = cls
1812 self.parent = cls or module
1813 self.c_basename = c_basename
1814 self.return_converter = return_converter
1815 self.docstring = docstring or ''
1816 self.kind = kind
1817 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08001818 self.self_converter = None
1819
1820 @property
1821 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08001822 if self.kind in (METHOD_INIT, METHOD_NEW):
1823 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001824 flags = []
1825 if self.kind == CLASS_METHOD:
1826 flags.append('METH_CLASS')
1827 elif self.kind == STATIC_METHOD:
1828 flags.append('METH_STATIC')
1829 else:
1830 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
1831 if self.coexist:
1832 flags.append('METH_COEXIST')
1833 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07001834
1835 def __repr__(self):
1836 return '<clinic.Function ' + self.name + '>'
1837
1838
1839class Parameter:
1840 """
1841 Mutable duck type of inspect.Parameter.
1842 """
1843
1844 def __init__(self, name, kind, *, default=_empty,
1845 function, converter, annotation=_empty,
1846 docstring=None, group=0):
1847 self.name = name
1848 self.kind = kind
1849 self.default = default
1850 self.function = function
1851 self.converter = converter
1852 self.annotation = annotation
1853 self.docstring = docstring or ''
1854 self.group = group
1855
1856 def __repr__(self):
1857 return '<clinic.Parameter ' + self.name + '>'
1858
1859 def is_keyword_only(self):
1860 return self.kind == inspect.Parameter.KEYWORD_ONLY
1861
Larry Hastings31826802013-10-19 00:09:25 -07001862
Larry Hastings31826802013-10-19 00:09:25 -07001863
1864def add_c_converter(f, name=None):
1865 if not name:
1866 name = f.__name__
1867 if not name.endswith('_converter'):
1868 return f
1869 name = name[:-len('_converter')]
1870 converters[name] = f
1871 return f
1872
1873def add_default_legacy_c_converter(cls):
1874 # automatically add converter for default format unit
1875 # (but without stomping on the existing one if it's already
1876 # set, in case you subclass)
1877 if ((cls.format_unit != 'O&') and
1878 (cls.format_unit not in legacy_converters)):
1879 legacy_converters[cls.format_unit] = cls
1880 return cls
1881
1882def add_legacy_c_converter(format_unit, **kwargs):
1883 """
1884 Adds a legacy converter.
1885 """
1886 def closure(f):
1887 if not kwargs:
1888 added_f = f
1889 else:
1890 added_f = functools.partial(f, **kwargs)
1891 legacy_converters[format_unit] = added_f
1892 return f
1893 return closure
1894
1895class CConverterAutoRegister(type):
1896 def __init__(cls, name, bases, classdict):
1897 add_c_converter(cls)
1898 add_default_legacy_c_converter(cls)
1899
1900class CConverter(metaclass=CConverterAutoRegister):
1901 """
1902 For the init function, self, name, function, and default
1903 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08001904 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07001905 """
1906
Larry Hastings78cf85c2014-01-04 12:44:57 -08001907 # The C type to use for this variable.
1908 # 'type' should be a Python string specifying the type, e.g. "int".
1909 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07001910 type = None
Larry Hastings31826802013-10-19 00:09:25 -07001911
1912 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08001913 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08001914 # Or the magic value "unknown" if this value is a cannot be evaluated
1915 # at Argument-Clinic-preprocessing time (but is presumed to be valid
1916 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07001917 default = unspecified
1918
Larry Hastings4a55fc52014-01-12 11:09:57 -08001919 # If not None, default must be isinstance() of this type.
1920 # (You can also specify a tuple of types.)
1921 default_type = None
1922
Larry Hastings31826802013-10-19 00:09:25 -07001923 # "default" converted into a C value, as a string.
1924 # Or None if there is no default.
1925 c_default = None
1926
Larry Hastings2a727912014-01-16 11:32:01 -08001927 # "default" converted into a Python value, as a string.
1928 # Or None if there is no default.
1929 py_default = None
1930
Larry Hastingsabc716b2013-11-20 09:13:52 -08001931 # The default value used to initialize the C variable when
1932 # there is no default, but not specifying a default may
1933 # result in an "uninitialized variable" warning. This can
1934 # easily happen when using option groups--although
1935 # properly-written code won't actually use the variable,
1936 # the variable does get passed in to the _impl. (Ah, if
1937 # only dataflow analysis could inline the static function!)
1938 #
1939 # This value is specified as a string.
1940 # Every non-abstract subclass should supply a valid value.
1941 c_ignored_default = 'NULL'
1942
Larry Hastings31826802013-10-19 00:09:25 -07001943 # The C converter *function* to be used, if any.
1944 # (If this is not None, format_unit must be 'O&'.)
1945 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001946
Larry Hastings78cf85c2014-01-04 12:44:57 -08001947 # Should Argument Clinic add a '&' before the name of
1948 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07001949 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08001950
1951 # Should Argument Clinic add a '&' before the name of
1952 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07001953 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08001954
1955 #############################################################
1956 #############################################################
1957 ## You shouldn't need to read anything below this point to ##
1958 ## write your own converter functions. ##
1959 #############################################################
1960 #############################################################
1961
1962 # The "format unit" to specify for this variable when
1963 # parsing arguments using PyArg_ParseTuple (AndKeywords).
1964 # Custom converters should always use the default value of 'O&'.
1965 format_unit = 'O&'
1966
1967 # What encoding do we want for this variable? Only used
1968 # by format units starting with 'e'.
1969 encoding = None
1970
Larry Hastings77561cc2014-01-07 12:13:13 -08001971 # Should this object be required to be a subclass of a specific type?
1972 # If not None, should be a string representing a pointer to a
1973 # PyTypeObject (e.g. "&PyUnicode_Type").
1974 # Only used by the 'O!' format unit (and the "object" converter).
1975 subclass_of = None
1976
Larry Hastings78cf85c2014-01-04 12:44:57 -08001977 # Do we want an adjacent '_length' variable for this variable?
1978 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07001979 length = False
1980
Larry Hastings5c661892014-01-24 06:17:25 -08001981 # Should we show this parameter in the generated
1982 # __text_signature__? This is *almost* always True.
1983 show_in_signature = True
1984
1985 # Overrides the name used in a text signature.
1986 # The name used for a "self" parameter must be one of
1987 # self, type, or module; however users can set their own.
1988 # This lets the self_converter overrule the user-settable
1989 # name, *just* for the text signature.
1990 # Only set by self_converter.
1991 signature_name = None
1992
1993 # keep in sync with self_converter.__init__!
Larry Hastings2a727912014-01-16 11:32:01 -08001994 def __init__(self, name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs):
Larry Hastings31826802013-10-19 00:09:25 -07001995 self.function = function
1996 self.name = name
1997
1998 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08001999 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002000 if isinstance(self.default_type, type):
2001 types_str = self.default_type.__name__
2002 else:
2003 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2004 fail("{}: default value {!r} for field {} is not of type {}".format(
2005 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002006 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002007
Larry Hastingsb4705752014-01-18 21:54:15 -08002008 if c_default:
2009 self.c_default = c_default
2010 if py_default:
2011 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002012
Larry Hastings31826802013-10-19 00:09:25 -07002013 if annotation != unspecified:
2014 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings31826802013-10-19 00:09:25 -07002015 self.converter_init(**kwargs)
2016
2017 def converter_init(self):
2018 pass
2019
2020 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002021 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002022
Larry Hastings5c661892014-01-24 06:17:25 -08002023 def _render_self(self, parameter, data):
2024 self.parameter = parameter
2025 original_name = self.name
2026 name = ensure_legal_c_identifier(original_name)
2027
2028 # impl_arguments
2029 s = ("&" if self.impl_by_reference else "") + name
2030 data.impl_arguments.append(s)
2031 if self.length:
2032 data.impl_arguments.append(self.length_name())
2033
2034 # impl_parameters
2035 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2036 if self.length:
2037 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2038
2039 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002040 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002041 original_name = self.name
2042 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002043
2044 # declarations
2045 d = self.declaration()
2046 data.declarations.append(d)
2047
2048 # initializers
2049 initializers = self.initialize()
2050 if initializers:
2051 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2052
Larry Hastings31826802013-10-19 00:09:25 -07002053 # keywords
Larry Hastings90261132014-01-07 12:21:08 -08002054 data.keywords.append(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002055
2056 # format_units
2057 if self.is_optional() and '|' not in data.format_units:
2058 data.format_units.append('|')
2059 if parameter.is_keyword_only() and '$' not in data.format_units:
2060 data.format_units.append('$')
2061 data.format_units.append(self.format_unit)
2062
2063 # parse_arguments
2064 self.parse_argument(data.parse_arguments)
2065
Larry Hastings31826802013-10-19 00:09:25 -07002066 # cleanup
2067 cleanup = self.cleanup()
2068 if cleanup:
2069 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2070
Larry Hastings5c661892014-01-24 06:17:25 -08002071 def render(self, parameter, data):
2072 """
2073 parameter is a clinic.Parameter instance.
2074 data is a CRenderData instance.
2075 """
2076 self._render_self(parameter, data)
2077 self._render_non_self(parameter, data)
2078
Larry Hastingsebdcb502013-11-23 14:54:00 -08002079 def length_name(self):
2080 """Computes the name of the associated "length" variable."""
2081 if not self.length:
2082 return None
2083 return ensure_legal_c_identifier(self.name) + "_length"
2084
Larry Hastings31826802013-10-19 00:09:25 -07002085 # Why is this one broken out separately?
2086 # For "positional-only" function parsing,
2087 # which generates a bunch of PyArg_ParseTuple calls.
2088 def parse_argument(self, list):
2089 assert not (self.converter and self.encoding)
2090 if self.format_unit == 'O&':
2091 assert self.converter
2092 list.append(self.converter)
2093
2094 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002095 list.append(c_repr(self.encoding))
2096 elif self.subclass_of:
2097 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002098
Larry Hastingsebdcb502013-11-23 14:54:00 -08002099 legal_name = ensure_legal_c_identifier(self.name)
2100 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002101 list.append(s)
2102
Larry Hastingsebdcb502013-11-23 14:54:00 -08002103 if self.length:
2104 list.append("&" + self.length_name())
2105
Larry Hastings31826802013-10-19 00:09:25 -07002106 #
2107 # All the functions after here are intended as extension points.
2108 #
2109
2110 def simple_declaration(self, by_reference=False):
2111 """
2112 Computes the basic declaration of the variable.
2113 Used in computing the prototype declaration and the
2114 variable declaration.
2115 """
2116 prototype = [self.type]
2117 if by_reference or not self.type.endswith('*'):
2118 prototype.append(" ")
2119 if by_reference:
2120 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002121 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002122 return "".join(prototype)
2123
2124 def declaration(self):
2125 """
2126 The C statement to declare this variable.
2127 """
2128 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002129 default = self.c_default
2130 if not default and self.parameter.group:
2131 default = self.c_ignored_default
2132 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002133 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002134 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002135 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002136 if self.length:
2137 declaration.append('\nPy_ssize_clean_t ')
2138 declaration.append(self.length_name())
2139 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002140 s = "".join(declaration)
2141 # double up curly-braces, this string will be used
2142 # as part of a format_map() template later
2143 s = s.replace("{", "{{")
2144 s = s.replace("}", "}}")
2145 return s
Larry Hastings31826802013-10-19 00:09:25 -07002146
2147 def initialize(self):
2148 """
2149 The C statements required to set up this variable before parsing.
2150 Returns a string containing this code indented at column 0.
2151 If no initialization is necessary, returns an empty string.
2152 """
2153 return ""
2154
2155 def cleanup(self):
2156 """
2157 The C statements required to clean up after this variable.
2158 Returns a string containing this code indented at column 0.
2159 If no cleanup is necessary, returns an empty string.
2160 """
2161 return ""
2162
2163
2164class bool_converter(CConverter):
2165 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002166 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002167 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002168 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002169
2170 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002171 if self.default is not unspecified:
2172 self.default = bool(self.default)
2173 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002174
2175class char_converter(CConverter):
2176 type = 'char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002177 default_type = str
Larry Hastings31826802013-10-19 00:09:25 -07002178 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002179 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002180
Larry Hastings4a55fc52014-01-12 11:09:57 -08002181 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002182 if isinstance(self.default, str) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002183 fail("char_converter: illegal default value " + repr(self.default))
2184
2185
Larry Hastings31826802013-10-19 00:09:25 -07002186@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002187class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002188 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002189 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002190 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002191 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002192
2193 def converter_init(self, *, bitwise=False):
2194 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002195 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002196
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002197class byte_converter(unsigned_char_converter): pass
2198
Larry Hastings31826802013-10-19 00:09:25 -07002199class short_converter(CConverter):
2200 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002201 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002202 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002203 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002204
2205class unsigned_short_converter(CConverter):
2206 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002207 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002208 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002209 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002210
2211 def converter_init(self, *, bitwise=False):
2212 if not bitwise:
2213 fail("Unsigned shorts must be bitwise (for now).")
2214
Larry Hastingsebdcb502013-11-23 14:54:00 -08002215@add_legacy_c_converter('C', types='str')
Larry Hastings31826802013-10-19 00:09:25 -07002216class int_converter(CConverter):
2217 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002218 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002219 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002220 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002221
Larry Hastingsebdcb502013-11-23 14:54:00 -08002222 def converter_init(self, *, types='int'):
2223 if types == 'str':
2224 self.format_unit = 'C'
2225 elif types != 'int':
2226 fail("int_converter: illegal 'types' argument")
Larry Hastings31826802013-10-19 00:09:25 -07002227
2228class unsigned_int_converter(CConverter):
2229 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002230 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002231 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002232 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002233
2234 def converter_init(self, *, bitwise=False):
2235 if not bitwise:
2236 fail("Unsigned ints must be bitwise (for now).")
2237
2238class long_converter(CConverter):
2239 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002240 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002241 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002242 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002243
2244class unsigned_long_converter(CConverter):
2245 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002246 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002247 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002248 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002249
2250 def converter_init(self, *, bitwise=False):
2251 if not bitwise:
2252 fail("Unsigned longs must be bitwise (for now).")
2253
2254class PY_LONG_LONG_converter(CConverter):
2255 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002256 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002257 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002258 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002259
2260class unsigned_PY_LONG_LONG_converter(CConverter):
2261 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002262 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002263 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002264 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002265
2266 def converter_init(self, *, bitwise=False):
2267 if not bitwise:
2268 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2269
2270class Py_ssize_t_converter(CConverter):
2271 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002272 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002273 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002274 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002275
2276
2277class float_converter(CConverter):
2278 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002279 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002280 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002281 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002282
2283class double_converter(CConverter):
2284 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002285 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002286 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002287 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002288
2289
2290class Py_complex_converter(CConverter):
2291 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002292 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002293 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002294 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002295
2296
2297class object_converter(CConverter):
2298 type = 'PyObject *'
2299 format_unit = 'O'
2300
Larry Hastings4a55fc52014-01-12 11:09:57 -08002301 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2302 if converter:
2303 if subclass_of:
2304 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2305 self.format_unit = 'O&'
2306 self.converter = converter
2307 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002308 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002309 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002310
Larry Hastings77561cc2014-01-07 12:13:13 -08002311 if type is not None:
2312 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002313
2314
Larry Hastingsebdcb502013-11-23 14:54:00 -08002315@add_legacy_c_converter('s#', length=True)
Larry Hastings2a727912014-01-16 11:32:01 -08002316@add_legacy_c_converter('y', types="bytes")
2317@add_legacy_c_converter('y#', types="bytes", length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002318@add_legacy_c_converter('z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002319@add_legacy_c_converter('z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002320class str_converter(CConverter):
2321 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002322 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002323 format_unit = 's'
2324
Larry Hastingsebdcb502013-11-23 14:54:00 -08002325 def converter_init(self, *, encoding=None, types="str",
2326 length=False, nullable=False, zeroes=False):
2327
2328 types = set(types.strip().split())
2329 bytes_type = set(("bytes",))
2330 str_type = set(("str",))
2331 all_3_type = set(("bytearray",)) | bytes_type | str_type
2332 is_bytes = types == bytes_type
2333 is_str = types == str_type
2334 is_all_3 = types == all_3_type
2335
2336 self.length = bool(length)
2337 format_unit = None
2338
2339 if encoding:
2340 self.encoding = encoding
2341
2342 if is_str and not (length or zeroes or nullable):
2343 format_unit = 'es'
2344 elif is_all_3 and not (length or zeroes or nullable):
2345 format_unit = 'et'
2346 elif is_str and length and zeroes and not nullable:
2347 format_unit = 'es#'
2348 elif is_all_3 and length and not (nullable or zeroes):
2349 format_unit = 'et#'
2350
2351 if format_unit.endswith('#'):
Larry Hastings5c661892014-01-24 06:17:25 -08002352 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 -08002353 # TODO set pointer to NULL
2354 # TODO add cleanup for buffer
2355 pass
2356
2357 else:
2358 if zeroes:
2359 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
2360
2361 if is_bytes and not (nullable or length):
2362 format_unit = 'y'
2363 elif is_bytes and length and not nullable:
2364 format_unit = 'y#'
2365 elif is_str and not (nullable or length):
2366 format_unit = 's'
2367 elif is_str and length and not nullable:
2368 format_unit = 's#'
2369 elif is_str and nullable and not length:
2370 format_unit = 'z'
2371 elif is_str and nullable and length:
2372 format_unit = 'z#'
2373
2374 if not format_unit:
2375 fail("str_converter: illegal combination of arguments")
2376 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002377
2378
2379class PyBytesObject_converter(CConverter):
2380 type = 'PyBytesObject *'
2381 format_unit = 'S'
2382
2383class PyByteArrayObject_converter(CConverter):
2384 type = 'PyByteArrayObject *'
2385 format_unit = 'Y'
2386
2387class unicode_converter(CConverter):
2388 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002389 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002390 format_unit = 'U'
2391
Larry Hastingsebdcb502013-11-23 14:54:00 -08002392@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002393@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002394@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002395class Py_UNICODE_converter(CConverter):
2396 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002397 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002398 format_unit = 'u'
2399
Larry Hastingsebdcb502013-11-23 14:54:00 -08002400 def converter_init(self, *, nullable=False, length=False):
2401 format_unit = 'Z' if nullable else 'u'
2402 if length:
2403 format_unit += '#'
2404 self.length = True
2405 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002406
Larry Hastingsebdcb502013-11-23 14:54:00 -08002407#
2408# We define three string conventions for buffer types in the 'types' argument:
2409# 'buffer' : any object supporting the buffer interface
2410# 'rwbuffer': any object supporting the buffer interface, but must be writeable
2411# 'robuffer': any object supporting the buffer interface, but must not be writeable
2412#
2413@add_legacy_c_converter('s*', types='str bytes bytearray buffer')
2414@add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True)
2415@add_legacy_c_converter('w*', types='bytearray rwbuffer')
Larry Hastings31826802013-10-19 00:09:25 -07002416class Py_buffer_converter(CConverter):
2417 type = 'Py_buffer'
2418 format_unit = 'y*'
2419 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002420 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002421
Larry Hastingsebdcb502013-11-23 14:54:00 -08002422 def converter_init(self, *, types='bytes bytearray buffer', nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002423 if self.default not in (unspecified, None):
2424 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08002425 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002426 types = set(types.strip().split())
2427 bytes_type = set(('bytes',))
2428 bytearray_type = set(('bytearray',))
2429 buffer_type = set(('buffer',))
2430 rwbuffer_type = set(('rwbuffer',))
2431 robuffer_type = set(('robuffer',))
2432 str_type = set(('str',))
2433 bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type
2434
2435 format_unit = None
2436 if types == (str_type | bytes_bytearray_buffer_type):
2437 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07002438 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002439 if nullable:
2440 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
2441 elif types == (bytes_bytearray_buffer_type):
2442 format_unit = 'y*'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002443 elif types == (bytearray_type | rwbuffer_type):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002444 format_unit = 'w*'
2445 if not format_unit:
2446 fail("Py_buffer_converter: illegal combination of arguments")
2447
2448 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002449
2450 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002451 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002452 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002453
2454
Larry Hastings5c661892014-01-24 06:17:25 -08002455def correct_name_for_self(f):
2456 if f.kind in (CALLABLE, METHOD_INIT):
2457 if f.cls:
2458 return "PyObject *", "self"
2459 return "PyModuleDef *", "module"
2460 if f.kind == STATIC_METHOD:
2461 return "void *", "null"
2462 if f.kind in (CLASS_METHOD, METHOD_NEW):
2463 return "PyTypeObject *", "type"
2464 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2465
2466
Larry Hastingsebdcb502013-11-23 14:54:00 -08002467class self_converter(CConverter):
2468 """
2469 A special-case converter:
2470 this is the default converter used for "self".
2471 """
Larry Hastings5c661892014-01-24 06:17:25 -08002472 type = None
2473 format_unit = ''
2474
2475
Larry Hastings78cf85c2014-01-04 12:44:57 -08002476 def converter_init(self, *, type=None):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002477 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002478 default_type, default_name = correct_name_for_self(f)
2479 self.signature_name = default_name
2480 self.type = type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002481
Larry Hastings5c661892014-01-24 06:17:25 -08002482 kind = self.function.kind
2483 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2484
2485 if (kind == STATIC_METHOD) or new_or_init:
2486 self.show_in_signature = False
2487
2488 # tp_new (METHOD_NEW) functions are of type newfunc:
2489 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2490 # PyTypeObject is a typedef for struct _typeobject.
2491 #
2492 # tp_init (METHOD_INIT) functions are of type initproc:
2493 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2494 #
2495 # All other functions generated by Argument Clinic are stored in
2496 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2497 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2498 # However! We habitually cast these functions to PyCFunction,
2499 # since functions that accept keyword arguments don't fit this signature
2500 # but are stored there anyway. So strict type equality isn't important
2501 # for these functions.
2502 #
2503 # So:
2504 #
2505 # * The name of the first parameter to the impl and the parsing function will always
2506 # be self.name.
2507 #
2508 # * The type of the first parameter to the impl will always be of self.type.
2509 #
2510 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2511 # * The type of the first parameter to the parsing function is also self.type.
2512 # This means that if you step into the parsing function, your "self" parameter
2513 # is of the correct type, which may make debugging more pleasant.
2514 #
2515 # * Else if the function is tp_new (METHOD_NEW):
2516 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2517 # so the type signature of the function call is an exact match.
2518 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2519 # in the impl call.
2520 #
2521 # * Else if the function is tp_init (METHOD_INIT):
2522 # * The type of the first parameter to the parsing function is "PyObject *",
2523 # so the type signature of the function call is an exact match.
2524 # * If self.type != "PyObject *", we cast the first parameter to self.type
2525 # in the impl call.
2526
2527 @property
2528 def parser_type(self):
2529 kind = self.function.kind
2530 if kind == METHOD_NEW:
2531 return "PyTypeObject *"
2532 if kind == METHOD_INIT:
2533 return "PyObject *"
2534 return self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002535
Larry Hastingsebdcb502013-11-23 14:54:00 -08002536 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002537 """
2538 parameter is a clinic.Parameter instance.
2539 data is a CRenderData instance.
2540 """
2541 if self.function.kind == STATIC_METHOD:
2542 return
2543
2544 self._render_self(parameter, data)
2545
2546 if self.type != self.parser_type:
2547 # insert cast to impl_argument[0], aka self.
2548 # we know we're in the first slot in all the CRenderData lists,
2549 # because we render parameters in order, and self is always first.
2550 assert len(data.impl_arguments) == 1
2551 assert data.impl_arguments[0] == self.name
2552 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2553
2554 def set_template_dict(self, template_dict):
2555 template_dict['self_name'] = self.name
2556 template_dict['self_type'] = self.parser_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002557
Larry Hastings31826802013-10-19 00:09:25 -07002558
2559
2560def add_c_return_converter(f, name=None):
2561 if not name:
2562 name = f.__name__
2563 if not name.endswith('_return_converter'):
2564 return f
2565 name = name[:-len('_return_converter')]
2566 return_converters[name] = f
2567 return f
2568
2569
2570class CReturnConverterAutoRegister(type):
2571 def __init__(cls, name, bases, classdict):
2572 add_c_return_converter(cls)
2573
2574class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2575
Larry Hastings78cf85c2014-01-04 12:44:57 -08002576 # The C type to use for this variable.
2577 # 'type' should be a Python string specifying the type, e.g. "int".
2578 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002579 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002580
2581 # The Python default value for this parameter, as a Python value.
2582 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002583 default = None
2584
Larry Hastings2a727912014-01-16 11:32:01 -08002585 def __init__(self, *, py_default=None, **kwargs):
2586 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002587 try:
2588 self.return_converter_init(**kwargs)
2589 except TypeError as e:
2590 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2591 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2592
2593 def return_converter_init(self):
2594 pass
2595
2596 def declare(self, data, name="_return_value"):
2597 line = []
2598 add = line.append
2599 add(self.type)
2600 if not self.type.endswith('*'):
2601 add(' ')
2602 add(name + ';')
2603 data.declarations.append(''.join(line))
2604 data.return_value = name
2605
2606 def err_occurred_if(self, expr, data):
2607 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2608
2609 def err_occurred_if_null_pointer(self, variable, data):
2610 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2611
2612 def render(self, function, data):
2613 """
2614 function is a clinic.Function instance.
2615 data is a CRenderData instance.
2616 """
2617 pass
2618
2619add_c_return_converter(CReturnConverter, 'object')
2620
Larry Hastings78cf85c2014-01-04 12:44:57 -08002621class NoneType_return_converter(CReturnConverter):
2622 def render(self, function, data):
2623 self.declare(data)
2624 data.return_conversion.append('''
2625if (_return_value != Py_None)
2626 goto exit;
2627return_value = Py_None;
2628Py_INCREF(Py_None);
2629'''.strip())
2630
Larry Hastings4a55fc52014-01-12 11:09:57 -08002631class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002632 type = 'int'
2633
2634 def render(self, function, data):
2635 self.declare(data)
2636 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002637 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002638
2639class long_return_converter(CReturnConverter):
2640 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002641 conversion_fn = 'PyLong_FromLong'
2642 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002643
2644 def render(self, function, data):
2645 self.declare(data)
2646 self.err_occurred_if("_return_value == -1", data)
2647 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002648 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002649
Larry Hastings4a55fc52014-01-12 11:09:57 -08002650class int_return_converter(long_return_converter):
2651 type = 'int'
2652 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002653
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002654class init_return_converter(long_return_converter):
2655 """
2656 Special return converter for __init__ functions.
2657 """
2658 type = 'int'
2659 cast = '(long)'
2660
2661 def render(self, function, data):
2662 pass
2663
Larry Hastings4a55fc52014-01-12 11:09:57 -08002664class unsigned_long_return_converter(long_return_converter):
2665 type = 'unsigned long'
2666 conversion_fn = 'PyLong_FromUnsignedLong'
2667
2668class unsigned_int_return_converter(unsigned_long_return_converter):
2669 type = 'unsigned int'
2670 cast = '(unsigned long)'
2671
2672class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07002673 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002674 conversion_fn = 'PyLong_FromSsize_t'
2675
2676class size_t_return_converter(long_return_converter):
2677 type = 'size_t'
2678 conversion_fn = 'PyLong_FromSize_t'
2679
2680
2681class double_return_converter(CReturnConverter):
2682 type = 'double'
2683 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002684
2685 def render(self, function, data):
2686 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002687 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07002688 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002689 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
2690
2691class float_return_converter(double_return_converter):
2692 type = 'float'
2693 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07002694
2695
2696class DecodeFSDefault_return_converter(CReturnConverter):
2697 type = 'char *'
2698
2699 def render(self, function, data):
2700 self.declare(data)
2701 self.err_occurred_if_null_pointer("_return_value", data)
2702 data.return_conversion.append(
2703 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
2704
2705
2706class IndentStack:
2707 def __init__(self):
2708 self.indents = []
2709 self.margin = None
2710
2711 def _ensure(self):
2712 if not self.indents:
2713 fail('IndentStack expected indents, but none are defined.')
2714
2715 def measure(self, line):
2716 """
2717 Returns the length of the line's margin.
2718 """
2719 if '\t' in line:
2720 fail('Tab characters are illegal in the Clinic DSL.')
2721 stripped = line.lstrip()
2722 if not len(stripped):
2723 # we can't tell anything from an empty line
2724 # so just pretend it's indented like our current indent
2725 self._ensure()
2726 return self.indents[-1]
2727 return len(line) - len(stripped)
2728
2729 def infer(self, line):
2730 """
2731 Infer what is now the current margin based on this line.
2732 Returns:
2733 1 if we have indented (or this is the first margin)
2734 0 if the margin has not changed
2735 -N if we have dedented N times
2736 """
2737 indent = self.measure(line)
2738 margin = ' ' * indent
2739 if not self.indents:
2740 self.indents.append(indent)
2741 self.margin = margin
2742 return 1
2743 current = self.indents[-1]
2744 if indent == current:
2745 return 0
2746 if indent > current:
2747 self.indents.append(indent)
2748 self.margin = margin
2749 return 1
2750 # indent < current
2751 if indent not in self.indents:
2752 fail("Illegal outdent.")
2753 outdent_count = 0
2754 while indent != current:
2755 self.indents.pop()
2756 current = self.indents[-1]
2757 outdent_count -= 1
2758 self.margin = margin
2759 return outdent_count
2760
2761 @property
2762 def depth(self):
2763 """
2764 Returns how many margins are currently defined.
2765 """
2766 return len(self.indents)
2767
2768 def indent(self, line):
2769 """
2770 Indents a line by the currently defined margin.
2771 """
2772 return self.margin + line
2773
2774 def dedent(self, line):
2775 """
2776 Dedents a line by the currently defined margin.
2777 (The inverse of 'indent'.)
2778 """
2779 margin = self.margin
2780 indent = self.indents[-1]
2781 if not line.startswith(margin):
2782 fail('Cannot dedent, line does not start with the previous margin:')
2783 return line[indent:]
2784
2785
2786class DSLParser:
2787 def __init__(self, clinic):
2788 self.clinic = clinic
2789
2790 self.directives = {}
2791 for name in dir(self):
2792 # functions that start with directive_ are added to directives
2793 _, s, key = name.partition("directive_")
2794 if s:
2795 self.directives[key] = getattr(self, name)
2796
2797 # functions that start with at_ are too, with an @ in front
2798 _, s, key = name.partition("at_")
2799 if s:
2800 self.directives['@' + key] = getattr(self, name)
2801
2802 self.reset()
2803
2804 def reset(self):
2805 self.function = None
2806 self.state = self.state_dsl_start
2807 self.parameter_indent = None
2808 self.keyword_only = False
2809 self.group = 0
2810 self.parameter_state = self.ps_start
2811 self.indent = IndentStack()
2812 self.kind = CALLABLE
2813 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08002814 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08002815 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07002816
Larry Hastingsebdcb502013-11-23 14:54:00 -08002817 def directive_version(self, required):
2818 global version
2819 if version_comparitor(version, required) < 0:
2820 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
2821
Larry Hastings31826802013-10-19 00:09:25 -07002822 def directive_module(self, name):
2823 fields = name.split('.')
2824 new = fields.pop()
2825 module, cls = self.clinic._module_and_class(fields)
2826 if cls:
2827 fail("Can't nest a module inside a class!")
2828 m = Module(name, module)
2829 module.modules[name] = m
2830 self.block.signatures.append(m)
2831
2832 def directive_class(self, name):
2833 fields = name.split('.')
2834 in_classes = False
2835 parent = self
2836 name = fields.pop()
2837 so_far = []
2838 module, cls = self.clinic._module_and_class(fields)
2839
Larry Hastings31826802013-10-19 00:09:25 -07002840 c = Class(name, module, cls)
Larry Hastings31826802013-10-19 00:09:25 -07002841 if cls:
2842 cls.classes[name] = c
Larry Hastingsed4a1c52013-11-18 09:32:13 -08002843 else:
2844 module.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07002845 self.block.signatures.append(c)
2846
Larry Hastingsbebf7352014-01-17 17:47:17 -08002847 def directive_set(self, name, value):
2848 if name not in ("line_prefix", "line_suffix"):
2849 fail("unknown variable", repr(name))
2850
2851 value = value.format_map({
2852 'block comment start': '/*',
2853 'block comment end': '*/',
2854 })
2855
2856 self.clinic.__dict__[name] = value
2857
2858 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06002859 if command == 'new':
2860 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08002861 return
2862
Zachary Ware071baa62014-01-21 23:07:12 -06002863 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08002864 self.clinic.get_destination(name).clear()
2865 fail("unknown destination command", repr(command))
2866
2867
2868 def directive_output(self, field, destination=''):
2869 fd = self.clinic.field_destinations
2870
2871 if field == "preset":
2872 preset = self.clinic.presets.get(destination)
2873 if not preset:
2874 fail("Unknown preset " + repr(destination) + "!")
2875 fd.update(preset)
2876 return
2877
2878 if field == "push":
2879 self.clinic.field_destinations_stack.append(fd.copy())
2880 return
2881
2882 if field == "pop":
2883 if not self.clinic.field_destinations_stack:
2884 fail("Can't 'output pop', stack is empty!")
2885 previous_fd = self.clinic.field_destinations_stack.pop()
2886 fd.update(previous_fd)
2887 return
2888
2889 # secret command for debugging!
2890 if field == "print":
2891 self.block.output.append(pprint.pformat(fd))
2892 self.block.output.append('\n')
2893 return
2894
2895 d = self.clinic.get_destination(destination)
2896
2897 if field == "everything":
2898 for name in list(fd):
2899 fd[name] = d
2900 return
2901
2902 if field not in fd:
2903 fail("Invalid field " + repr(field) + ", must be one of:\n " + ", ".join(valid_fields))
2904 fd[field] = d
2905
2906 def directive_dump(self, name):
2907 self.block.output.append(self.clinic.get_destination(name).dump())
2908
2909 def directive_print(self, *args):
2910 self.block.output.append(' '.join(args))
2911 self.block.output.append('\n')
2912
2913 def directive_preserve(self):
2914 if self.preserve_output:
2915 fail("Can't have preserve twice in one block!")
2916 self.preserve_output = True
2917
Larry Hastings31826802013-10-19 00:09:25 -07002918 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002919 if self.kind is not CALLABLE:
2920 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07002921 self.kind = CLASS_METHOD
2922
2923 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002924 if self.kind is not CALLABLE:
2925 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07002926 self.kind = STATIC_METHOD
2927
2928 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002929 if self.coexist:
2930 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07002931 self.coexist = True
2932
2933 def parse(self, block):
2934 self.reset()
2935 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08002936 self.saved_output = self.block.output
2937 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07002938 block_start = self.clinic.block_parser.line_number
2939 lines = block.input.split('\n')
2940 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
2941 if '\t' in line:
2942 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
2943 self.state(line)
2944
2945 self.next(self.state_terminal)
2946 self.state(None)
2947
Larry Hastingsbebf7352014-01-17 17:47:17 -08002948 block.output.extend(self.clinic.language.render(clinic, block.signatures))
2949
2950 if self.preserve_output:
2951 if block.output:
2952 fail("'preserve' only works for blocks that don't produce any output!")
2953 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07002954
2955 @staticmethod
2956 def ignore_line(line):
2957 # ignore comment-only lines
2958 if line.lstrip().startswith('#'):
2959 return True
2960
2961 # Ignore empty lines too
2962 # (but not in docstring sections!)
2963 if not line.strip():
2964 return True
2965
2966 return False
2967
2968 @staticmethod
2969 def calculate_indent(line):
2970 return len(line) - len(line.strip())
2971
2972 def next(self, state, line=None):
2973 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
2974 self.state = state
2975 if line is not None:
2976 self.state(line)
2977
2978 def state_dsl_start(self, line):
2979 # self.block = self.ClinicOutputBlock(self)
2980 if self.ignore_line(line):
2981 return
2982 self.next(self.state_modulename_name, line)
2983
2984 def state_modulename_name(self, line):
2985 # looking for declaration, which establishes the leftmost column
2986 # line should be
2987 # modulename.fnname [as c_basename] [-> return annotation]
2988 # square brackets denote optional syntax.
2989 #
Larry Hastings4a714d42014-01-14 22:22:41 -08002990 # alternatively:
2991 # modulename.fnname [as c_basename] = modulename.existing_fn_name
2992 # clones the parameters and return converter from that
2993 # function. you can't modify them. you must enter a
2994 # new docstring.
2995 #
Larry Hastings31826802013-10-19 00:09:25 -07002996 # (but we might find a directive first!)
2997 #
2998 # this line is permitted to start with whitespace.
2999 # we'll call this number of spaces F (for "function").
3000
3001 if not line.strip():
3002 return
3003
3004 self.indent.infer(line)
3005
3006 # is it a directive?
3007 fields = shlex.split(line)
3008 directive_name = fields[0]
3009 directive = self.directives.get(directive_name, None)
3010 if directive:
Larry Hastingsbebf7352014-01-17 17:47:17 -08003011 try:
3012 directive(*fields[1:])
3013 except TypeError as e:
3014 fail(str(e))
Larry Hastings31826802013-10-19 00:09:25 -07003015 return
3016
Larry Hastings4a714d42014-01-14 22:22:41 -08003017 # are we cloning?
3018 before, equals, existing = line.rpartition('=')
3019 if equals:
3020 full_name, _, c_basename = before.partition(' as ')
3021 full_name = full_name.strip()
3022 c_basename = c_basename.strip()
3023 existing = existing.strip()
3024 if (is_legal_py_identifier(full_name) and
3025 (not c_basename or is_legal_c_identifier(c_basename)) and
3026 is_legal_py_identifier(existing)):
3027 # we're cloning!
3028 fields = [x.strip() for x in existing.split('.')]
3029 function_name = fields.pop()
3030 module, cls = self.clinic._module_and_class(fields)
3031
3032 for existing_function in (cls or module).functions:
3033 if existing_function.name == function_name:
3034 break
3035 else:
3036 existing_function = None
3037 if not existing_function:
3038 fail("Couldn't find existing function " + repr(existing) + "!")
3039
3040 fields = [x.strip() for x in full_name.split('.')]
3041 function_name = fields.pop()
3042 module, cls = self.clinic._module_and_class(fields)
3043
3044 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3045 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
3046 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3047 return_converter=existing_function.return_converter, kind=existing_function.kind, coexist=existing_function.coexist)
3048
3049 self.function.parameters = existing_function.parameters.copy()
3050
3051 self.block.signatures.append(self.function)
3052 (cls or module).functions.append(self.function)
3053 self.next(self.state_function_docstring)
3054 return
3055
Larry Hastings31826802013-10-19 00:09:25 -07003056 line, _, returns = line.partition('->')
3057
3058 full_name, _, c_basename = line.partition(' as ')
3059 full_name = full_name.strip()
3060 c_basename = c_basename.strip() or None
3061
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003062 if not is_legal_py_identifier(full_name):
3063 fail("Illegal function name: {}".format(full_name))
3064 if c_basename and not is_legal_c_identifier(c_basename):
3065 fail("Illegal C basename: {}".format(c_basename))
3066
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003067 return_converter = None
3068 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003069 ast_input = "def x() -> {}: pass".format(returns)
3070 module = None
3071 try:
3072 module = ast.parse(ast_input)
3073 except SyntaxError:
3074 pass
3075 if not module:
3076 fail("Badly-formed annotation for " + full_name + ": " + returns)
3077 try:
3078 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003079 if legacy:
3080 fail("Legacy converter {!r} not allowed as a return converter"
3081 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003082 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003083 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003084 return_converter = return_converters[name](**kwargs)
3085 except ValueError:
3086 fail("Badly-formed annotation for " + full_name + ": " + returns)
3087
3088 fields = [x.strip() for x in full_name.split('.')]
3089 function_name = fields.pop()
3090 module, cls = self.clinic._module_and_class(fields)
3091
Larry Hastings8666e652014-01-12 14:12:59 -08003092 fields = full_name.split('.')
3093 if fields[-1] == '__new__':
3094 if (self.kind != CLASS_METHOD) or (not cls):
3095 fail("__new__ must be a class method!")
3096 self.kind = METHOD_NEW
3097 elif fields[-1] == '__init__':
3098 if (self.kind != CALLABLE) or (not cls):
3099 fail("__init__ must be a normal method, not a class or static method!")
3100 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003101 if not return_converter:
3102 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003103 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003104 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003105
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003106 if not return_converter:
3107 return_converter = CReturnConverter()
3108
Larry Hastings31826802013-10-19 00:09:25 -07003109 if not module:
3110 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3111 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3112 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3113 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003114
3115 # insert a self converter automatically
3116 _, name = correct_name_for_self(self.function)
3117 sc = self.function.self_converter = self_converter(name, self.function)
3118 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3119 self.function.parameters[sc.name] = p_self
3120
Larry Hastings4a714d42014-01-14 22:22:41 -08003121 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003122 self.next(self.state_parameters_start)
3123
3124 # Now entering the parameters section. The rules, formally stated:
3125 #
3126 # * All lines must be indented with spaces only.
3127 # * The first line must be a parameter declaration.
3128 # * The first line must be indented.
3129 # * This first line establishes the indent for parameters.
3130 # * We'll call this number of spaces P (for "parameter").
3131 # * Thenceforth:
3132 # * Lines indented with P spaces specify a parameter.
3133 # * Lines indented with > P spaces are docstrings for the previous
3134 # parameter.
3135 # * We'll call this number of spaces D (for "docstring").
3136 # * All subsequent lines indented with >= D spaces are stored as
3137 # part of the per-parameter docstring.
3138 # * All lines will have the first D spaces of the indent stripped
3139 # before they are stored.
3140 # * It's illegal to have a line starting with a number of spaces X
3141 # such that P < X < D.
3142 # * A line with < P spaces is the first line of the function
3143 # docstring, which ends processing for parameters and per-parameter
3144 # docstrings.
3145 # * The first line of the function docstring must be at the same
3146 # indent as the function declaration.
3147 # * It's illegal to have any line in the parameters section starting
3148 # with X spaces such that F < X < P. (As before, F is the indent
3149 # of the function declaration.)
3150 #
Larry Hastings31826802013-10-19 00:09:25 -07003151 # Also, currently Argument Clinic places the following restrictions on groups:
3152 # * Each group must contain at least one parameter.
3153 # * Each group may contain at most one group, which must be the furthest
3154 # thing in the group from the required parameters. (The nested group
3155 # must be the first in the group when it's before the required
3156 # parameters, and the last thing in the group when after the required
3157 # parameters.)
3158 # * There may be at most one (top-level) group to the left or right of
3159 # the required parameters.
3160 # * You must specify a slash, and it must be after all parameters.
3161 # (In other words: either all parameters are positional-only,
3162 # or none are.)
3163 #
3164 # Said another way:
3165 # * Each group must contain at least one parameter.
3166 # * All left square brackets before the required parameters must be
3167 # consecutive. (You can't have a left square bracket followed
3168 # by a parameter, then another left square bracket. You can't
3169 # have a left square bracket, a parameter, a right square bracket,
3170 # and then a left square bracket.)
3171 # * All right square brackets after the required parameters must be
3172 # consecutive.
3173 #
3174 # These rules are enforced with a single state variable:
3175 # "parameter_state". (Previously the code was a miasma of ifs and
3176 # separate boolean state variables.) The states are:
3177 #
3178 # [ [ a, b, ] c, ] d, e, f, [ g, h, [ i ] ] / <- line
3179 # 01 2 3 4 5 6 <- state transitions
3180 #
3181 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3182 # 1: ps_left_square_before. left square brackets before required parameters.
3183 # 2: ps_group_before. in a group, before required parameters.
3184 # 3: ps_required. required parameters. (renumber left groups!)
3185 # 4: ps_group_after. in a group, after required parameters.
3186 # 5: ps_right_square_after. right square brackets after required parameters.
3187 # 6: ps_seen_slash. seen slash.
3188 ps_start, ps_left_square_before, ps_group_before, ps_required, \
3189 ps_group_after, ps_right_square_after, ps_seen_slash = range(7)
3190
3191 def state_parameters_start(self, line):
3192 if self.ignore_line(line):
3193 return
3194
3195 # if this line is not indented, we have no parameters
3196 if not self.indent.infer(line):
3197 return self.next(self.state_function_docstring, line)
3198
Larry Hastings2a727912014-01-16 11:32:01 -08003199 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003200 return self.next(self.state_parameter, line)
3201
3202
3203 def to_required(self):
3204 """
3205 Transition to the "required" parameter state.
3206 """
3207 if self.parameter_state != self.ps_required:
3208 self.parameter_state = self.ps_required
3209 for p in self.function.parameters.values():
3210 p.group = -p.group
3211
3212 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003213 if self.parameter_continuation:
3214 line = self.parameter_continuation + ' ' + line.lstrip()
3215 self.parameter_continuation = ''
3216
Larry Hastings31826802013-10-19 00:09:25 -07003217 if self.ignore_line(line):
3218 return
3219
3220 assert self.indent.depth == 2
3221 indent = self.indent.infer(line)
3222 if indent == -1:
3223 # we outdented, must be to definition column
3224 return self.next(self.state_function_docstring, line)
3225
3226 if indent == 1:
3227 # we indented, must be to new parameter docstring column
3228 return self.next(self.state_parameter_docstring_start, line)
3229
Larry Hastings2a727912014-01-16 11:32:01 -08003230 line = line.rstrip()
3231 if line.endswith('\\'):
3232 self.parameter_continuation = line[:-1]
3233 return
3234
Larry Hastings31826802013-10-19 00:09:25 -07003235 line = line.lstrip()
3236
3237 if line in ('*', '/', '[', ']'):
3238 self.parse_special_symbol(line)
3239 return
3240
3241 if self.parameter_state in (self.ps_start, self.ps_required):
3242 self.to_required()
3243 elif self.parameter_state == self.ps_left_square_before:
3244 self.parameter_state = self.ps_group_before
3245 elif self.parameter_state == self.ps_group_before:
3246 if not self.group:
3247 self.to_required()
3248 elif self.parameter_state == self.ps_group_after:
3249 pass
3250 else:
3251 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3252
Larry Hastings2a727912014-01-16 11:32:01 -08003253 base, equals, default = line.rpartition('=')
3254 if not equals:
3255 base = default
3256 default = None
Larry Hastings31826802013-10-19 00:09:25 -07003257 module = None
3258 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003259 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003260 module = ast.parse(ast_input)
3261 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003262 try:
3263 default = None
3264 ast_input = "def x({}): pass".format(line)
3265 module = ast.parse(ast_input)
3266 except SyntaxError:
3267 pass
Larry Hastings31826802013-10-19 00:09:25 -07003268 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003269 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003270
3271 function_args = module.body[0].args
3272 parameter = function_args.args[0]
3273
Larry Hastings16c51912014-01-07 11:53:01 -08003274 parameter_name = parameter.arg
3275 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3276
Larry Hastings2a727912014-01-16 11:32:01 -08003277 if not default:
3278 value = unspecified
3279 if 'py_default' in kwargs:
3280 fail("You can't specify py_default without specifying a default value!")
3281 else:
3282 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003283 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003284 ast_input = "x = {}".format(default)
3285 try:
3286 module = ast.parse(ast_input)
3287
Larry Hastings5c661892014-01-24 06:17:25 -08003288 if 'c_default' not in kwargs:
3289 # we can only represent very simple data values in C.
3290 # detect whether default is okay, via a blacklist
3291 # of disallowed ast nodes.
3292 class DetectBadNodes(ast.NodeVisitor):
3293 bad = False
3294 def bad_node(self, node):
3295 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003296
Larry Hastings5c661892014-01-24 06:17:25 -08003297 # inline function call
3298 visit_Call = bad_node
3299 # inline if statement ("x = 3 if y else z")
3300 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003301
Larry Hastings5c661892014-01-24 06:17:25 -08003302 # comprehensions and generator expressions
3303 visit_ListComp = visit_SetComp = bad_node
3304 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003305
Larry Hastings5c661892014-01-24 06:17:25 -08003306 # literals for advanced types
3307 visit_Dict = visit_Set = bad_node
3308 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003309
Larry Hastings5c661892014-01-24 06:17:25 -08003310 # "starred": "a = [1, 2, 3]; *a"
3311 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003312
Larry Hastings5c661892014-01-24 06:17:25 -08003313 # allow ellipsis, for now
3314 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003315
Larry Hastings5c661892014-01-24 06:17:25 -08003316 blacklist = DetectBadNodes()
3317 blacklist.visit(module)
3318 bad = blacklist.bad
3319 else:
3320 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003321 # but at least make an attempt at ensuring it's a valid expression.
3322 try:
3323 value = eval(default)
3324 if value == unspecified:
3325 fail("'unspecified' is not a legal default value!")
3326 except NameError:
3327 pass # probably a named constant
3328 except Exception as e:
3329 fail("Malformed expression given as default value\n"
3330 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003331 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003332 fail("Unsupported expression as default value: " + repr(default))
3333
3334 expr = module.body[0].value
3335 # mild hack: explicitly support NULL as a default value
3336 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3337 value = NULL
3338 py_default = 'None'
3339 c_default = "NULL"
3340 elif (isinstance(expr, ast.BinOp) or
3341 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3342 c_default = kwargs.get("c_default")
3343 if not (isinstance(c_default, str) and c_default):
3344 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3345 py_default = default
3346 value = unknown
3347 elif isinstance(expr, ast.Attribute):
3348 a = []
3349 n = expr
3350 while isinstance(n, ast.Attribute):
3351 a.append(n.attr)
3352 n = n.value
3353 if not isinstance(n, ast.Name):
3354 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3355 a.append(n.id)
3356 py_default = ".".join(reversed(a))
3357
3358 c_default = kwargs.get("c_default")
3359 if not (isinstance(c_default, str) and c_default):
3360 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3361
3362 try:
3363 value = eval(py_default)
3364 except NameError:
3365 value = unknown
3366 else:
3367 value = ast.literal_eval(expr)
3368 py_default = repr(value)
3369 if isinstance(value, (bool, None.__class__)):
3370 c_default = "Py_" + py_default
3371 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003372 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003373 else:
3374 c_default = py_default
3375
3376 except SyntaxError as e:
3377 fail("Syntax error: " + repr(e.text))
3378 except (ValueError, AttributeError):
3379 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003380 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003381 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003382 if not (isinstance(c_default, str) and c_default):
3383 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3384
Larry Hastings2a727912014-01-16 11:32:01 -08003385 kwargs.setdefault('c_default', c_default)
3386 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003387
Larry Hastings31826802013-10-19 00:09:25 -07003388 dict = legacy_converters if legacy else converters
3389 legacy_str = "legacy " if legacy else ""
3390 if name not in dict:
3391 fail('{} is not a valid {}converter'.format(name, legacy_str))
3392 converter = dict[name](parameter_name, self.function, value, **kwargs)
3393
3394 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003395
3396 if isinstance(converter, self_converter):
3397 if len(self.function.parameters) == 1:
3398 if (self.parameter_state != self.ps_required):
3399 fail("A 'self' parameter cannot be marked optional.")
3400 if value is not unspecified:
3401 fail("A 'self' parameter cannot have a default value.")
3402 if self.group:
3403 fail("A 'self' parameter cannot be in an optional group.")
3404 kind = inspect.Parameter.POSITIONAL_ONLY
3405 self.parameter_state = self.ps_start
3406 self.function.parameters.clear()
3407 else:
3408 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3409
Larry Hastings31826802013-10-19 00:09:25 -07003410 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003411
3412 if parameter_name in self.function.parameters:
3413 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003414 self.function.parameters[parameter_name] = p
3415
3416 def parse_converter(self, annotation):
3417 if isinstance(annotation, ast.Str):
3418 return annotation.s, True, {}
3419
3420 if isinstance(annotation, ast.Name):
3421 return annotation.id, False, {}
3422
Larry Hastings4a55fc52014-01-12 11:09:57 -08003423 if not isinstance(annotation, ast.Call):
3424 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003425
3426 name = annotation.func.id
3427 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
3428 return name, False, kwargs
3429
3430 def parse_special_symbol(self, symbol):
3431 if self.parameter_state == self.ps_seen_slash:
3432 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3433
3434 if symbol == '*':
3435 if self.keyword_only:
3436 fail("Function " + self.function.name + " uses '*' more than once.")
3437 self.keyword_only = True
3438 elif symbol == '[':
3439 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3440 self.parameter_state = self.ps_left_square_before
3441 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3442 self.parameter_state = self.ps_group_after
3443 else:
3444 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3445 self.group += 1
3446 elif symbol == ']':
3447 if not self.group:
3448 fail("Function " + self.function.name + " has a ] without a matching [.")
3449 if not any(p.group == self.group for p in self.function.parameters.values()):
3450 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3451 self.group -= 1
3452 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3453 self.parameter_state = self.ps_group_before
3454 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3455 self.parameter_state = self.ps_right_square_after
3456 else:
3457 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3458 elif symbol == '/':
3459 # ps_required is allowed here, that allows positional-only without option groups
3460 # to work (and have default values!)
3461 if (self.parameter_state not in (self.ps_required, self.ps_right_square_after, self.ps_group_before)) or self.group:
3462 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3463 if self.keyword_only:
3464 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3465 self.parameter_state = self.ps_seen_slash
3466 # fixup preceeding parameters
3467 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003468 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003469 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3470 p.kind = inspect.Parameter.POSITIONAL_ONLY
3471
3472 def state_parameter_docstring_start(self, line):
3473 self.parameter_docstring_indent = len(self.indent.margin)
3474 assert self.indent.depth == 3
3475 return self.next(self.state_parameter_docstring, line)
3476
3477 # every line of the docstring must start with at least F spaces,
3478 # where F > P.
3479 # these F spaces will be stripped.
3480 def state_parameter_docstring(self, line):
3481 stripped = line.strip()
3482 if stripped.startswith('#'):
3483 return
3484
3485 indent = self.indent.measure(line)
3486 if indent < self.parameter_docstring_indent:
3487 self.indent.infer(line)
3488 assert self.indent.depth < 3
3489 if self.indent.depth == 2:
3490 # back to a parameter
3491 return self.next(self.state_parameter, line)
3492 assert self.indent.depth == 1
3493 return self.next(self.state_function_docstring, line)
3494
3495 assert self.function.parameters
3496 last_parameter = next(reversed(list(self.function.parameters.values())))
3497
3498 new_docstring = last_parameter.docstring
3499
3500 if new_docstring:
3501 new_docstring += '\n'
3502 if stripped:
3503 new_docstring += self.indent.dedent(line)
3504
3505 last_parameter.docstring = new_docstring
3506
3507 # the final stanza of the DSL is the docstring.
3508 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003509 if self.group:
3510 fail("Function " + self.function.name + " has a ] without a matching [.")
3511
3512 stripped = line.strip()
3513 if stripped.startswith('#'):
3514 return
3515
3516 new_docstring = self.function.docstring
3517 if new_docstring:
3518 new_docstring += "\n"
3519 if stripped:
3520 line = self.indent.dedent(line).rstrip()
3521 else:
3522 line = ''
3523 new_docstring += line
3524 self.function.docstring = new_docstring
3525
3526 def format_docstring(self):
3527 f = self.function
3528
Larry Hastings5c661892014-01-24 06:17:25 -08003529 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3530 if new_or_init and not f.docstring:
3531 # don't render a docstring at all, no signature, nothing.
3532 return f.docstring
3533
Larry Hastings31826802013-10-19 00:09:25 -07003534 add, output = text_accumulator()
3535 parameters = list(f.parameters.values())
3536
3537 ##
3538 ## docstring first line
3539 ##
3540
Larry Hastings5c661892014-01-24 06:17:25 -08003541 if new_or_init:
Larry Hastings46258262014-01-22 03:05:49 -08003542 assert f.cls
3543 add(f.cls.name)
3544 else:
3545 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003546 add('(')
3547
3548 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003549 assert parameters, "We should always have a self parameter. " + repr(f)
3550 assert isinstance(parameters[0].converter, self_converter)
3551 parameters[0].right_bracket_count = 0
3552 parameters_after_self = parameters[1:]
3553 if parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003554 # for now, the only way Clinic supports positional-only parameters
Larry Hastings5c661892014-01-24 06:17:25 -08003555 # is if all of them are positional-only...
3556 #
3557 # ... except for self! self is always positional-only.
3558
3559 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters_after_self]
3560 if parameters_after_self[0].kind == inspect.Parameter.POSITIONAL_ONLY:
Larry Hastings31826802013-10-19 00:09:25 -07003561 assert all(positional_only_parameters)
3562 for p in parameters:
3563 p.right_bracket_count = abs(p.group)
3564 else:
3565 # don't put any right brackets around non-positional-only parameters, ever.
Larry Hastings5c661892014-01-24 06:17:25 -08003566 for p in parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003567 p.right_bracket_count = 0
3568
3569 right_bracket_count = 0
3570
3571 def fix_right_bracket_count(desired):
3572 nonlocal right_bracket_count
3573 s = ''
3574 while right_bracket_count < desired:
3575 s += '['
3576 right_bracket_count += 1
3577 while right_bracket_count > desired:
3578 s += ']'
3579 right_bracket_count -= 1
3580 return s
3581
3582 added_star = False
3583 add_comma = False
3584
3585 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08003586 if not p.converter.show_in_signature:
3587 continue
3588
Larry Hastings31826802013-10-19 00:09:25 -07003589 assert p.name
3590
3591 if p.is_keyword_only() and not added_star:
3592 added_star = True
3593 if add_comma:
3594 add(', ')
3595 add('*')
Larry Hastings5c661892014-01-24 06:17:25 -08003596 add_comma = True
Larry Hastings31826802013-10-19 00:09:25 -07003597
Larry Hastings5c661892014-01-24 06:17:25 -08003598 name = p.converter.signature_name or p.name
3599 a = [name]
Larry Hastings31826802013-10-19 00:09:25 -07003600 if p.converter.is_optional():
3601 a.append('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08003602 value = p.converter.py_default
3603 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08003604 value = repr(p.converter.default)
Larry Hastingsc4fe0922014-01-19 02:27:34 -08003605 a.append(value)
Larry Hastings31826802013-10-19 00:09:25 -07003606 s = fix_right_bracket_count(p.right_bracket_count)
3607 s += "".join(a)
3608 if add_comma:
3609 add(', ')
3610 add(s)
3611 add_comma = True
3612
3613 add(fix_right_bracket_count(0))
3614 add(')')
3615
Larry Hastings2a727912014-01-16 11:32:01 -08003616 # PEP 8 says:
3617 #
3618 # The Python standard library will not use function annotations
3619 # as that would result in a premature commitment to a particular
3620 # annotation style. Instead, the annotations are left for users
3621 # to discover and experiment with useful annotation styles.
3622 #
3623 # therefore this is commented out:
3624 #
3625 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003626 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08003627 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003628
3629 docstring_first_line = output()
3630
3631 # now fix up the places where the brackets look wrong
3632 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
3633
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003634 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07003635 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003636 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07003637 for p in parameters:
3638 if not p.docstring.strip():
3639 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003640 if spacer_line:
3641 add('\n')
3642 else:
3643 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07003644 add(" ")
3645 add(p.name)
3646 add('\n')
3647 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003648 parameters = output()
3649 if parameters:
3650 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07003651
3652 ##
3653 ## docstring body
3654 ##
3655
3656 docstring = f.docstring.rstrip()
3657 lines = [line.rstrip() for line in docstring.split('\n')]
3658
3659 # Enforce the summary line!
3660 # The first line of a docstring should be a summary of the function.
3661 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
3662 # by itself.
3663 #
3664 # Argument Clinic enforces the following rule:
3665 # * either the docstring is empty,
3666 # * or it must have a summary line.
3667 #
3668 # Guido said Clinic should enforce this:
3669 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
3670
3671 if len(lines) >= 2:
3672 if lines[1]:
3673 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
3674 "Every non-blank function docstring must start with\n" +
3675 "a single line summary followed by an empty line.")
3676 elif len(lines) == 1:
3677 # the docstring is only one line right now--the summary line.
3678 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003679 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07003680 lines.append('')
3681
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003682 parameters_marker_count = len(docstring.split('{parameters}')) - 1
3683 if parameters_marker_count > 1:
3684 fail('You may not specify {parameters} more than once in a docstring!')
3685
3686 if not parameters_marker_count:
3687 # insert after summary line
3688 lines.insert(2, '{parameters}')
3689
3690 # insert at front of docstring
3691 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07003692
3693 docstring = "\n".join(lines)
3694
3695 add(docstring)
3696 docstring = output()
3697
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003698 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07003699 docstring = docstring.rstrip()
3700
3701 return docstring
3702
3703 def state_terminal(self, line):
3704 """
3705 Called when processing the block is done.
3706 """
3707 assert not line
3708
3709 if not self.function:
3710 return
3711
3712 if self.keyword_only:
3713 values = self.function.parameters.values()
3714 if not values:
3715 no_parameter_after_star = True
3716 else:
3717 last_parameter = next(reversed(list(values)))
3718 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
3719 if no_parameter_after_star:
3720 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
3721
3722 # remove trailing whitespace from all parameter docstrings
3723 for name, value in self.function.parameters.items():
3724 if not value:
3725 continue
3726 value.docstring = value.docstring.rstrip()
3727
3728 self.function.docstring = self.format_docstring()
3729
3730
Larry Hastings5c661892014-01-24 06:17:25 -08003731
3732
Larry Hastings31826802013-10-19 00:09:25 -07003733# maps strings to callables.
3734# the callable should return an object
3735# that implements the clinic parser
3736# interface (__init__ and parse).
3737#
3738# example parsers:
3739# "clinic", handles the Clinic DSL
3740# "python", handles running Python code
3741#
3742parsers = {'clinic' : DSLParser, 'python': PythonParser}
3743
3744
3745clinic = None
3746
3747
3748def main(argv):
3749 import sys
3750
3751 if sys.version_info.major < 3 or sys.version_info.minor < 3:
3752 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
3753
3754 import argparse
3755 cmdline = argparse.ArgumentParser()
3756 cmdline.add_argument("-f", "--force", action='store_true')
3757 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08003758 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07003759 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003760 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07003761 cmdline.add_argument("filename", type=str, nargs="*")
3762 ns = cmdline.parse_args(argv)
3763
3764 if ns.converters:
3765 if ns.filename:
3766 print("Usage error: can't specify --converters and a filename at the same time.")
3767 print()
3768 cmdline.print_usage()
3769 sys.exit(-1)
3770 converters = []
3771 return_converters = []
3772 ignored = set("""
3773 add_c_converter
3774 add_c_return_converter
3775 add_default_legacy_c_converter
3776 add_legacy_c_converter
3777 """.strip().split())
3778 module = globals()
3779 for name in module:
3780 for suffix, ids in (
3781 ("_return_converter", return_converters),
3782 ("_converter", converters),
3783 ):
3784 if name in ignored:
3785 continue
3786 if name.endswith(suffix):
3787 ids.append((name, name[:-len(suffix)]))
3788 break
3789 print()
3790
3791 print("Legacy converters:")
3792 legacy = sorted(legacy_converters)
3793 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
3794 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
3795 print()
3796
3797 for title, attribute, ids in (
3798 ("Converters", 'converter_init', converters),
3799 ("Return converters", 'return_converter_init', return_converters),
3800 ):
3801 print(title + ":")
3802 longest = -1
3803 for name, short_name in ids:
3804 longest = max(longest, len(short_name))
3805 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
3806 cls = module[name]
3807 callable = getattr(cls, attribute, None)
3808 if not callable:
3809 continue
3810 signature = inspect.signature(callable)
3811 parameters = []
3812 for parameter_name, parameter in signature.parameters.items():
3813 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
3814 if parameter.default != inspect.Parameter.empty:
3815 s = '{}={!r}'.format(parameter_name, parameter.default)
3816 else:
3817 s = parameter_name
3818 parameters.append(s)
3819 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07003820 print()
Larry Hastings2a727912014-01-16 11:32:01 -08003821 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
3822 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07003823 sys.exit(0)
3824
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003825 if ns.make:
3826 if ns.output or ns.filename:
3827 print("Usage error: can't use -o or filenames with --make.")
3828 print()
3829 cmdline.print_usage()
3830 sys.exit(-1)
3831 for root, dirs, files in os.walk('.'):
Larry Hastings5c661892014-01-24 06:17:25 -08003832 for rcs_dir in ('.svn', '.git', '.hg', 'build'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003833 if rcs_dir in dirs:
3834 dirs.remove(rcs_dir)
3835 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08003836 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003837 continue
3838 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08003839 if ns.verbose:
3840 print(path)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003841 parse_file(path, verify=not ns.force)
3842 return
3843
Larry Hastings31826802013-10-19 00:09:25 -07003844 if not ns.filename:
3845 cmdline.print_usage()
3846 sys.exit(-1)
3847
3848 if ns.output and len(ns.filename) > 1:
3849 print("Usage error: can't use -o with multiple filenames.")
3850 print()
3851 cmdline.print_usage()
3852 sys.exit(-1)
3853
3854 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08003855 if ns.verbose:
3856 print(filename)
Larry Hastings31826802013-10-19 00:09:25 -07003857 parse_file(filename, output=ns.output, verify=not ns.force)
3858
3859
3860if __name__ == "__main__":
3861 sys.exit(main(sys.argv[1:]))