blob: c26d268797a2932ac0a03a5368c8554db052b6ca [file] [log] [blame]
Larry Hastings31826802013-10-19 00:09:25 -07001#!/usr/bin/env python3
2#
3# Argument Clinic
4# Copyright 2012-2013 by Larry Hastings.
5# Licensed to the PSF under a contributor agreement.
6#
7
8import abc
9import ast
10import atexit
Larry Hastings31826802013-10-19 00:09:25 -070011import collections
12import contextlib
13import functools
14import hashlib
15import inspect
16import io
17import itertools
18import os
Larry Hastingsbebf7352014-01-17 17:47:17 -080019import pprint
Larry Hastings31826802013-10-19 00:09:25 -070020import re
21import shlex
22import sys
23import tempfile
24import textwrap
Georg Brandlaabebde2014-01-16 06:53:54 +010025import traceback
Larry Hastingsbebf7352014-01-17 17:47:17 -080026import uuid
Larry Hastings31826802013-10-19 00:09:25 -070027
Larry Hastings31826802013-10-19 00:09:25 -070028# TODO:
Larry Hastings31826802013-10-19 00:09:25 -070029#
30# soon:
31#
32# * allow mixing any two of {positional-only, positional-or-keyword,
33# keyword-only}
34# * dict constructor uses positional-only and keyword-only
35# * max and min use positional only with an optional group
36# and keyword-only
37#
Larry Hastings31826802013-10-19 00:09:25 -070038
Larry Hastingsebdcb502013-11-23 14:54:00 -080039version = '1'
40
Larry Hastings31826802013-10-19 00:09:25 -070041_empty = inspect._empty
42_void = inspect._void
43
Larry Hastings4a55fc52014-01-12 11:09:57 -080044NoneType = type(None)
Larry Hastings31826802013-10-19 00:09:25 -070045
46class Unspecified:
47 def __repr__(self):
48 return '<Unspecified>'
49
50unspecified = Unspecified()
51
52
53class Null:
54 def __repr__(self):
55 return '<Null>'
56
57NULL = Null()
58
59
Larry Hastings2a727912014-01-16 11:32:01 -080060class Unknown:
61 def __repr__(self):
62 return '<Unknown>'
63
64unknown = Unknown()
65
66
Larry Hastings31826802013-10-19 00:09:25 -070067def _text_accumulator():
68 text = []
69 def output():
70 s = ''.join(text)
71 text.clear()
72 return s
73 return text, text.append, output
74
75
76def text_accumulator():
77 """
78 Creates a simple text accumulator / joiner.
79
80 Returns a pair of callables:
81 append, output
82 "append" appends a string to the accumulator.
83 "output" returns the contents of the accumulator
84 joined together (''.join(accumulator)) and
85 empties the accumulator.
86 """
87 text, append, output = _text_accumulator()
88 return append, output
89
90
Larry Hastingsbebf7352014-01-17 17:47:17 -080091def warn_or_fail(fail=False, *args, filename=None, line_number=None):
Larry Hastings31826802013-10-19 00:09:25 -070092 joined = " ".join([str(a) for a in args])
93 add, output = text_accumulator()
Larry Hastingsbebf7352014-01-17 17:47:17 -080094 if fail:
95 add("Error")
96 else:
97 add("Warning")
Larry Hastings31826802013-10-19 00:09:25 -070098 if clinic:
99 if filename is None:
100 filename = clinic.filename
101 if clinic.block_parser and (line_number is None):
102 line_number = clinic.block_parser.line_number
103 if filename is not None:
104 add(' in file "' + filename + '"')
105 if line_number is not None:
106 add(" on line " + str(line_number))
107 add(':\n')
108 add(joined)
109 print(output())
Larry Hastingsbebf7352014-01-17 17:47:17 -0800110 if fail:
111 sys.exit(-1)
Larry Hastings31826802013-10-19 00:09:25 -0700112
113
Larry Hastingsbebf7352014-01-17 17:47:17 -0800114def warn(*args, filename=None, line_number=None):
115 return warn_or_fail(False, *args, filename=filename, line_number=line_number)
116
117def fail(*args, filename=None, line_number=None):
118 return warn_or_fail(True, *args, filename=filename, line_number=line_number)
119
Larry Hastings31826802013-10-19 00:09:25 -0700120
121def quoted_for_c_string(s):
122 for old, new in (
123 ('"', '\\"'),
124 ("'", "\\'"),
125 ):
126 s = s.replace(old, new)
127 return s
128
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700129is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
130
131def is_legal_py_identifier(s):
132 return all(is_legal_c_identifier(field) for field in s.split('.'))
133
Larry Hastingsbebf7352014-01-17 17:47:17 -0800134# identifiers that are okay in Python but aren't a good idea in C.
135# so if they're used Argument Clinic will add "_value" to the end
136# of the name in C.
Larry Hastings31826802013-10-19 00:09:25 -0700137c_keywords = set("""
Larry Hastingsbebf7352014-01-17 17:47:17 -0800138asm auto break case char cls const continue default do double
Larry Hastingsed4a1c52013-11-18 09:32:13 -0800139else enum extern float for goto if inline int long module null
140register return self short signed sizeof static struct switch
Larry Hastingsbebf7352014-01-17 17:47:17 -0800141typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700142""".strip().split())
143
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700144def ensure_legal_c_identifier(s):
145 # for now, just complain if what we're given isn't legal
146 if not is_legal_c_identifier(s):
147 fail("Illegal C identifier: {}".format(s))
148 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700149 if s in c_keywords:
150 return s + "_value"
151 return s
152
153def rstrip_lines(s):
154 text, add, output = _text_accumulator()
155 for line in s.split('\n'):
156 add(line.rstrip())
157 add('\n')
158 text.pop()
159 return output()
160
161def linear_format(s, **kwargs):
162 """
163 Perform str.format-like substitution, except:
164 * The strings substituted must be on lines by
165 themselves. (This line is the "source line".)
166 * If the substitution text is empty, the source line
167 is removed in the output.
168 * If the substitution text is not empty:
169 * Each line of the substituted text is indented
170 by the indent of the source line.
171 * A newline will be added to the end.
172 """
173
174 add, output = text_accumulator()
175 for line in s.split('\n'):
176 indent, curly, trailing = line.partition('{')
177 if not curly:
178 add(line)
179 add('\n')
180 continue
181
182 name, curl, trailing = trailing.partition('}')
183 if not curly or name not in kwargs:
184 add(line)
185 add('\n')
186 continue
187
188 if trailing:
189 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
190 if indent.strip():
191 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
192
193 value = kwargs[name]
194 if not value:
195 continue
196
197 value = textwrap.indent(rstrip_lines(value), indent)
198 add(value)
199 add('\n')
200
201 return output()[:-1]
202
Larry Hastingsbebf7352014-01-17 17:47:17 -0800203def indent_all_lines(s, prefix):
204 """
205 Returns 's', with 'prefix' prepended to all lines.
206
207 If the last line is empty, prefix is not prepended
208 to it. (If s is blank, returns s unchanged.)
209
210 (textwrap.indent only adds to non-blank lines.)
211 """
212 split = s.split('\n')
213 last = split.pop()
214 final = []
215 for line in split:
216 final.append(prefix)
217 final.append(line)
218 final.append('\n')
219 if last:
220 final.append(prefix)
221 final.append(last)
222 return ''.join(final)
223
224def suffix_all_lines(s, suffix):
225 """
226 Returns 's', with 'suffix' appended to all lines.
227
228 If the last line is empty, suffix is not appended
229 to it. (If s is blank, returns s unchanged.)
230 """
231 split = s.split('\n')
232 last = split.pop()
233 final = []
234 for line in split:
235 final.append(line)
236 final.append(suffix)
237 final.append('\n')
238 if last:
239 final.append(last)
240 final.append(suffix)
241 return ''.join(final)
242
243
Larry Hastingsebdcb502013-11-23 14:54:00 -0800244def version_splitter(s):
245 """Splits a version string into a tuple of integers.
246
247 The following ASCII characters are allowed, and employ
248 the following conversions:
249 a -> -3
250 b -> -2
251 c -> -1
252 (This permits Python-style version strings such as "1.4b3".)
253 """
254 version = []
255 accumulator = []
256 def flush():
257 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800258 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800259 version.append(int(''.join(accumulator)))
260 accumulator.clear()
261
262 for c in s:
263 if c.isdigit():
264 accumulator.append(c)
265 elif c == '.':
266 flush()
267 elif c in 'abc':
268 flush()
269 version.append('abc'.index(c) - 3)
270 else:
271 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
272 flush()
273 return tuple(version)
274
275def version_comparitor(version1, version2):
276 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
277 for i, (a, b) in enumerate(iterator):
278 if a < b:
279 return -1
280 if a > b:
281 return 1
282 return 0
283
Larry Hastings31826802013-10-19 00:09:25 -0700284
285class CRenderData:
286 def __init__(self):
287
288 # The C statements to declare variables.
289 # Should be full lines with \n eol characters.
290 self.declarations = []
291
292 # The C statements required to initialize the variables before the parse call.
293 # Should be full lines with \n eol characters.
294 self.initializers = []
295
296 # The entries for the "keywords" array for PyArg_ParseTuple.
297 # Should be individual strings representing the names.
298 self.keywords = []
299
300 # The "format units" for PyArg_ParseTuple.
301 # Should be individual strings that will get
302 self.format_units = []
303
304 # The varargs arguments for PyArg_ParseTuple.
305 self.parse_arguments = []
306
307 # The parameter declarations for the impl function.
308 self.impl_parameters = []
309
310 # The arguments to the impl function at the time it's called.
311 self.impl_arguments = []
312
313 # For return converters: the name of the variable that
314 # should receive the value returned by the impl.
315 self.return_value = "return_value"
316
317 # For return converters: the code to convert the return
318 # value from the parse function. This is also where
319 # you should check the _return_value for errors, and
320 # "goto exit" if there are any.
321 self.return_conversion = []
322
323 # The C statements required to clean up after the impl call.
324 self.cleanup = []
325
326
327class Language(metaclass=abc.ABCMeta):
328
329 start_line = ""
330 body_prefix = ""
331 stop_line = ""
332 checksum_line = ""
333
334 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800335 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700336 pass
337
338 def validate(self):
339 def assert_only_one(field, token='dsl_name'):
340 line = getattr(self, field)
341 token = '{' + token + '}'
342 if len(line.split(token)) != 2:
343 fail(self.__class__.__name__ + " " + field + " must contain " + token + " exactly once!")
344 assert_only_one('start_line')
345 assert_only_one('stop_line')
346 assert_only_one('checksum_line')
347 assert_only_one('checksum_line', 'checksum')
348
349 if len(self.body_prefix.split('{dsl_name}')) >= 3:
350 fail(self.__class__.__name__ + " body_prefix may contain " + token + " once at most!")
351
352
353
354class PythonLanguage(Language):
355
356 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800357 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700358 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800359 stop_line = "#[{dsl_name} start generated code]*/"
360 checksum_line = "#/*[{dsl_name} end generated code: checksum={checksum}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700361
362
363def permute_left_option_groups(l):
364 """
365 Given [1, 2, 3], should yield:
366 ()
367 (3,)
368 (2, 3)
369 (1, 2, 3)
370 """
371 yield tuple()
372 accumulator = []
373 for group in reversed(l):
374 accumulator = list(group) + accumulator
375 yield tuple(accumulator)
376
377
378def permute_right_option_groups(l):
379 """
380 Given [1, 2, 3], should yield:
381 ()
382 (1,)
383 (1, 2)
384 (1, 2, 3)
385 """
386 yield tuple()
387 accumulator = []
388 for group in l:
389 accumulator.extend(group)
390 yield tuple(accumulator)
391
392
393def permute_optional_groups(left, required, right):
394 """
395 Generator function that computes the set of acceptable
396 argument lists for the provided iterables of
397 argument groups. (Actually it generates a tuple of tuples.)
398
399 Algorithm: prefer left options over right options.
400
401 If required is empty, left must also be empty.
402 """
403 required = tuple(required)
404 result = []
405
406 if not required:
407 assert not left
408
409 accumulator = []
410 counts = set()
411 for r in permute_right_option_groups(right):
412 for l in permute_left_option_groups(left):
413 t = l + required + r
414 if len(t) in counts:
415 continue
416 counts.add(len(t))
417 accumulator.append(t)
418
419 accumulator.sort(key=len)
420 return tuple(accumulator)
421
422
423class CLanguage(Language):
424
Larry Hastings61272b72014-01-07 12:41:53 -0800425 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700426 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800427 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700428 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800429 stop_line = "[{dsl_name} start generated code]*/"
430 checksum_line = "/*[{dsl_name} end generated code: checksum={checksum}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700431
Larry Hastingsbebf7352014-01-17 17:47:17 -0800432 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700433 function = None
434 for o in signatures:
435 if isinstance(o, Function):
436 if function:
437 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
438 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800439 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700440
441 def docstring_for_c_string(self, f):
442 text, add, output = _text_accumulator()
443 # turn docstring into a properly quoted C string
444 for line in f.docstring.split('\n'):
445 add('"')
446 add(quoted_for_c_string(line))
447 add('\\n"\n')
448
449 text.pop()
450 add('"')
451 return ''.join(text)
452
Larry Hastings31826802013-10-19 00:09:25 -0700453
Larry Hastingsbebf7352014-01-17 17:47:17 -0800454 def output_templates(self, f):
455 parameters = list(f.parameters.values())
456 converters = [p.converter for p in parameters]
457
458 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
459 default_return_converter = (not f.return_converter or
460 f.return_converter.type == 'PyObject *')
461
462 positional = parameters and (parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY)
463 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
464 first_optional = len(parameters)
465 for i, p in enumerate(parameters):
466 c = p.converter
467 if type(c) != object_converter:
468 break
469 if c.format_unit != 'O':
470 break
471 if p.default is not unspecified:
472 first_optional = min(first_optional, i)
473 else:
474 all_boring_objects = True
475
476 meth_o = (len(parameters) == 1 and
477 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
478 not converters[0].is_optional() and
479 isinstance(converters[0], object_converter) and
480 converters[0].format_unit == 'O')
481
482
483 # we have to set seven things before we're done:
484 #
485 # docstring_prototype
486 # docstring_definition
487 # impl_prototype
488 # methoddef_define
489 # parser_prototype
490 # parser_definition
491 # impl_definition
492 #
493 # since impl_prototype is always just impl_definition + ';'
494 # we just define impl_definition at the top
495
496 docstring_prototype = "PyDoc_VAR({c_basename}__doc__);"
497
498 docstring_definition = """
Larry Hastings31826802013-10-19 00:09:25 -0700499PyDoc_STRVAR({c_basename}__doc__,
500{docstring});
Larry Hastingsbebf7352014-01-17 17:47:17 -0800501""".strip()
Larry Hastings31826802013-10-19 00:09:25 -0700502
Larry Hastingsbebf7352014-01-17 17:47:17 -0800503 impl_definition = """
Larry Hastings31826802013-10-19 00:09:25 -0700504static {impl_return_type}
Larry Hastingsbebf7352014-01-17 17:47:17 -0800505{c_basename}_impl({impl_parameters})""".strip()
Larry Hastings31826802013-10-19 00:09:25 -0700506
Larry Hastingsbebf7352014-01-17 17:47:17 -0800507 impl_prototype = parser_prototype = parser_definition = None
508
509 def meth_varargs():
510 nonlocal flags
511 nonlocal parser_prototype
512
513 flags = "METH_VARARGS"
514
515 parser_prototype = """
516static PyObject *
517{c_basename}({self_type}{self_name}, PyObject *args)
518""".strip()
519
520 if not parameters:
521 # no parameters, METH_NOARGS
522
523 flags = "METH_NOARGS"
524
525 parser_prototype = """
Larry Hastings31826802013-10-19 00:09:25 -0700526static PyObject *
Larry Hastings3cceb382014-01-04 11:09:09 -0800527{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800528""".strip()
529
530 if default_return_converter:
531 parser_definition = parser_prototype + """
532{{
533 return {c_basename}_impl({impl_arguments});
534}}
535""".rstrip()
536 else:
537 parser_definition = parser_prototype + """
Larry Hastings31826802013-10-19 00:09:25 -0700538{{
539 PyObject *return_value = NULL;
540 {declarations}
541 {initializers}
542
543 {return_value} = {c_basename}_impl({impl_arguments});
544 {return_conversion}
545
546{exit_label}
547 {cleanup}
548 return return_value;
549}}
Larry Hastingsbebf7352014-01-17 17:47:17 -0800550""".rstrip()
Larry Hastings31826802013-10-19 00:09:25 -0700551
Larry Hastingsbebf7352014-01-17 17:47:17 -0800552 elif meth_o:
553 if default_return_converter:
554 # maps perfectly to METH_O, doesn't need a return converter,
555 # so we skip the parse function and call
556 # directly into the impl function
Larry Hastings31826802013-10-19 00:09:25 -0700557
Larry Hastingsbebf7352014-01-17 17:47:17 -0800558 # SLIGHT HACK
559 # METH_O uses {impl_parameters} for the parser.
560
561 flags = "METH_O"
562
563 impl_definition = """
Larry Hastings31826802013-10-19 00:09:25 -0700564static PyObject *
565{c_basename}({impl_parameters})
Larry Hastingsbebf7352014-01-17 17:47:17 -0800566""".strip()
Larry Hastings31826802013-10-19 00:09:25 -0700567
Larry Hastingsbebf7352014-01-17 17:47:17 -0800568 impl_prototype = parser_prototype = parser_definition = ''
Larry Hastings31826802013-10-19 00:09:25 -0700569
Larry Hastingsbebf7352014-01-17 17:47:17 -0800570 else:
571 # SLIGHT HACK
572 # METH_O uses {impl_parameters} for the parser.
573
574 flags = "METH_O"
575
576 parser_prototype = """
Larry Hastings31826802013-10-19 00:09:25 -0700577static PyObject *
578{c_basename}({impl_parameters})
Larry Hastingsbebf7352014-01-17 17:47:17 -0800579""".strip()
580
581 parser_definition = parser_prototype + """
Larry Hastings31826802013-10-19 00:09:25 -0700582{{
583 PyObject *return_value = NULL;
584 {declarations}
585 {initializers}
Larry Hastingsbebf7352014-01-17 17:47:17 -0800586
Larry Hastings31826802013-10-19 00:09:25 -0700587 _return_value = {c_basename}_impl({impl_arguments});
588 {return_conversion}
589
590{exit_label}
591 {cleanup}
592 return return_value;
593}}
Larry Hastingsbebf7352014-01-17 17:47:17 -0800594""".rstrip()
Larry Hastings31826802013-10-19 00:09:25 -0700595
Larry Hastingsbebf7352014-01-17 17:47:17 -0800596 elif has_option_groups:
597 # positional parameters with option groups
598 # (we have to generate lots of PyArg_ParseTuple calls
599 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700600
Larry Hastingsbebf7352014-01-17 17:47:17 -0800601 meth_varargs()
Larry Hastings31826802013-10-19 00:09:25 -0700602
Larry Hastingsbebf7352014-01-17 17:47:17 -0800603 parser_definition = parser_prototype + """
Larry Hastings31826802013-10-19 00:09:25 -0700604{{
605 PyObject *return_value = NULL;
606 {declarations}
607 {initializers}
608
609 {option_group_parsing}
610 {return_value} = {c_basename}_impl({impl_arguments});
611 {return_conversion}
612
613{exit_label}
614 {cleanup}
615 return return_value;
616}}
Larry Hastingsbebf7352014-01-17 17:47:17 -0800617""".rstrip()
Larry Hastings31826802013-10-19 00:09:25 -0700618
Larry Hastingsbebf7352014-01-17 17:47:17 -0800619 elif positional and all_boring_objects:
620 # positional-only, but no option groups,
621 # and nothing but normal objects:
622 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700623
Larry Hastingsbebf7352014-01-17 17:47:17 -0800624 meth_varargs()
Larry Hastings31826802013-10-19 00:09:25 -0700625
Larry Hastingsbebf7352014-01-17 17:47:17 -0800626 # substitute in the min and max by hand right here
627 assert parameters
628 min_o = first_optional
629 max_o = len(parameters)
630 if isinstance(parameters[0].converter, self_converter):
631 min_o -= 1
632 max_o -= 1
633 min_o = str(min_o)
634 max_o = str(max_o)
635
636 parser_definition = parser_prototype + """
637{{
638 PyObject *return_value = NULL;
639 {declarations}
640 {initializers}
641
642 if (!PyArg_UnpackTuple(args, "{name}",
643 {min}, {max},
644 {parse_arguments}))
645 goto exit;
646 {return_value} = {c_basename}_impl({impl_arguments});
647 {return_conversion}
648
649exit:
650 {cleanup}
651 return return_value;
652}}
653""".rstrip().replace('{min}', min_o).replace('{max}', max_o)
654
655 elif positional:
656 # positional-only, but no option groups
657 # we only need one call to PyArg_ParseTuple
658
659 meth_varargs()
660
661 parser_definition = parser_prototype + """
662{{
663 PyObject *return_value = NULL;
664 {declarations}
665 {initializers}
666
667 if (!PyArg_ParseTuple(args,
668 "{format_units}:{name}",
669 {parse_arguments}))
670 goto exit;
671 {return_value} = {c_basename}_impl({impl_arguments});
672 {return_conversion}
673
674exit:
675 {cleanup}
676 return return_value;
677}}
678""".rstrip()
679
680 else:
681 # positional-or-keyword arguments
682 flags = "METH_VARARGS|METH_KEYWORDS"
683
684 parser_prototype = """
Larry Hastings31826802013-10-19 00:09:25 -0700685static PyObject *
Larry Hastingsebdcb502013-11-23 14:54:00 -0800686{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800687""".strip()
688
689 parser_definition = parser_prototype + """
Larry Hastings31826802013-10-19 00:09:25 -0700690{{
691 PyObject *return_value = NULL;
692 static char *_keywords[] = {{{keywords}, NULL}};
693 {declarations}
694 {initializers}
695
696 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
697 "{format_units}:{name}", _keywords,
698 {parse_arguments}))
699 goto exit;
700 {return_value} = {c_basename}_impl({impl_arguments});
701 {return_conversion}
702
Larry Hastingsbebf7352014-01-17 17:47:17 -0800703exit:
Larry Hastings31826802013-10-19 00:09:25 -0700704 {cleanup}
705 return return_value;
706}}
Larry Hastingsbebf7352014-01-17 17:47:17 -0800707""".rstrip()
Larry Hastings31826802013-10-19 00:09:25 -0700708
Larry Hastingsbebf7352014-01-17 17:47:17 -0800709 if f.methoddef_flags:
710 assert flags
711 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700712
Larry Hastingsbebf7352014-01-17 17:47:17 -0800713 methoddef_define = """
714#define {methoddef_name} \\
715 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
716""".strip().replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700717
Larry Hastingsbebf7352014-01-17 17:47:17 -0800718 # parser_prototype mustn't be None, but it could be an empty string.
719 assert parser_prototype is not None
720 assert not parser_prototype.endswith(';')
Larry Hastings31826802013-10-19 00:09:25 -0700721
Larry Hastingsbebf7352014-01-17 17:47:17 -0800722 if parser_prototype:
723 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700724
Larry Hastingsbebf7352014-01-17 17:47:17 -0800725 assert impl_definition
726 if impl_prototype is None:
727 impl_prototype = impl_definition + ";"
Larry Hastings31826802013-10-19 00:09:25 -0700728
Larry Hastingsbebf7352014-01-17 17:47:17 -0800729 # __new__ and __init__ don't need methoddefs
730 if f.kind in (METHOD_NEW, METHOD_INIT):
731 methoddef_define = ''
732
733 d = {
734 "docstring_prototype" : docstring_prototype,
735 "docstring_definition" : docstring_definition,
736 "impl_prototype" : impl_prototype,
737 "methoddef_define" : methoddef_define,
738 "parser_prototype" : parser_prototype,
739 "parser_definition" : parser_definition,
740 "impl_definition" : impl_definition,
741 }
742
743 d2 = {}
744 for name, value in d.items():
745 if value:
746 value = '\n' + value + '\n'
747 d2[name] = value
748 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700749
750 @staticmethod
751 def group_to_variable_name(group):
752 adjective = "left_" if group < 0 else "right_"
753 return "group_" + adjective + str(abs(group))
754
755 def render_option_group_parsing(self, f, template_dict):
756 # positional only, grouped, optional arguments!
757 # can be optional on the left or right.
758 # here's an example:
759 #
760 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
761 #
762 # Here group D are required, and all other groups are optional.
763 # (Group D's "group" is actually None.)
764 # We can figure out which sets of arguments we have based on
765 # how many arguments are in the tuple.
766 #
767 # Note that you need to count up on both sides. For example,
768 # you could have groups C+D, or C+D+E, or C+D+E+F.
769 #
770 # What if the number of arguments leads us to an ambiguous result?
771 # Clinic prefers groups on the left. So in the above example,
772 # five arguments would map to B+C, not C+D.
773
774 add, output = text_accumulator()
775 parameters = list(f.parameters.values())
776
777 groups = []
778 group = None
779 left = []
780 right = []
781 required = []
782 last = unspecified
783
784 for p in parameters:
785 group_id = p.group
786 if group_id != last:
787 last = group_id
788 group = []
789 if group_id < 0:
790 left.append(group)
791 elif group_id == 0:
792 group = required
793 else:
794 right.append(group)
795 group.append(p)
796
797 count_min = sys.maxsize
798 count_max = -1
799
Larry Hastings2a727912014-01-16 11:32:01 -0800800 add("switch (PyTuple_GET_SIZE(args)) {{\n")
Larry Hastings31826802013-10-19 00:09:25 -0700801 for subset in permute_optional_groups(left, required, right):
802 count = len(subset)
803 count_min = min(count_min, count)
804 count_max = max(count_max, count)
805
Larry Hastings583baa82014-01-12 08:49:30 -0800806 if count == 0:
807 add(""" case 0:
808 break;
809""")
810 continue
811
Larry Hastings31826802013-10-19 00:09:25 -0700812 group_ids = {p.group for p in subset} # eliminate duplicates
813 d = {}
814 d['count'] = count
815 d['name'] = f.name
816 d['groups'] = sorted(group_ids)
817 d['format_units'] = "".join(p.converter.format_unit for p in subset)
818
819 parse_arguments = []
820 for p in subset:
821 p.converter.parse_argument(parse_arguments)
822 d['parse_arguments'] = ", ".join(parse_arguments)
823
824 group_ids.discard(0)
825 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
826 lines = "\n".join(lines)
827
828 s = """
829 case {count}:
830 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
831 return NULL;
832 {group_booleans}
833 break;
834"""[1:]
835 s = linear_format(s, group_booleans=lines)
836 s = s.format_map(d)
837 add(s)
838
839 add(" default:\n")
840 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
841 add(s.format(f.full_name, count_min, count_max))
842 add(' return NULL;\n')
843 add("}}")
844 template_dict['option_group_parsing'] = output()
845
Larry Hastingsbebf7352014-01-17 17:47:17 -0800846 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -0700847 if not f:
848 return ""
849
850 add, output = text_accumulator()
851 data = CRenderData()
852
Larry Hastings31826802013-10-19 00:09:25 -0700853 parameters = list(f.parameters.values())
854 converters = [p.converter for p in parameters]
855
856 template_dict = {}
857
858 full_name = f.full_name
859 template_dict['full_name'] = full_name
860
861 name = full_name.rpartition('.')[2]
862 template_dict['name'] = name
863
Larry Hastings8666e652014-01-12 14:12:59 -0800864 if f.c_basename:
865 c_basename = f.c_basename
866 else:
867 fields = full_name.split(".")
868 if fields[-1] == '__new__':
869 fields.pop()
870 c_basename = "_".join(fields)
Larry Hastings31826802013-10-19 00:09:25 -0700871 template_dict['c_basename'] = c_basename
872
873 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
874 template_dict['methoddef_name'] = methoddef_name
875
876 template_dict['docstring'] = self.docstring_for_c_string(f)
877
Larry Hastings31826802013-10-19 00:09:25 -0700878 positional = has_option_groups = False
879
880 if parameters:
881 last_group = 0
882
883 for p in parameters:
884 c = p.converter
885
886 # insert group variable
887 group = p.group
888 if last_group != group:
889 last_group = group
890 if group:
891 group_name = self.group_to_variable_name(group)
892 data.impl_arguments.append(group_name)
893 data.declarations.append("int " + group_name + " = 0;")
894 data.impl_parameters.append("int " + group_name)
895 has_option_groups = True
896 c.render(p, data)
897
898 positional = parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY
Larry Hastings4a55fc52014-01-12 11:09:57 -0800899 if has_option_groups and (not positional):
900 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
Larry Hastings31826802013-10-19 00:09:25 -0700901
Larry Hastingsbebf7352014-01-17 17:47:17 -0800902 # HACK
903 # when we're METH_O, but have a custom
904 # return converter, we use
905 # "impl_parameters" for the parsing
906 # function because that works better.
907 # but that means we must supress actually
908 # declaring the impl's parameters as variables
909 # in the parsing function. but since it's
910 # METH_O, we only have one anyway, so we don't
911 # have any problem finding it.
912 default_return_converter = (not f.return_converter or
913 f.return_converter.type == 'PyObject *')
914 if (len(parameters) == 1 and
915 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
916 not converters[0].is_optional() and
917 isinstance(converters[0], object_converter) and
918 converters[0].format_unit == 'O' and
919 not default_return_converter):
920
921 data.declarations.pop(0)
922
Larry Hastingsebdcb502013-11-23 14:54:00 -0800923 # now insert our "self" (or whatever) parameters
924 # (we deliberately don't call render on self converters)
925 stock_self = self_converter('self', f)
926 template_dict['self_name'] = stock_self.name
927 template_dict['self_type'] = stock_self.type
928 data.impl_parameters.insert(0, f.self_converter.type + ("" if f.self_converter.type.endswith('*') else " ") + f.self_converter.name)
929 if f.self_converter.type != stock_self.type:
930 self_cast = '(' + f.self_converter.type + ')'
931 else:
932 self_cast = ''
933 data.impl_arguments.insert(0, self_cast + stock_self.name)
934
Larry Hastings31826802013-10-19 00:09:25 -0700935 f.return_converter.render(f, data)
936 template_dict['impl_return_type'] = f.return_converter.type
937
938 template_dict['declarations'] = "\n".join(data.declarations)
939 template_dict['initializers'] = "\n\n".join(data.initializers)
940 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
941 template_dict['format_units'] = ''.join(data.format_units)
942 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
943 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
944 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
945 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
946 template_dict['cleanup'] = "".join(data.cleanup)
947 template_dict['return_value'] = data.return_value
948
Larry Hastingsbebf7352014-01-17 17:47:17 -0800949 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -0700950 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800951
952 templates = self.output_templates(f)
953
954 for name, destination in clinic.field_destinations.items():
955 template = templates[name]
956 if has_option_groups:
957 template = linear_format(template,
958 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -0700959 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -0800960 declarations=template_dict['declarations'],
961 return_conversion=template_dict['return_conversion'],
962 initializers=template_dict['initializers'],
963 cleanup=template_dict['cleanup'],
964 )
Larry Hastings31826802013-10-19 00:09:25 -0700965
Larry Hastingsbebf7352014-01-17 17:47:17 -0800966 # Only generate the "exit:" label
967 # if we have any gotos
968 need_exit_label = "goto exit;" in template
969 template = linear_format(template,
970 exit_label="exit:" if need_exit_label else ''
971 )
Larry Hastings31826802013-10-19 00:09:25 -0700972
Larry Hastingsbebf7352014-01-17 17:47:17 -0800973 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -0700974
Larry Hastingsbebf7352014-01-17 17:47:17 -0800975 if clinic.line_prefix:
976 s = indent_all_lines(s, clinic.line_prefix)
977 if clinic.line_suffix:
978 s = suffix_all_lines(s, clinic.line_suffix)
979
980 destination.append(s)
981
982 return clinic.get_destination('block').dump()
983
Larry Hastings31826802013-10-19 00:09:25 -0700984
985
986@contextlib.contextmanager
987def OverrideStdioWith(stdout):
988 saved_stdout = sys.stdout
989 sys.stdout = stdout
990 try:
991 yield
992 finally:
993 assert sys.stdout is stdout
994 sys.stdout = saved_stdout
995
996
997def create_regex(before, after):
998 """Create an re object for matching marker lines."""
999 pattern = r'^{}(\w+){}$'
1000 return re.compile(pattern.format(re.escape(before), re.escape(after)))
1001
1002
1003class Block:
1004 r"""
1005 Represents a single block of text embedded in
1006 another file. If dsl_name is None, the block represents
1007 verbatim text, raw original text from the file, in
1008 which case "input" will be the only non-false member.
1009 If dsl_name is not None, the block represents a Clinic
1010 block.
1011
1012 input is always str, with embedded \n characters.
1013 input represents the original text from the file;
1014 if it's a Clinic block, it is the original text with
1015 the body_prefix and redundant leading whitespace removed.
1016
1017 dsl_name is either str or None. If str, it's the text
1018 found on the start line of the block between the square
1019 brackets.
1020
1021 signatures is either list or None. If it's a list,
1022 it may only contain clinic.Module, clinic.Class, and
1023 clinic.Function objects. At the moment it should
1024 contain at most one of each.
1025
1026 output is either str or None. If str, it's the output
1027 from this block, with embedded '\n' characters.
1028
1029 indent is either str or None. It's the leading whitespace
1030 that was found on every line of input. (If body_prefix is
1031 not empty, this is the indent *after* removing the
1032 body_prefix.)
1033
1034 preindent is either str or None. It's the whitespace that
1035 was found in front of every line of input *before* the
1036 "body_prefix" (see the Language object). If body_prefix
1037 is empty, preindent must always be empty too.
1038
1039 To illustrate indent and preindent: Assume that '_'
1040 represents whitespace. If the block processed was in a
1041 Python file, and looked like this:
1042 ____#/*[python]
1043 ____#__for a in range(20):
1044 ____#____print(a)
1045 ____#[python]*/
1046 "preindent" would be "____" and "indent" would be "__".
1047
1048 """
1049 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1050 assert isinstance(input, str)
1051 self.input = input
1052 self.dsl_name = dsl_name
1053 self.signatures = signatures or []
1054 self.output = output
1055 self.indent = indent
1056 self.preindent = preindent
1057
1058
1059class BlockParser:
1060 """
1061 Block-oriented parser for Argument Clinic.
1062 Iterator, yields Block objects.
1063 """
1064
1065 def __init__(self, input, language, *, verify=True):
1066 """
1067 "input" should be a str object
1068 with embedded \n characters.
1069
1070 "language" should be a Language object.
1071 """
1072 language.validate()
1073
1074 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1075 self.block_start_line_number = self.line_number = 0
1076
1077 self.language = language
1078 before, _, after = language.start_line.partition('{dsl_name}')
1079 assert _ == '{dsl_name}'
1080 self.start_re = create_regex(before, after)
1081 self.verify = verify
1082 self.last_checksum_re = None
1083 self.last_dsl_name = None
1084 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001085 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001086
1087 def __iter__(self):
1088 return self
1089
1090 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001091 while True:
1092 if not self.input:
1093 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001094
Larry Hastingsbebf7352014-01-17 17:47:17 -08001095 if self.dsl_name:
1096 return_value = self.parse_clinic_block(self.dsl_name)
1097 self.dsl_name = None
1098 self.first_block = False
1099 return return_value
1100 block = self.parse_verbatim_block()
1101 if self.first_block and not block.input:
1102 continue
1103 self.first_block = False
1104 return block
1105
Larry Hastings31826802013-10-19 00:09:25 -07001106
1107 def is_start_line(self, line):
1108 match = self.start_re.match(line.lstrip())
1109 return match.group(1) if match else None
1110
1111 def _line(self):
1112 self.line_number += 1
1113 return self.input.pop()
1114
1115 def parse_verbatim_block(self):
1116 add, output = text_accumulator()
1117 self.block_start_line_number = self.line_number
1118
1119 while self.input:
1120 line = self._line()
1121 dsl_name = self.is_start_line(line)
1122 if dsl_name:
1123 self.dsl_name = dsl_name
1124 break
1125 add(line)
1126
1127 return Block(output())
1128
1129 def parse_clinic_block(self, dsl_name):
1130 input_add, input_output = text_accumulator()
1131 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001132 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001133 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1134
Larry Hastings90261132014-01-07 12:21:08 -08001135 def is_stop_line(line):
1136 # make sure to recognize stop line even if it
1137 # doesn't end with EOL (it could be the very end of the file)
1138 if not line.startswith(stop_line):
1139 return False
1140 remainder = line[len(stop_line):]
1141 return (not remainder) or remainder.isspace()
1142
Larry Hastings31826802013-10-19 00:09:25 -07001143 # consume body of program
1144 while self.input:
1145 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001146 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001147 break
1148 if body_prefix:
1149 line = line.lstrip()
1150 assert line.startswith(body_prefix)
1151 line = line[len(body_prefix):]
1152 input_add(line)
1153
1154 # consume output and checksum line, if present.
1155 if self.last_dsl_name == dsl_name:
1156 checksum_re = self.last_checksum_re
1157 else:
1158 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, checksum='{checksum}').partition('{checksum}')
1159 assert _ == '{checksum}'
1160 checksum_re = create_regex(before, after)
1161 self.last_dsl_name = dsl_name
1162 self.last_checksum_re = checksum_re
1163
1164 # scan forward for checksum line
1165 output_add, output_output = text_accumulator()
1166 checksum = None
1167 while self.input:
1168 line = self._line()
1169 match = checksum_re.match(line.lstrip())
1170 checksum = match.group(1) if match else None
1171 if checksum:
1172 break
1173 output_add(line)
1174 if self.is_start_line(line):
1175 break
1176
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001177 output = output_output()
Larry Hastings31826802013-10-19 00:09:25 -07001178 if checksum:
Larry Hastings31826802013-10-19 00:09:25 -07001179 if self.verify:
1180 computed = compute_checksum(output)
1181 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001182 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1183 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001184 "the end marker,\n"
1185 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001186 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001187 else:
1188 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001189 output_lines = output.splitlines(keepends=True)
1190 self.line_number -= len(output_lines)
1191 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001192 output = None
1193
1194 return Block(input_output(), dsl_name, output=output)
1195
1196
1197class BlockPrinter:
1198
1199 def __init__(self, language, f=None):
1200 self.language = language
1201 self.f = f or io.StringIO()
1202
1203 def print_block(self, block):
1204 input = block.input
1205 output = block.output
1206 dsl_name = block.dsl_name
1207 write = self.f.write
1208
Larry Hastings31826802013-10-19 00:09:25 -07001209 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1210
1211 if not dsl_name:
1212 write(input)
1213 return
1214
1215 write(self.language.start_line.format(dsl_name=dsl_name))
1216 write("\n")
1217
1218 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1219 if not body_prefix:
1220 write(input)
1221 else:
1222 for line in input.split('\n'):
1223 write(body_prefix)
1224 write(line)
1225 write("\n")
1226
1227 write(self.language.stop_line.format(dsl_name=dsl_name))
1228 write("\n")
1229
Larry Hastingsbebf7352014-01-17 17:47:17 -08001230 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001231 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001232 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001233 output += '\n'
1234 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001235
1236 write(self.language.checksum_line.format(dsl_name=dsl_name, checksum=compute_checksum(output)))
1237 write("\n")
1238
Larry Hastingsbebf7352014-01-17 17:47:17 -08001239 def write(self, text):
1240 self.f.write(text)
1241
1242
1243class Destination:
1244 def __init__(self, name, type, clinic, *args):
1245 self.name = name
1246 self.type = type
1247 self.clinic = clinic
1248 valid_types = ('buffer', 'file', 'suppress', 'two-pass')
1249 if type not in valid_types:
1250 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1251 extra_arguments = 1 if type == "file" else 0
1252 if len(args) < extra_arguments:
1253 fail("Not enough arguments for destination " + name + " new " + type)
1254 if len(args) > extra_arguments:
1255 fail("Too many arguments for destination " + name + " new " + type)
1256 if type =='file':
1257 d = {}
1258 d['filename'] = filename = clinic.filename
1259 d['basename'], d['extension'] = os.path.splitext(filename)
1260 self.filename = args[0].format_map(d)
1261 if type == 'two-pass':
1262 self.id = None
1263
1264 self.text, self.append, self._dump = _text_accumulator()
1265
1266 def __repr__(self):
1267 if self.type == 'file':
1268 file_repr = " " + repr(self.filename)
1269 else:
1270 file_repr = ''
1271 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1272
1273 def clear(self):
1274 if self.type != 'buffer':
1275 fail("Can't clear destination" + self.name + " , it's not of type buffer")
1276 self.text.clear()
1277
1278 def dump(self):
1279 if self.type == 'two-pass':
1280 if self.id is None:
1281 self.id = str(uuid.uuid4())
1282 return self.id
1283 fail("You can only dump a two-pass buffer exactly once!")
1284 return self._dump()
1285
Larry Hastings31826802013-10-19 00:09:25 -07001286
1287# maps strings to Language objects.
1288# "languages" maps the name of the language ("C", "Python").
1289# "extensions" maps the file extension ("c", "py").
1290languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001291extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1292extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001293
1294
1295# maps strings to callables.
1296# these callables must be of the form:
1297# def foo(name, default, *, ...)
1298# The callable may have any number of keyword-only parameters.
1299# The callable must return a CConverter object.
1300# The callable should not call builtins.print.
1301converters = {}
1302
1303# maps strings to callables.
1304# these callables follow the same rules as those for "converters" above.
1305# note however that they will never be called with keyword-only parameters.
1306legacy_converters = {}
1307
1308
1309# maps strings to callables.
1310# these callables must be of the form:
1311# def foo(*, ...)
1312# The callable may have any number of keyword-only parameters.
1313# The callable must return a CConverter object.
1314# The callable should not call builtins.print.
1315return_converters = {}
1316
1317class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001318
1319 presets_text = """
1320preset original
1321everything block
1322docstring_prototype suppress
1323parser_prototype suppress
1324
1325preset file
1326everything file
1327docstring_prototype suppress
1328parser_prototype suppress
1329impl_definition block
1330
1331preset buffer
1332everything buffer
1333docstring_prototype suppress
1334impl_prototype suppress
1335parser_prototype suppress
1336impl_definition block
1337
1338preset partial-buffer
1339everything buffer
1340docstring_prototype block
1341impl_prototype suppress
1342methoddef_define block
1343parser_prototype block
1344impl_definition block
1345
1346preset two-pass
1347everything buffer
1348docstring_prototype two-pass
1349impl_prototype suppress
1350methoddef_define two-pass
1351parser_prototype two-pass
1352impl_definition block
1353
1354"""
1355
Larry Hastings31826802013-10-19 00:09:25 -07001356 def __init__(self, language, printer=None, *, verify=True, filename=None):
1357 # maps strings to Parser objects.
1358 # (instantiated from the "parsers" global.)
1359 self.parsers = {}
1360 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001361 if printer:
1362 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001363 self.printer = printer or BlockPrinter(language)
1364 self.verify = verify
1365 self.filename = filename
1366 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001367 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001368 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001369
Larry Hastingsbebf7352014-01-17 17:47:17 -08001370 self.line_prefix = self.line_suffix = ''
1371
1372 self.destinations = {}
1373 self.add_destination("block", "buffer")
1374 self.add_destination("suppress", "suppress")
1375 self.add_destination("buffer", "buffer")
1376 self.add_destination("two-pass", "two-pass")
1377 if filename:
1378 self.add_destination("file", "file", "{basename}.clinic{extension}")
1379
1380 d = self.destinations.get
1381 self.field_destinations = collections.OrderedDict((
1382 ('docstring_prototype', d('suppress')),
1383 ('docstring_definition', d('block')),
1384 ('methoddef_define', d('block')),
1385 ('impl_prototype', d('block')),
1386 ('parser_prototype', d('suppress')),
1387 ('parser_definition', d('block')),
1388 ('impl_definition', d('block')),
1389 ))
1390
1391 self.field_destinations_stack = []
1392
1393 self.presets = {}
1394 preset = None
1395 for line in self.presets_text.strip().split('\n'):
1396 line = line.strip()
1397 if not line:
1398 continue
1399 name, value = line.split()
1400 if name == 'preset':
1401 self.presets[value] = preset = collections.OrderedDict()
1402 continue
1403
1404 destination = self.get_destination(value)
1405
1406 if name == 'everything':
1407 for name in self.field_destinations:
1408 preset[name] = destination
1409 continue
1410
1411 assert name in self.field_destinations
1412 preset[name] = destination
1413
Larry Hastings31826802013-10-19 00:09:25 -07001414 global clinic
1415 clinic = self
1416
Larry Hastingsbebf7352014-01-17 17:47:17 -08001417 def get_destination(self, name, default=unspecified):
1418 d = self.destinations.get(name)
1419 if not d:
1420 if default is not unspecified:
1421 return default
1422 fail("Destination does not exist: " + repr(name))
1423 return d
1424
1425 def add_destination(self, name, type, *args):
1426 if name in self.destinations:
1427 fail("Destination already exists: " + repr(name))
1428 self.destinations[name] = Destination(name, type, self, *args)
1429
Larry Hastings31826802013-10-19 00:09:25 -07001430 def parse(self, input):
1431 printer = self.printer
1432 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1433 for block in self.block_parser:
1434 dsl_name = block.dsl_name
1435 if dsl_name:
1436 if dsl_name not in self.parsers:
1437 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1438 self.parsers[dsl_name] = parsers[dsl_name](self)
1439 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001440 try:
1441 parser.parse(block)
1442 except Exception:
1443 fail('Exception raised during parsing:\n' +
1444 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001445 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001446
1447 second_pass_replacements = {}
1448
1449 for name, destination in self.destinations.items():
1450 if destination.type == 'suppress':
1451 continue
1452 output = destination._dump()
1453
1454 if destination.type == 'two-pass':
1455 if destination.id:
1456 second_pass_replacements[destination.id] = output
1457 elif output:
1458 fail("Two-pass buffer " + repr(name) + " not empty at end of file!")
1459 continue
1460
1461 if output:
1462
1463 block = Block("", dsl_name="clinic", output=output)
1464
1465 if destination.type == 'buffer':
1466 block.input = "dump " + name + "\n"
1467 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1468 printer.write("\n")
1469 printer.print_block(block)
1470 continue
1471
1472 if destination.type == 'file':
1473 try:
1474 with open(destination.filename, "rt") as f:
1475 parser_2 = BlockParser(f.read(), language=self.language)
1476 blocks = list(parser_2)
1477 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1478 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
1479 except FileNotFoundError:
1480 pass
1481
1482 block.input = 'preserve\n'
1483 printer_2 = BlockPrinter(self.language)
1484 printer_2.print_block(block)
1485 with open(destination.filename, "wt") as f:
1486 f.write(printer_2.f.getvalue())
1487 continue
1488 text = printer.f.getvalue()
1489
1490 if second_pass_replacements:
1491 printer_2 = BlockPrinter(self.language)
1492 parser_2 = BlockParser(text, self.language)
1493 changed = False
1494 for block in parser_2:
1495 if block.dsl_name:
1496 for id, replacement in second_pass_replacements.items():
1497 if id in block.output:
1498 changed = True
1499 block.output = block.output.replace(id, replacement)
1500 printer_2.print_block(block)
1501 if changed:
1502 text = printer_2.f.getvalue()
1503
1504 return text
1505
Larry Hastings31826802013-10-19 00:09:25 -07001506
1507 def _module_and_class(self, fields):
1508 """
1509 fields should be an iterable of field names.
1510 returns a tuple of (module, class).
1511 the module object could actually be self (a clinic object).
1512 this function is only ever used to find the parent of where
1513 a new class/module should go.
1514 """
1515 in_classes = False
1516 parent = module = self
1517 cls = None
1518 so_far = []
1519
1520 for field in fields:
1521 so_far.append(field)
1522 if not in_classes:
1523 child = parent.modules.get(field)
1524 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001525 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001526 continue
1527 in_classes = True
1528 if not hasattr(parent, 'classes'):
1529 return module, cls
1530 child = parent.classes.get(field)
1531 if not child:
1532 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1533 cls = parent = child
1534
1535 return module, cls
1536
1537
1538def parse_file(filename, *, verify=True, output=None, encoding='utf-8'):
1539 extension = os.path.splitext(filename)[1][1:]
1540 if not extension:
1541 fail("Can't extract file type for file " + repr(filename))
1542
1543 try:
1544 language = extensions[extension]()
1545 except KeyError:
1546 fail("Can't identify file type for file " + repr(filename))
1547
1548 clinic = Clinic(language, verify=verify, filename=filename)
1549
1550 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001551 raw = f.read()
1552
1553 cooked = clinic.parse(raw)
1554 if cooked == raw:
1555 return
Larry Hastings31826802013-10-19 00:09:25 -07001556
1557 directory = os.path.dirname(filename) or '.'
1558
1559 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001560 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001561 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1562 with open(tmpfilename, "wb") as f:
1563 f.write(bytes)
1564 os.replace(tmpfilename, output or filename)
1565
1566
1567def compute_checksum(input):
1568 input = input or ''
1569 return hashlib.sha1(input.encode('utf-8')).hexdigest()
1570
1571
1572
1573
1574class PythonParser:
1575 def __init__(self, clinic):
1576 pass
1577
1578 def parse(self, block):
1579 s = io.StringIO()
1580 with OverrideStdioWith(s):
1581 exec(block.input)
1582 block.output = s.getvalue()
1583
1584
1585class Module:
1586 def __init__(self, name, module=None):
1587 self.name = name
1588 self.module = self.parent = module
1589
1590 self.modules = collections.OrderedDict()
1591 self.classes = collections.OrderedDict()
1592 self.functions = []
1593
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001594 def __repr__(self):
1595 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1596
Larry Hastings31826802013-10-19 00:09:25 -07001597class Class:
1598 def __init__(self, name, module=None, cls=None):
1599 self.name = name
1600 self.module = module
1601 self.cls = cls
1602 self.parent = cls or module
1603
1604 self.classes = collections.OrderedDict()
1605 self.functions = []
1606
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001607 def __repr__(self):
1608 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1609
Larry Hastings8666e652014-01-12 14:12:59 -08001610unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001611
Larry Hastings8666e652014-01-12 14:12:59 -08001612__abs__
1613__add__
1614__and__
1615__bytes__
1616__call__
1617__complex__
1618__delitem__
1619__divmod__
1620__eq__
1621__float__
1622__floordiv__
1623__ge__
1624__getattr__
1625__getattribute__
1626__getitem__
1627__gt__
1628__hash__
1629__iadd__
1630__iand__
1631__idivmod__
1632__ifloordiv__
1633__ilshift__
1634__imod__
1635__imul__
1636__index__
1637__int__
1638__invert__
1639__ior__
1640__ipow__
1641__irshift__
1642__isub__
1643__iter__
1644__itruediv__
1645__ixor__
1646__le__
1647__len__
1648__lshift__
1649__lt__
1650__mod__
1651__mul__
1652__neg__
1653__new__
1654__next__
1655__or__
1656__pos__
1657__pow__
1658__radd__
1659__rand__
1660__rdivmod__
1661__repr__
1662__rfloordiv__
1663__rlshift__
1664__rmod__
1665__rmul__
1666__ror__
1667__round__
1668__rpow__
1669__rrshift__
1670__rshift__
1671__rsub__
1672__rtruediv__
1673__rxor__
1674__setattr__
1675__setitem__
1676__str__
1677__sub__
1678__truediv__
1679__xor__
1680
1681""".strip().split())
1682
1683
1684INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = range(6)
Larry Hastings31826802013-10-19 00:09:25 -07001685
1686class Function:
1687 """
1688 Mutable duck type for inspect.Function.
1689
1690 docstring - a str containing
1691 * embedded line breaks
1692 * text outdented to the left margin
1693 * no trailing whitespace.
1694 It will always be true that
1695 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
1696 """
1697
1698 def __init__(self, parameters=None, *, name,
1699 module, cls=None, c_basename=None,
1700 full_name=None,
1701 return_converter, return_annotation=_empty,
1702 docstring=None, kind=CALLABLE, coexist=False):
1703 self.parameters = parameters or collections.OrderedDict()
1704 self.return_annotation = return_annotation
1705 self.name = name
1706 self.full_name = full_name
1707 self.module = module
1708 self.cls = cls
1709 self.parent = cls or module
1710 self.c_basename = c_basename
1711 self.return_converter = return_converter
1712 self.docstring = docstring or ''
1713 self.kind = kind
1714 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08001715 self.self_converter = None
1716
1717 @property
1718 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08001719 if self.kind in (METHOD_INIT, METHOD_NEW):
1720 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001721 flags = []
1722 if self.kind == CLASS_METHOD:
1723 flags.append('METH_CLASS')
1724 elif self.kind == STATIC_METHOD:
1725 flags.append('METH_STATIC')
1726 else:
1727 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
1728 if self.coexist:
1729 flags.append('METH_COEXIST')
1730 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07001731
1732 def __repr__(self):
1733 return '<clinic.Function ' + self.name + '>'
1734
1735
1736class Parameter:
1737 """
1738 Mutable duck type of inspect.Parameter.
1739 """
1740
1741 def __init__(self, name, kind, *, default=_empty,
1742 function, converter, annotation=_empty,
1743 docstring=None, group=0):
1744 self.name = name
1745 self.kind = kind
1746 self.default = default
1747 self.function = function
1748 self.converter = converter
1749 self.annotation = annotation
1750 self.docstring = docstring or ''
1751 self.group = group
1752
1753 def __repr__(self):
1754 return '<clinic.Parameter ' + self.name + '>'
1755
1756 def is_keyword_only(self):
1757 return self.kind == inspect.Parameter.KEYWORD_ONLY
1758
Larry Hastings31826802013-10-19 00:09:25 -07001759
Larry Hastings31826802013-10-19 00:09:25 -07001760
1761def add_c_converter(f, name=None):
1762 if not name:
1763 name = f.__name__
1764 if not name.endswith('_converter'):
1765 return f
1766 name = name[:-len('_converter')]
1767 converters[name] = f
1768 return f
1769
1770def add_default_legacy_c_converter(cls):
1771 # automatically add converter for default format unit
1772 # (but without stomping on the existing one if it's already
1773 # set, in case you subclass)
1774 if ((cls.format_unit != 'O&') and
1775 (cls.format_unit not in legacy_converters)):
1776 legacy_converters[cls.format_unit] = cls
1777 return cls
1778
1779def add_legacy_c_converter(format_unit, **kwargs):
1780 """
1781 Adds a legacy converter.
1782 """
1783 def closure(f):
1784 if not kwargs:
1785 added_f = f
1786 else:
1787 added_f = functools.partial(f, **kwargs)
1788 legacy_converters[format_unit] = added_f
1789 return f
1790 return closure
1791
1792class CConverterAutoRegister(type):
1793 def __init__(cls, name, bases, classdict):
1794 add_c_converter(cls)
1795 add_default_legacy_c_converter(cls)
1796
1797class CConverter(metaclass=CConverterAutoRegister):
1798 """
1799 For the init function, self, name, function, and default
1800 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08001801 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07001802 """
1803
Larry Hastings78cf85c2014-01-04 12:44:57 -08001804 # The C type to use for this variable.
1805 # 'type' should be a Python string specifying the type, e.g. "int".
1806 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07001807 type = None
Larry Hastings31826802013-10-19 00:09:25 -07001808
1809 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08001810 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08001811 # Or the magic value "unknown" if this value is a cannot be evaluated
1812 # at Argument-Clinic-preprocessing time (but is presumed to be valid
1813 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07001814 default = unspecified
1815
Larry Hastings4a55fc52014-01-12 11:09:57 -08001816 # If not None, default must be isinstance() of this type.
1817 # (You can also specify a tuple of types.)
1818 default_type = None
1819
Larry Hastings31826802013-10-19 00:09:25 -07001820 # "default" converted into a C value, as a string.
1821 # Or None if there is no default.
1822 c_default = None
1823
Larry Hastings2a727912014-01-16 11:32:01 -08001824 # "default" converted into a Python value, as a string.
1825 # Or None if there is no default.
1826 py_default = None
1827
Larry Hastingsabc716b2013-11-20 09:13:52 -08001828 # The default value used to initialize the C variable when
1829 # there is no default, but not specifying a default may
1830 # result in an "uninitialized variable" warning. This can
1831 # easily happen when using option groups--although
1832 # properly-written code won't actually use the variable,
1833 # the variable does get passed in to the _impl. (Ah, if
1834 # only dataflow analysis could inline the static function!)
1835 #
1836 # This value is specified as a string.
1837 # Every non-abstract subclass should supply a valid value.
1838 c_ignored_default = 'NULL'
1839
Larry Hastings31826802013-10-19 00:09:25 -07001840 # The C converter *function* to be used, if any.
1841 # (If this is not None, format_unit must be 'O&'.)
1842 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001843
Larry Hastings78cf85c2014-01-04 12:44:57 -08001844 # Should Argument Clinic add a '&' before the name of
1845 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07001846 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08001847
1848 # Should Argument Clinic add a '&' before the name of
1849 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07001850 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08001851
1852 #############################################################
1853 #############################################################
1854 ## You shouldn't need to read anything below this point to ##
1855 ## write your own converter functions. ##
1856 #############################################################
1857 #############################################################
1858
1859 # The "format unit" to specify for this variable when
1860 # parsing arguments using PyArg_ParseTuple (AndKeywords).
1861 # Custom converters should always use the default value of 'O&'.
1862 format_unit = 'O&'
1863
1864 # What encoding do we want for this variable? Only used
1865 # by format units starting with 'e'.
1866 encoding = None
1867
Larry Hastings77561cc2014-01-07 12:13:13 -08001868 # Should this object be required to be a subclass of a specific type?
1869 # If not None, should be a string representing a pointer to a
1870 # PyTypeObject (e.g. "&PyUnicode_Type").
1871 # Only used by the 'O!' format unit (and the "object" converter).
1872 subclass_of = None
1873
Larry Hastings78cf85c2014-01-04 12:44:57 -08001874 # Do we want an adjacent '_length' variable for this variable?
1875 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07001876 length = False
1877
Larry Hastings2a727912014-01-16 11:32:01 -08001878 def __init__(self, name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs):
Larry Hastings31826802013-10-19 00:09:25 -07001879 self.function = function
1880 self.name = name
1881
1882 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08001883 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08001884 if isinstance(self.default_type, type):
1885 types_str = self.default_type.__name__
1886 else:
1887 types_str = ', '.join((cls.__name__ for cls in self.default_type))
1888 fail("{}: default value {!r} for field {} is not of type {}".format(
1889 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07001890 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08001891
1892 self.c_default = c_default
1893 self.py_default = py_default
1894
Larry Hastings31826802013-10-19 00:09:25 -07001895 if annotation != unspecified:
1896 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings31826802013-10-19 00:09:25 -07001897 self.converter_init(**kwargs)
1898
1899 def converter_init(self):
1900 pass
1901
1902 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08001903 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07001904
1905 def render(self, parameter, data):
1906 """
1907 parameter is a clinic.Parameter instance.
1908 data is a CRenderData instance.
1909 """
Larry Hastingsabc716b2013-11-20 09:13:52 -08001910 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08001911 original_name = self.name
1912 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07001913
1914 # declarations
1915 d = self.declaration()
1916 data.declarations.append(d)
1917
1918 # initializers
1919 initializers = self.initialize()
1920 if initializers:
1921 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
1922
1923 # impl_arguments
1924 s = ("&" if self.impl_by_reference else "") + name
1925 data.impl_arguments.append(s)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001926 if self.length:
1927 data.impl_arguments.append(self.length_name())
Larry Hastings31826802013-10-19 00:09:25 -07001928
1929 # keywords
Larry Hastings90261132014-01-07 12:21:08 -08001930 data.keywords.append(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07001931
1932 # format_units
1933 if self.is_optional() and '|' not in data.format_units:
1934 data.format_units.append('|')
1935 if parameter.is_keyword_only() and '$' not in data.format_units:
1936 data.format_units.append('$')
1937 data.format_units.append(self.format_unit)
1938
1939 # parse_arguments
1940 self.parse_argument(data.parse_arguments)
1941
1942 # impl_parameters
1943 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
Larry Hastingsebdcb502013-11-23 14:54:00 -08001944 if self.length:
1945 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
Larry Hastings31826802013-10-19 00:09:25 -07001946
1947 # cleanup
1948 cleanup = self.cleanup()
1949 if cleanup:
1950 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
1951
Larry Hastingsebdcb502013-11-23 14:54:00 -08001952 def length_name(self):
1953 """Computes the name of the associated "length" variable."""
1954 if not self.length:
1955 return None
1956 return ensure_legal_c_identifier(self.name) + "_length"
1957
Larry Hastings31826802013-10-19 00:09:25 -07001958 # Why is this one broken out separately?
1959 # For "positional-only" function parsing,
1960 # which generates a bunch of PyArg_ParseTuple calls.
1961 def parse_argument(self, list):
1962 assert not (self.converter and self.encoding)
1963 if self.format_unit == 'O&':
1964 assert self.converter
1965 list.append(self.converter)
1966
1967 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08001968 list.append(c_repr(self.encoding))
1969 elif self.subclass_of:
1970 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07001971
Larry Hastingsebdcb502013-11-23 14:54:00 -08001972 legal_name = ensure_legal_c_identifier(self.name)
1973 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07001974 list.append(s)
1975
Larry Hastingsebdcb502013-11-23 14:54:00 -08001976 if self.length:
1977 list.append("&" + self.length_name())
1978
Larry Hastings31826802013-10-19 00:09:25 -07001979 #
1980 # All the functions after here are intended as extension points.
1981 #
1982
1983 def simple_declaration(self, by_reference=False):
1984 """
1985 Computes the basic declaration of the variable.
1986 Used in computing the prototype declaration and the
1987 variable declaration.
1988 """
1989 prototype = [self.type]
1990 if by_reference or not self.type.endswith('*'):
1991 prototype.append(" ")
1992 if by_reference:
1993 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07001994 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07001995 return "".join(prototype)
1996
1997 def declaration(self):
1998 """
1999 The C statement to declare this variable.
2000 """
2001 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002002 default = self.c_default
2003 if not default and self.parameter.group:
2004 default = self.c_ignored_default
2005 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002006 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002007 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002008 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002009 if self.length:
2010 declaration.append('\nPy_ssize_clean_t ')
2011 declaration.append(self.length_name())
2012 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002013 s = "".join(declaration)
2014 # double up curly-braces, this string will be used
2015 # as part of a format_map() template later
2016 s = s.replace("{", "{{")
2017 s = s.replace("}", "}}")
2018 return s
Larry Hastings31826802013-10-19 00:09:25 -07002019
2020 def initialize(self):
2021 """
2022 The C statements required to set up this variable before parsing.
2023 Returns a string containing this code indented at column 0.
2024 If no initialization is necessary, returns an empty string.
2025 """
2026 return ""
2027
2028 def cleanup(self):
2029 """
2030 The C statements required to clean up after this variable.
2031 Returns a string containing this code indented at column 0.
2032 If no cleanup is necessary, returns an empty string.
2033 """
2034 return ""
2035
2036
2037class bool_converter(CConverter):
2038 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002039 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002040 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002041 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002042
2043 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002044 if self.default is not unspecified:
2045 self.default = bool(self.default)
2046 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002047
2048class char_converter(CConverter):
2049 type = 'char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002050 default_type = str
Larry Hastings31826802013-10-19 00:09:25 -07002051 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002052 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002053
Larry Hastings4a55fc52014-01-12 11:09:57 -08002054 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002055 if isinstance(self.default, str) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002056 fail("char_converter: illegal default value " + repr(self.default))
2057
2058
Larry Hastings31826802013-10-19 00:09:25 -07002059@add_legacy_c_converter('B', bitwise=True)
2060class byte_converter(CConverter):
2061 type = 'byte'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002062 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002063 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002064 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002065
2066 def converter_init(self, *, bitwise=False):
2067 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002068 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002069
2070class short_converter(CConverter):
2071 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002072 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002073 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002074 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002075
2076class unsigned_short_converter(CConverter):
2077 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002078 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002079 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002080 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002081
2082 def converter_init(self, *, bitwise=False):
2083 if not bitwise:
2084 fail("Unsigned shorts must be bitwise (for now).")
2085
Larry Hastingsebdcb502013-11-23 14:54:00 -08002086@add_legacy_c_converter('C', types='str')
Larry Hastings31826802013-10-19 00:09:25 -07002087class int_converter(CConverter):
2088 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002089 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002090 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002091 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002092
Larry Hastingsebdcb502013-11-23 14:54:00 -08002093 def converter_init(self, *, types='int'):
2094 if types == 'str':
2095 self.format_unit = 'C'
2096 elif types != 'int':
2097 fail("int_converter: illegal 'types' argument")
Larry Hastings31826802013-10-19 00:09:25 -07002098
2099class unsigned_int_converter(CConverter):
2100 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002101 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002102 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002103 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002104
2105 def converter_init(self, *, bitwise=False):
2106 if not bitwise:
2107 fail("Unsigned ints must be bitwise (for now).")
2108
2109class long_converter(CConverter):
2110 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002111 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002112 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002113 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002114
2115class unsigned_long_converter(CConverter):
2116 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002117 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002118 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002119 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002120
2121 def converter_init(self, *, bitwise=False):
2122 if not bitwise:
2123 fail("Unsigned longs must be bitwise (for now).")
2124
2125class PY_LONG_LONG_converter(CConverter):
2126 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002127 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002128 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002129 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002130
2131class unsigned_PY_LONG_LONG_converter(CConverter):
2132 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002133 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002134 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002135 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002136
2137 def converter_init(self, *, bitwise=False):
2138 if not bitwise:
2139 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2140
2141class Py_ssize_t_converter(CConverter):
2142 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002143 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002144 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002145 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002146
2147
2148class float_converter(CConverter):
2149 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002150 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002151 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002152 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002153
2154class double_converter(CConverter):
2155 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002156 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002157 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002158 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002159
2160
2161class Py_complex_converter(CConverter):
2162 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002163 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002164 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002165 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002166
2167
2168class object_converter(CConverter):
2169 type = 'PyObject *'
2170 format_unit = 'O'
2171
Larry Hastings4a55fc52014-01-12 11:09:57 -08002172 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2173 if converter:
2174 if subclass_of:
2175 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2176 self.format_unit = 'O&'
2177 self.converter = converter
2178 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002179 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002180 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002181
Larry Hastings77561cc2014-01-07 12:13:13 -08002182 if type is not None:
2183 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002184
2185
Larry Hastingsebdcb502013-11-23 14:54:00 -08002186@add_legacy_c_converter('s#', length=True)
Larry Hastings2a727912014-01-16 11:32:01 -08002187@add_legacy_c_converter('y', types="bytes")
2188@add_legacy_c_converter('y#', types="bytes", length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002189@add_legacy_c_converter('z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002190@add_legacy_c_converter('z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002191class str_converter(CConverter):
2192 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002193 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002194 format_unit = 's'
2195
Larry Hastingsebdcb502013-11-23 14:54:00 -08002196 def converter_init(self, *, encoding=None, types="str",
2197 length=False, nullable=False, zeroes=False):
2198
2199 types = set(types.strip().split())
2200 bytes_type = set(("bytes",))
2201 str_type = set(("str",))
2202 all_3_type = set(("bytearray",)) | bytes_type | str_type
2203 is_bytes = types == bytes_type
2204 is_str = types == str_type
2205 is_all_3 = types == all_3_type
2206
2207 self.length = bool(length)
2208 format_unit = None
2209
2210 if encoding:
2211 self.encoding = encoding
2212
2213 if is_str and not (length or zeroes or nullable):
2214 format_unit = 'es'
2215 elif is_all_3 and not (length or zeroes or nullable):
2216 format_unit = 'et'
2217 elif is_str and length and zeroes and not nullable:
2218 format_unit = 'es#'
2219 elif is_all_3 and length and not (nullable or zeroes):
2220 format_unit = 'et#'
2221
2222 if format_unit.endswith('#'):
Larry Hastings2f9a9aa2013-11-24 04:23:35 -08002223 print("Warning: code using format unit ", repr(format_unit), "probably doesn't work properly.")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002224 # TODO set pointer to NULL
2225 # TODO add cleanup for buffer
2226 pass
2227
2228 else:
2229 if zeroes:
2230 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
2231
2232 if is_bytes and not (nullable or length):
2233 format_unit = 'y'
2234 elif is_bytes and length and not nullable:
2235 format_unit = 'y#'
2236 elif is_str and not (nullable or length):
2237 format_unit = 's'
2238 elif is_str and length and not nullable:
2239 format_unit = 's#'
2240 elif is_str and nullable and not length:
2241 format_unit = 'z'
2242 elif is_str and nullable and length:
2243 format_unit = 'z#'
2244
2245 if not format_unit:
2246 fail("str_converter: illegal combination of arguments")
2247 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002248
2249
2250class PyBytesObject_converter(CConverter):
2251 type = 'PyBytesObject *'
2252 format_unit = 'S'
2253
2254class PyByteArrayObject_converter(CConverter):
2255 type = 'PyByteArrayObject *'
2256 format_unit = 'Y'
2257
2258class unicode_converter(CConverter):
2259 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002260 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002261 format_unit = 'U'
2262
Larry Hastingsebdcb502013-11-23 14:54:00 -08002263@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002264@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002265@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002266class Py_UNICODE_converter(CConverter):
2267 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002268 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002269 format_unit = 'u'
2270
Larry Hastingsebdcb502013-11-23 14:54:00 -08002271 def converter_init(self, *, nullable=False, length=False):
2272 format_unit = 'Z' if nullable else 'u'
2273 if length:
2274 format_unit += '#'
2275 self.length = True
2276 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002277
Larry Hastingsebdcb502013-11-23 14:54:00 -08002278#
2279# We define three string conventions for buffer types in the 'types' argument:
2280# 'buffer' : any object supporting the buffer interface
2281# 'rwbuffer': any object supporting the buffer interface, but must be writeable
2282# 'robuffer': any object supporting the buffer interface, but must not be writeable
2283#
2284@add_legacy_c_converter('s*', types='str bytes bytearray buffer')
2285@add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True)
2286@add_legacy_c_converter('w*', types='bytearray rwbuffer')
Larry Hastings31826802013-10-19 00:09:25 -07002287class Py_buffer_converter(CConverter):
2288 type = 'Py_buffer'
2289 format_unit = 'y*'
2290 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002291 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002292
Larry Hastingsebdcb502013-11-23 14:54:00 -08002293 def converter_init(self, *, types='bytes bytearray buffer', nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002294 if self.default not in (unspecified, None):
2295 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08002296 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002297 types = set(types.strip().split())
2298 bytes_type = set(('bytes',))
2299 bytearray_type = set(('bytearray',))
2300 buffer_type = set(('buffer',))
2301 rwbuffer_type = set(('rwbuffer',))
2302 robuffer_type = set(('robuffer',))
2303 str_type = set(('str',))
2304 bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type
2305
2306 format_unit = None
2307 if types == (str_type | bytes_bytearray_buffer_type):
2308 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07002309 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002310 if nullable:
2311 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
2312 elif types == (bytes_bytearray_buffer_type):
2313 format_unit = 'y*'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002314 elif types == (bytearray_type | rwbuffer_type):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002315 format_unit = 'w*'
2316 if not format_unit:
2317 fail("Py_buffer_converter: illegal combination of arguments")
2318
2319 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002320
2321 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002322 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002323 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002324
2325
2326class self_converter(CConverter):
2327 """
2328 A special-case converter:
2329 this is the default converter used for "self".
2330 """
2331 type = "PyObject *"
Larry Hastings78cf85c2014-01-04 12:44:57 -08002332 def converter_init(self, *, type=None):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002333 f = self.function
Larry Hastings8666e652014-01-12 14:12:59 -08002334 if f.kind in (CALLABLE, METHOD_INIT):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002335 if f.cls:
2336 self.name = "self"
2337 else:
2338 self.name = "module"
2339 self.type = "PyModuleDef *"
2340 elif f.kind == STATIC_METHOD:
2341 self.name = "null"
2342 self.type = "void *"
2343 elif f.kind == CLASS_METHOD:
2344 self.name = "cls"
2345 self.type = "PyTypeObject *"
Larry Hastings8666e652014-01-12 14:12:59 -08002346 elif f.kind == METHOD_NEW:
2347 self.name = "type"
2348 self.type = "PyTypeObject *"
Larry Hastingsebdcb502013-11-23 14:54:00 -08002349
Larry Hastings78cf85c2014-01-04 12:44:57 -08002350 if type:
2351 self.type = type
2352
Larry Hastingsebdcb502013-11-23 14:54:00 -08002353 def render(self, parameter, data):
2354 fail("render() should never be called on self_converter instances")
2355
Larry Hastings31826802013-10-19 00:09:25 -07002356
2357
2358def add_c_return_converter(f, name=None):
2359 if not name:
2360 name = f.__name__
2361 if not name.endswith('_return_converter'):
2362 return f
2363 name = name[:-len('_return_converter')]
2364 return_converters[name] = f
2365 return f
2366
2367
2368class CReturnConverterAutoRegister(type):
2369 def __init__(cls, name, bases, classdict):
2370 add_c_return_converter(cls)
2371
2372class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2373
Larry Hastings78cf85c2014-01-04 12:44:57 -08002374 # The C type to use for this variable.
2375 # 'type' should be a Python string specifying the type, e.g. "int".
2376 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002377 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002378
2379 # The Python default value for this parameter, as a Python value.
2380 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002381 default = None
2382
Larry Hastings2a727912014-01-16 11:32:01 -08002383 def __init__(self, *, py_default=None, **kwargs):
2384 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002385 try:
2386 self.return_converter_init(**kwargs)
2387 except TypeError as e:
2388 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2389 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2390
2391 def return_converter_init(self):
2392 pass
2393
2394 def declare(self, data, name="_return_value"):
2395 line = []
2396 add = line.append
2397 add(self.type)
2398 if not self.type.endswith('*'):
2399 add(' ')
2400 add(name + ';')
2401 data.declarations.append(''.join(line))
2402 data.return_value = name
2403
2404 def err_occurred_if(self, expr, data):
2405 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2406
2407 def err_occurred_if_null_pointer(self, variable, data):
2408 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2409
2410 def render(self, function, data):
2411 """
2412 function is a clinic.Function instance.
2413 data is a CRenderData instance.
2414 """
2415 pass
2416
2417add_c_return_converter(CReturnConverter, 'object')
2418
Larry Hastings78cf85c2014-01-04 12:44:57 -08002419class NoneType_return_converter(CReturnConverter):
2420 def render(self, function, data):
2421 self.declare(data)
2422 data.return_conversion.append('''
2423if (_return_value != Py_None)
2424 goto exit;
2425return_value = Py_None;
2426Py_INCREF(Py_None);
2427'''.strip())
2428
Larry Hastings4a55fc52014-01-12 11:09:57 -08002429class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002430 type = 'int'
2431
2432 def render(self, function, data):
2433 self.declare(data)
2434 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002435 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002436
2437class long_return_converter(CReturnConverter):
2438 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002439 conversion_fn = 'PyLong_FromLong'
2440 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002441
2442 def render(self, function, data):
2443 self.declare(data)
2444 self.err_occurred_if("_return_value == -1", data)
2445 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002446 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002447
Larry Hastings4a55fc52014-01-12 11:09:57 -08002448class int_return_converter(long_return_converter):
2449 type = 'int'
2450 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002451
Larry Hastings4a55fc52014-01-12 11:09:57 -08002452class unsigned_long_return_converter(long_return_converter):
2453 type = 'unsigned long'
2454 conversion_fn = 'PyLong_FromUnsignedLong'
2455
2456class unsigned_int_return_converter(unsigned_long_return_converter):
2457 type = 'unsigned int'
2458 cast = '(unsigned long)'
2459
2460class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07002461 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002462 conversion_fn = 'PyLong_FromSsize_t'
2463
2464class size_t_return_converter(long_return_converter):
2465 type = 'size_t'
2466 conversion_fn = 'PyLong_FromSize_t'
2467
2468
2469class double_return_converter(CReturnConverter):
2470 type = 'double'
2471 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002472
2473 def render(self, function, data):
2474 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002475 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07002476 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002477 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
2478
2479class float_return_converter(double_return_converter):
2480 type = 'float'
2481 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07002482
2483
2484class DecodeFSDefault_return_converter(CReturnConverter):
2485 type = 'char *'
2486
2487 def render(self, function, data):
2488 self.declare(data)
2489 self.err_occurred_if_null_pointer("_return_value", data)
2490 data.return_conversion.append(
2491 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
2492
2493
2494class IndentStack:
2495 def __init__(self):
2496 self.indents = []
2497 self.margin = None
2498
2499 def _ensure(self):
2500 if not self.indents:
2501 fail('IndentStack expected indents, but none are defined.')
2502
2503 def measure(self, line):
2504 """
2505 Returns the length of the line's margin.
2506 """
2507 if '\t' in line:
2508 fail('Tab characters are illegal in the Clinic DSL.')
2509 stripped = line.lstrip()
2510 if not len(stripped):
2511 # we can't tell anything from an empty line
2512 # so just pretend it's indented like our current indent
2513 self._ensure()
2514 return self.indents[-1]
2515 return len(line) - len(stripped)
2516
2517 def infer(self, line):
2518 """
2519 Infer what is now the current margin based on this line.
2520 Returns:
2521 1 if we have indented (or this is the first margin)
2522 0 if the margin has not changed
2523 -N if we have dedented N times
2524 """
2525 indent = self.measure(line)
2526 margin = ' ' * indent
2527 if not self.indents:
2528 self.indents.append(indent)
2529 self.margin = margin
2530 return 1
2531 current = self.indents[-1]
2532 if indent == current:
2533 return 0
2534 if indent > current:
2535 self.indents.append(indent)
2536 self.margin = margin
2537 return 1
2538 # indent < current
2539 if indent not in self.indents:
2540 fail("Illegal outdent.")
2541 outdent_count = 0
2542 while indent != current:
2543 self.indents.pop()
2544 current = self.indents[-1]
2545 outdent_count -= 1
2546 self.margin = margin
2547 return outdent_count
2548
2549 @property
2550 def depth(self):
2551 """
2552 Returns how many margins are currently defined.
2553 """
2554 return len(self.indents)
2555
2556 def indent(self, line):
2557 """
2558 Indents a line by the currently defined margin.
2559 """
2560 return self.margin + line
2561
2562 def dedent(self, line):
2563 """
2564 Dedents a line by the currently defined margin.
2565 (The inverse of 'indent'.)
2566 """
2567 margin = self.margin
2568 indent = self.indents[-1]
2569 if not line.startswith(margin):
2570 fail('Cannot dedent, line does not start with the previous margin:')
2571 return line[indent:]
2572
2573
2574class DSLParser:
2575 def __init__(self, clinic):
2576 self.clinic = clinic
2577
2578 self.directives = {}
2579 for name in dir(self):
2580 # functions that start with directive_ are added to directives
2581 _, s, key = name.partition("directive_")
2582 if s:
2583 self.directives[key] = getattr(self, name)
2584
2585 # functions that start with at_ are too, with an @ in front
2586 _, s, key = name.partition("at_")
2587 if s:
2588 self.directives['@' + key] = getattr(self, name)
2589
2590 self.reset()
2591
2592 def reset(self):
2593 self.function = None
2594 self.state = self.state_dsl_start
2595 self.parameter_indent = None
2596 self.keyword_only = False
2597 self.group = 0
2598 self.parameter_state = self.ps_start
2599 self.indent = IndentStack()
2600 self.kind = CALLABLE
2601 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08002602 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08002603 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07002604
Larry Hastingsebdcb502013-11-23 14:54:00 -08002605 def directive_version(self, required):
2606 global version
2607 if version_comparitor(version, required) < 0:
2608 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
2609
Larry Hastings31826802013-10-19 00:09:25 -07002610 def directive_module(self, name):
2611 fields = name.split('.')
2612 new = fields.pop()
2613 module, cls = self.clinic._module_and_class(fields)
2614 if cls:
2615 fail("Can't nest a module inside a class!")
2616 m = Module(name, module)
2617 module.modules[name] = m
2618 self.block.signatures.append(m)
2619
2620 def directive_class(self, name):
2621 fields = name.split('.')
2622 in_classes = False
2623 parent = self
2624 name = fields.pop()
2625 so_far = []
2626 module, cls = self.clinic._module_and_class(fields)
2627
Larry Hastings31826802013-10-19 00:09:25 -07002628 c = Class(name, module, cls)
Larry Hastings31826802013-10-19 00:09:25 -07002629 if cls:
2630 cls.classes[name] = c
Larry Hastingsed4a1c52013-11-18 09:32:13 -08002631 else:
2632 module.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07002633 self.block.signatures.append(c)
2634
Larry Hastingsbebf7352014-01-17 17:47:17 -08002635 def directive_set(self, name, value):
2636 if name not in ("line_prefix", "line_suffix"):
2637 fail("unknown variable", repr(name))
2638
2639 value = value.format_map({
2640 'block comment start': '/*',
2641 'block comment end': '*/',
2642 })
2643
2644 self.clinic.__dict__[name] = value
2645
2646 def directive_destination(self, name, command, *args):
2647 if command is 'new':
2648 self.clinic.add_destination(name, command, *args)
2649 return
2650
2651 if command is 'clear':
2652 self.clinic.get_destination(name).clear()
2653 fail("unknown destination command", repr(command))
2654
2655
2656 def directive_output(self, field, destination=''):
2657 fd = self.clinic.field_destinations
2658
2659 if field == "preset":
2660 preset = self.clinic.presets.get(destination)
2661 if not preset:
2662 fail("Unknown preset " + repr(destination) + "!")
2663 fd.update(preset)
2664 return
2665
2666 if field == "push":
2667 self.clinic.field_destinations_stack.append(fd.copy())
2668 return
2669
2670 if field == "pop":
2671 if not self.clinic.field_destinations_stack:
2672 fail("Can't 'output pop', stack is empty!")
2673 previous_fd = self.clinic.field_destinations_stack.pop()
2674 fd.update(previous_fd)
2675 return
2676
2677 # secret command for debugging!
2678 if field == "print":
2679 self.block.output.append(pprint.pformat(fd))
2680 self.block.output.append('\n')
2681 return
2682
2683 d = self.clinic.get_destination(destination)
2684
2685 if field == "everything":
2686 for name in list(fd):
2687 fd[name] = d
2688 return
2689
2690 if field not in fd:
2691 fail("Invalid field " + repr(field) + ", must be one of:\n " + ", ".join(valid_fields))
2692 fd[field] = d
2693
2694 def directive_dump(self, name):
2695 self.block.output.append(self.clinic.get_destination(name).dump())
2696
2697 def directive_print(self, *args):
2698 self.block.output.append(' '.join(args))
2699 self.block.output.append('\n')
2700
2701 def directive_preserve(self):
2702 if self.preserve_output:
2703 fail("Can't have preserve twice in one block!")
2704 self.preserve_output = True
2705
Larry Hastings31826802013-10-19 00:09:25 -07002706 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002707 if self.kind is not CALLABLE:
2708 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07002709 self.kind = CLASS_METHOD
2710
2711 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002712 if self.kind is not CALLABLE:
2713 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07002714 self.kind = STATIC_METHOD
2715
2716 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002717 if self.coexist:
2718 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07002719 self.coexist = True
2720
2721 def parse(self, block):
2722 self.reset()
2723 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08002724 self.saved_output = self.block.output
2725 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07002726 block_start = self.clinic.block_parser.line_number
2727 lines = block.input.split('\n')
2728 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
2729 if '\t' in line:
2730 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
2731 self.state(line)
2732
2733 self.next(self.state_terminal)
2734 self.state(None)
2735
Larry Hastingsbebf7352014-01-17 17:47:17 -08002736 block.output.extend(self.clinic.language.render(clinic, block.signatures))
2737
2738 if self.preserve_output:
2739 if block.output:
2740 fail("'preserve' only works for blocks that don't produce any output!")
2741 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07002742
2743 @staticmethod
2744 def ignore_line(line):
2745 # ignore comment-only lines
2746 if line.lstrip().startswith('#'):
2747 return True
2748
2749 # Ignore empty lines too
2750 # (but not in docstring sections!)
2751 if not line.strip():
2752 return True
2753
2754 return False
2755
2756 @staticmethod
2757 def calculate_indent(line):
2758 return len(line) - len(line.strip())
2759
2760 def next(self, state, line=None):
2761 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
2762 self.state = state
2763 if line is not None:
2764 self.state(line)
2765
2766 def state_dsl_start(self, line):
2767 # self.block = self.ClinicOutputBlock(self)
2768 if self.ignore_line(line):
2769 return
2770 self.next(self.state_modulename_name, line)
2771
2772 def state_modulename_name(self, line):
2773 # looking for declaration, which establishes the leftmost column
2774 # line should be
2775 # modulename.fnname [as c_basename] [-> return annotation]
2776 # square brackets denote optional syntax.
2777 #
Larry Hastings4a714d42014-01-14 22:22:41 -08002778 # alternatively:
2779 # modulename.fnname [as c_basename] = modulename.existing_fn_name
2780 # clones the parameters and return converter from that
2781 # function. you can't modify them. you must enter a
2782 # new docstring.
2783 #
Larry Hastings31826802013-10-19 00:09:25 -07002784 # (but we might find a directive first!)
2785 #
2786 # this line is permitted to start with whitespace.
2787 # we'll call this number of spaces F (for "function").
2788
2789 if not line.strip():
2790 return
2791
2792 self.indent.infer(line)
2793
2794 # is it a directive?
2795 fields = shlex.split(line)
2796 directive_name = fields[0]
2797 directive = self.directives.get(directive_name, None)
2798 if directive:
Larry Hastingsbebf7352014-01-17 17:47:17 -08002799 try:
2800 directive(*fields[1:])
2801 except TypeError as e:
2802 fail(str(e))
Larry Hastings31826802013-10-19 00:09:25 -07002803 return
2804
Larry Hastings4a714d42014-01-14 22:22:41 -08002805 # are we cloning?
2806 before, equals, existing = line.rpartition('=')
2807 if equals:
2808 full_name, _, c_basename = before.partition(' as ')
2809 full_name = full_name.strip()
2810 c_basename = c_basename.strip()
2811 existing = existing.strip()
2812 if (is_legal_py_identifier(full_name) and
2813 (not c_basename or is_legal_c_identifier(c_basename)) and
2814 is_legal_py_identifier(existing)):
2815 # we're cloning!
2816 fields = [x.strip() for x in existing.split('.')]
2817 function_name = fields.pop()
2818 module, cls = self.clinic._module_and_class(fields)
2819
2820 for existing_function in (cls or module).functions:
2821 if existing_function.name == function_name:
2822 break
2823 else:
2824 existing_function = None
2825 if not existing_function:
2826 fail("Couldn't find existing function " + repr(existing) + "!")
2827
2828 fields = [x.strip() for x in full_name.split('.')]
2829 function_name = fields.pop()
2830 module, cls = self.clinic._module_and_class(fields)
2831
2832 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
2833 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
2834 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
2835 return_converter=existing_function.return_converter, kind=existing_function.kind, coexist=existing_function.coexist)
2836
2837 self.function.parameters = existing_function.parameters.copy()
2838
2839 self.block.signatures.append(self.function)
2840 (cls or module).functions.append(self.function)
2841 self.next(self.state_function_docstring)
2842 return
2843
Larry Hastings31826802013-10-19 00:09:25 -07002844 line, _, returns = line.partition('->')
2845
2846 full_name, _, c_basename = line.partition(' as ')
2847 full_name = full_name.strip()
2848 c_basename = c_basename.strip() or None
2849
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002850 if not is_legal_py_identifier(full_name):
2851 fail("Illegal function name: {}".format(full_name))
2852 if c_basename and not is_legal_c_identifier(c_basename):
2853 fail("Illegal C basename: {}".format(c_basename))
2854
Larry Hastings31826802013-10-19 00:09:25 -07002855 if not returns:
2856 return_converter = CReturnConverter()
2857 else:
2858 ast_input = "def x() -> {}: pass".format(returns)
2859 module = None
2860 try:
2861 module = ast.parse(ast_input)
2862 except SyntaxError:
2863 pass
2864 if not module:
2865 fail("Badly-formed annotation for " + full_name + ": " + returns)
2866 try:
2867 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01002868 if legacy:
2869 fail("Legacy converter {!r} not allowed as a return converter"
2870 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07002871 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01002872 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07002873 return_converter = return_converters[name](**kwargs)
2874 except ValueError:
2875 fail("Badly-formed annotation for " + full_name + ": " + returns)
2876
2877 fields = [x.strip() for x in full_name.split('.')]
2878 function_name = fields.pop()
2879 module, cls = self.clinic._module_and_class(fields)
2880
Larry Hastings8666e652014-01-12 14:12:59 -08002881 fields = full_name.split('.')
2882 if fields[-1] == '__new__':
2883 if (self.kind != CLASS_METHOD) or (not cls):
2884 fail("__new__ must be a class method!")
2885 self.kind = METHOD_NEW
2886 elif fields[-1] == '__init__':
2887 if (self.kind != CALLABLE) or (not cls):
2888 fail("__init__ must be a normal method, not a class or static method!")
2889 self.kind = METHOD_INIT
2890 elif fields[-1] in unsupported_special_methods:
2891 fail(fields[-1] + " should not be converted to Argument Clinic! (Yet.)")
2892
Larry Hastings31826802013-10-19 00:09:25 -07002893 if not module:
2894 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
2895 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
2896 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
2897 self.block.signatures.append(self.function)
Larry Hastings4a714d42014-01-14 22:22:41 -08002898 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07002899 self.next(self.state_parameters_start)
2900
2901 # Now entering the parameters section. The rules, formally stated:
2902 #
2903 # * All lines must be indented with spaces only.
2904 # * The first line must be a parameter declaration.
2905 # * The first line must be indented.
2906 # * This first line establishes the indent for parameters.
2907 # * We'll call this number of spaces P (for "parameter").
2908 # * Thenceforth:
2909 # * Lines indented with P spaces specify a parameter.
2910 # * Lines indented with > P spaces are docstrings for the previous
2911 # parameter.
2912 # * We'll call this number of spaces D (for "docstring").
2913 # * All subsequent lines indented with >= D spaces are stored as
2914 # part of the per-parameter docstring.
2915 # * All lines will have the first D spaces of the indent stripped
2916 # before they are stored.
2917 # * It's illegal to have a line starting with a number of spaces X
2918 # such that P < X < D.
2919 # * A line with < P spaces is the first line of the function
2920 # docstring, which ends processing for parameters and per-parameter
2921 # docstrings.
2922 # * The first line of the function docstring must be at the same
2923 # indent as the function declaration.
2924 # * It's illegal to have any line in the parameters section starting
2925 # with X spaces such that F < X < P. (As before, F is the indent
2926 # of the function declaration.)
2927 #
Larry Hastings31826802013-10-19 00:09:25 -07002928 # Also, currently Argument Clinic places the following restrictions on groups:
2929 # * Each group must contain at least one parameter.
2930 # * Each group may contain at most one group, which must be the furthest
2931 # thing in the group from the required parameters. (The nested group
2932 # must be the first in the group when it's before the required
2933 # parameters, and the last thing in the group when after the required
2934 # parameters.)
2935 # * There may be at most one (top-level) group to the left or right of
2936 # the required parameters.
2937 # * You must specify a slash, and it must be after all parameters.
2938 # (In other words: either all parameters are positional-only,
2939 # or none are.)
2940 #
2941 # Said another way:
2942 # * Each group must contain at least one parameter.
2943 # * All left square brackets before the required parameters must be
2944 # consecutive. (You can't have a left square bracket followed
2945 # by a parameter, then another left square bracket. You can't
2946 # have a left square bracket, a parameter, a right square bracket,
2947 # and then a left square bracket.)
2948 # * All right square brackets after the required parameters must be
2949 # consecutive.
2950 #
2951 # These rules are enforced with a single state variable:
2952 # "parameter_state". (Previously the code was a miasma of ifs and
2953 # separate boolean state variables.) The states are:
2954 #
2955 # [ [ a, b, ] c, ] d, e, f, [ g, h, [ i ] ] / <- line
2956 # 01 2 3 4 5 6 <- state transitions
2957 #
2958 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
2959 # 1: ps_left_square_before. left square brackets before required parameters.
2960 # 2: ps_group_before. in a group, before required parameters.
2961 # 3: ps_required. required parameters. (renumber left groups!)
2962 # 4: ps_group_after. in a group, after required parameters.
2963 # 5: ps_right_square_after. right square brackets after required parameters.
2964 # 6: ps_seen_slash. seen slash.
2965 ps_start, ps_left_square_before, ps_group_before, ps_required, \
2966 ps_group_after, ps_right_square_after, ps_seen_slash = range(7)
2967
2968 def state_parameters_start(self, line):
2969 if self.ignore_line(line):
2970 return
2971
2972 # if this line is not indented, we have no parameters
2973 if not self.indent.infer(line):
2974 return self.next(self.state_function_docstring, line)
2975
Larry Hastings2a727912014-01-16 11:32:01 -08002976 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07002977 return self.next(self.state_parameter, line)
2978
2979
2980 def to_required(self):
2981 """
2982 Transition to the "required" parameter state.
2983 """
2984 if self.parameter_state != self.ps_required:
2985 self.parameter_state = self.ps_required
2986 for p in self.function.parameters.values():
2987 p.group = -p.group
2988
2989 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08002990 if self.parameter_continuation:
2991 line = self.parameter_continuation + ' ' + line.lstrip()
2992 self.parameter_continuation = ''
2993
Larry Hastings31826802013-10-19 00:09:25 -07002994 if self.ignore_line(line):
2995 return
2996
2997 assert self.indent.depth == 2
2998 indent = self.indent.infer(line)
2999 if indent == -1:
3000 # we outdented, must be to definition column
3001 return self.next(self.state_function_docstring, line)
3002
3003 if indent == 1:
3004 # we indented, must be to new parameter docstring column
3005 return self.next(self.state_parameter_docstring_start, line)
3006
Larry Hastings2a727912014-01-16 11:32:01 -08003007 line = line.rstrip()
3008 if line.endswith('\\'):
3009 self.parameter_continuation = line[:-1]
3010 return
3011
Larry Hastings31826802013-10-19 00:09:25 -07003012 line = line.lstrip()
3013
3014 if line in ('*', '/', '[', ']'):
3015 self.parse_special_symbol(line)
3016 return
3017
3018 if self.parameter_state in (self.ps_start, self.ps_required):
3019 self.to_required()
3020 elif self.parameter_state == self.ps_left_square_before:
3021 self.parameter_state = self.ps_group_before
3022 elif self.parameter_state == self.ps_group_before:
3023 if not self.group:
3024 self.to_required()
3025 elif self.parameter_state == self.ps_group_after:
3026 pass
3027 else:
3028 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3029
Larry Hastings2a727912014-01-16 11:32:01 -08003030 base, equals, default = line.rpartition('=')
3031 if not equals:
3032 base = default
3033 default = None
Larry Hastings31826802013-10-19 00:09:25 -07003034 module = None
3035 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003036 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003037 module = ast.parse(ast_input)
3038 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003039 try:
3040 default = None
3041 ast_input = "def x({}): pass".format(line)
3042 module = ast.parse(ast_input)
3043 except SyntaxError:
3044 pass
Larry Hastings31826802013-10-19 00:09:25 -07003045 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003046 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003047
3048 function_args = module.body[0].args
3049 parameter = function_args.args[0]
3050
Larry Hastings16c51912014-01-07 11:53:01 -08003051 parameter_name = parameter.arg
3052 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3053
Larry Hastings2a727912014-01-16 11:32:01 -08003054 if not default:
3055 value = unspecified
3056 if 'py_default' in kwargs:
3057 fail("You can't specify py_default without specifying a default value!")
3058 else:
3059 default = default.strip()
3060 ast_input = "x = {}".format(default)
3061 try:
3062 module = ast.parse(ast_input)
3063
3064 # blacklist of disallowed ast nodes
3065 class DetectBadNodes(ast.NodeVisitor):
3066 bad = False
3067 def bad_node(self, node):
3068 self.bad = True
3069
3070 # inline function call
3071 visit_Call = bad_node
3072 # inline if statement ("x = 3 if y else z")
3073 visit_IfExp = bad_node
3074
3075 # comprehensions and generator expressions
3076 visit_ListComp = visit_SetComp = bad_node
3077 visit_DictComp = visit_GeneratorExp = bad_node
3078
3079 # literals for advanced types
3080 visit_Dict = visit_Set = bad_node
3081 visit_List = visit_Tuple = bad_node
3082
3083 # "starred": "a = [1, 2, 3]; *a"
3084 visit_Starred = bad_node
3085
3086 # allow ellipsis, for now
3087 # visit_Ellipsis = bad_node
3088
3089 blacklist = DetectBadNodes()
3090 blacklist.visit(module)
3091 if blacklist.bad:
3092 fail("Unsupported expression as default value: " + repr(default))
3093
3094 expr = module.body[0].value
3095 # mild hack: explicitly support NULL as a default value
3096 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3097 value = NULL
3098 py_default = 'None'
3099 c_default = "NULL"
3100 elif (isinstance(expr, ast.BinOp) or
3101 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3102 c_default = kwargs.get("c_default")
3103 if not (isinstance(c_default, str) and c_default):
3104 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3105 py_default = default
3106 value = unknown
3107 elif isinstance(expr, ast.Attribute):
3108 a = []
3109 n = expr
3110 while isinstance(n, ast.Attribute):
3111 a.append(n.attr)
3112 n = n.value
3113 if not isinstance(n, ast.Name):
3114 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3115 a.append(n.id)
3116 py_default = ".".join(reversed(a))
3117
3118 c_default = kwargs.get("c_default")
3119 if not (isinstance(c_default, str) and c_default):
3120 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3121
3122 try:
3123 value = eval(py_default)
3124 except NameError:
3125 value = unknown
3126 else:
3127 value = ast.literal_eval(expr)
3128 py_default = repr(value)
3129 if isinstance(value, (bool, None.__class__)):
3130 c_default = "Py_" + py_default
3131 elif isinstance(value, str):
3132 c_default = '"' + quoted_for_c_string(value) + '"'
3133 else:
3134 c_default = py_default
3135
3136 except SyntaxError as e:
3137 fail("Syntax error: " + repr(e.text))
3138 except (ValueError, AttributeError):
3139 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003140 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003141 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003142 if not (isinstance(c_default, str) and c_default):
3143 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3144
Larry Hastings2a727912014-01-16 11:32:01 -08003145 kwargs.setdefault('c_default', c_default)
3146 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003147
Larry Hastings31826802013-10-19 00:09:25 -07003148 dict = legacy_converters if legacy else converters
3149 legacy_str = "legacy " if legacy else ""
3150 if name not in dict:
3151 fail('{} is not a valid {}converter'.format(name, legacy_str))
3152 converter = dict[name](parameter_name, self.function, value, **kwargs)
3153
Larry Hastingsebdcb502013-11-23 14:54:00 -08003154 # special case: if it's the self converter,
3155 # don't actually add it to the parameter list
3156 if isinstance(converter, self_converter):
3157 if self.function.parameters or (self.parameter_state != self.ps_required):
3158 fail("The 'self' parameter, if specified, must be the very first thing in the parameter block.")
3159 if self.function.self_converter:
3160 fail("You can't specify the 'self' parameter more than once.")
3161 self.function.self_converter = converter
3162 self.parameter_state = self.ps_start
3163 return
3164
Larry Hastings31826802013-10-19 00:09:25 -07003165 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
3166 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003167
3168 if parameter_name in self.function.parameters:
3169 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003170 self.function.parameters[parameter_name] = p
3171
3172 def parse_converter(self, annotation):
3173 if isinstance(annotation, ast.Str):
3174 return annotation.s, True, {}
3175
3176 if isinstance(annotation, ast.Name):
3177 return annotation.id, False, {}
3178
Larry Hastings4a55fc52014-01-12 11:09:57 -08003179 if not isinstance(annotation, ast.Call):
3180 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003181
3182 name = annotation.func.id
3183 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
3184 return name, False, kwargs
3185
3186 def parse_special_symbol(self, symbol):
3187 if self.parameter_state == self.ps_seen_slash:
3188 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3189
3190 if symbol == '*':
3191 if self.keyword_only:
3192 fail("Function " + self.function.name + " uses '*' more than once.")
3193 self.keyword_only = True
3194 elif symbol == '[':
3195 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3196 self.parameter_state = self.ps_left_square_before
3197 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3198 self.parameter_state = self.ps_group_after
3199 else:
3200 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3201 self.group += 1
3202 elif symbol == ']':
3203 if not self.group:
3204 fail("Function " + self.function.name + " has a ] without a matching [.")
3205 if not any(p.group == self.group for p in self.function.parameters.values()):
3206 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3207 self.group -= 1
3208 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3209 self.parameter_state = self.ps_group_before
3210 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3211 self.parameter_state = self.ps_right_square_after
3212 else:
3213 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3214 elif symbol == '/':
3215 # ps_required is allowed here, that allows positional-only without option groups
3216 # to work (and have default values!)
3217 if (self.parameter_state not in (self.ps_required, self.ps_right_square_after, self.ps_group_before)) or self.group:
3218 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
3219 if self.keyword_only:
3220 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3221 self.parameter_state = self.ps_seen_slash
3222 # fixup preceeding parameters
3223 for p in self.function.parameters.values():
3224 if p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD:
3225 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3226 p.kind = inspect.Parameter.POSITIONAL_ONLY
3227
3228 def state_parameter_docstring_start(self, line):
3229 self.parameter_docstring_indent = len(self.indent.margin)
3230 assert self.indent.depth == 3
3231 return self.next(self.state_parameter_docstring, line)
3232
3233 # every line of the docstring must start with at least F spaces,
3234 # where F > P.
3235 # these F spaces will be stripped.
3236 def state_parameter_docstring(self, line):
3237 stripped = line.strip()
3238 if stripped.startswith('#'):
3239 return
3240
3241 indent = self.indent.measure(line)
3242 if indent < self.parameter_docstring_indent:
3243 self.indent.infer(line)
3244 assert self.indent.depth < 3
3245 if self.indent.depth == 2:
3246 # back to a parameter
3247 return self.next(self.state_parameter, line)
3248 assert self.indent.depth == 1
3249 return self.next(self.state_function_docstring, line)
3250
3251 assert self.function.parameters
3252 last_parameter = next(reversed(list(self.function.parameters.values())))
3253
3254 new_docstring = last_parameter.docstring
3255
3256 if new_docstring:
3257 new_docstring += '\n'
3258 if stripped:
3259 new_docstring += self.indent.dedent(line)
3260
3261 last_parameter.docstring = new_docstring
3262
3263 # the final stanza of the DSL is the docstring.
3264 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003265 if self.group:
3266 fail("Function " + self.function.name + " has a ] without a matching [.")
3267
3268 stripped = line.strip()
3269 if stripped.startswith('#'):
3270 return
3271
3272 new_docstring = self.function.docstring
3273 if new_docstring:
3274 new_docstring += "\n"
3275 if stripped:
3276 line = self.indent.dedent(line).rstrip()
3277 else:
3278 line = ''
3279 new_docstring += line
3280 self.function.docstring = new_docstring
3281
3282 def format_docstring(self):
3283 f = self.function
3284
3285 add, output = text_accumulator()
3286 parameters = list(f.parameters.values())
3287
3288 ##
3289 ## docstring first line
3290 ##
3291
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003292 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003293 add('(')
3294
3295 # populate "right_bracket_count" field for every parameter
3296 if parameters:
3297 # for now, the only way Clinic supports positional-only parameters
3298 # is if all of them are positional-only.
3299 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters]
3300 if parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY:
3301 assert all(positional_only_parameters)
3302 for p in parameters:
3303 p.right_bracket_count = abs(p.group)
3304 else:
3305 # don't put any right brackets around non-positional-only parameters, ever.
3306 for p in parameters:
3307 p.right_bracket_count = 0
3308
3309 right_bracket_count = 0
3310
3311 def fix_right_bracket_count(desired):
3312 nonlocal right_bracket_count
3313 s = ''
3314 while right_bracket_count < desired:
3315 s += '['
3316 right_bracket_count += 1
3317 while right_bracket_count > desired:
3318 s += ']'
3319 right_bracket_count -= 1
3320 return s
3321
3322 added_star = False
3323 add_comma = False
3324
3325 for p in parameters:
3326 assert p.name
3327
3328 if p.is_keyword_only() and not added_star:
3329 added_star = True
3330 if add_comma:
3331 add(', ')
3332 add('*')
3333
3334 a = [p.name]
3335 if p.converter.is_optional():
3336 a.append('=')
3337 value = p.converter.default
Larry Hastings2a727912014-01-16 11:32:01 -08003338 a.append(p.converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003339 s = fix_right_bracket_count(p.right_bracket_count)
3340 s += "".join(a)
3341 if add_comma:
3342 add(', ')
3343 add(s)
3344 add_comma = True
3345
3346 add(fix_right_bracket_count(0))
3347 add(')')
3348
Larry Hastings2a727912014-01-16 11:32:01 -08003349 # PEP 8 says:
3350 #
3351 # The Python standard library will not use function annotations
3352 # as that would result in a premature commitment to a particular
3353 # annotation style. Instead, the annotations are left for users
3354 # to discover and experiment with useful annotation styles.
3355 #
3356 # therefore this is commented out:
3357 #
3358 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003359 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08003360 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003361
3362 docstring_first_line = output()
3363
3364 # now fix up the places where the brackets look wrong
3365 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
3366
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003367 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07003368 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003369 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07003370 for p in parameters:
3371 if not p.docstring.strip():
3372 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003373 if spacer_line:
3374 add('\n')
3375 else:
3376 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07003377 add(" ")
3378 add(p.name)
3379 add('\n')
3380 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003381 parameters = output()
3382 if parameters:
3383 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07003384
3385 ##
3386 ## docstring body
3387 ##
3388
3389 docstring = f.docstring.rstrip()
3390 lines = [line.rstrip() for line in docstring.split('\n')]
3391
3392 # Enforce the summary line!
3393 # The first line of a docstring should be a summary of the function.
3394 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
3395 # by itself.
3396 #
3397 # Argument Clinic enforces the following rule:
3398 # * either the docstring is empty,
3399 # * or it must have a summary line.
3400 #
3401 # Guido said Clinic should enforce this:
3402 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
3403
3404 if len(lines) >= 2:
3405 if lines[1]:
3406 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
3407 "Every non-blank function docstring must start with\n" +
3408 "a single line summary followed by an empty line.")
3409 elif len(lines) == 1:
3410 # the docstring is only one line right now--the summary line.
3411 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003412 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07003413 lines.append('')
3414
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003415 parameters_marker_count = len(docstring.split('{parameters}')) - 1
3416 if parameters_marker_count > 1:
3417 fail('You may not specify {parameters} more than once in a docstring!')
3418
3419 if not parameters_marker_count:
3420 # insert after summary line
3421 lines.insert(2, '{parameters}')
3422
3423 # insert at front of docstring
3424 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07003425
3426 docstring = "\n".join(lines)
3427
3428 add(docstring)
3429 docstring = output()
3430
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003431 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07003432 docstring = docstring.rstrip()
3433
3434 return docstring
3435
3436 def state_terminal(self, line):
3437 """
3438 Called when processing the block is done.
3439 """
3440 assert not line
3441
3442 if not self.function:
3443 return
3444
Larry Hastings6d2ea212014-01-05 02:50:45 -08003445 if not self.function.self_converter:
3446 self.function.self_converter = self_converter("self", self.function)
3447
Larry Hastings31826802013-10-19 00:09:25 -07003448 if self.keyword_only:
3449 values = self.function.parameters.values()
3450 if not values:
3451 no_parameter_after_star = True
3452 else:
3453 last_parameter = next(reversed(list(values)))
3454 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
3455 if no_parameter_after_star:
3456 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
3457
3458 # remove trailing whitespace from all parameter docstrings
3459 for name, value in self.function.parameters.items():
3460 if not value:
3461 continue
3462 value.docstring = value.docstring.rstrip()
3463
3464 self.function.docstring = self.format_docstring()
3465
3466
3467# maps strings to callables.
3468# the callable should return an object
3469# that implements the clinic parser
3470# interface (__init__ and parse).
3471#
3472# example parsers:
3473# "clinic", handles the Clinic DSL
3474# "python", handles running Python code
3475#
3476parsers = {'clinic' : DSLParser, 'python': PythonParser}
3477
3478
3479clinic = None
3480
3481
3482def main(argv):
3483 import sys
3484
3485 if sys.version_info.major < 3 or sys.version_info.minor < 3:
3486 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
3487
3488 import argparse
3489 cmdline = argparse.ArgumentParser()
3490 cmdline.add_argument("-f", "--force", action='store_true')
3491 cmdline.add_argument("-o", "--output", type=str)
3492 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003493 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07003494 cmdline.add_argument("filename", type=str, nargs="*")
3495 ns = cmdline.parse_args(argv)
3496
3497 if ns.converters:
3498 if ns.filename:
3499 print("Usage error: can't specify --converters and a filename at the same time.")
3500 print()
3501 cmdline.print_usage()
3502 sys.exit(-1)
3503 converters = []
3504 return_converters = []
3505 ignored = set("""
3506 add_c_converter
3507 add_c_return_converter
3508 add_default_legacy_c_converter
3509 add_legacy_c_converter
3510 """.strip().split())
3511 module = globals()
3512 for name in module:
3513 for suffix, ids in (
3514 ("_return_converter", return_converters),
3515 ("_converter", converters),
3516 ):
3517 if name in ignored:
3518 continue
3519 if name.endswith(suffix):
3520 ids.append((name, name[:-len(suffix)]))
3521 break
3522 print()
3523
3524 print("Legacy converters:")
3525 legacy = sorted(legacy_converters)
3526 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
3527 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
3528 print()
3529
3530 for title, attribute, ids in (
3531 ("Converters", 'converter_init', converters),
3532 ("Return converters", 'return_converter_init', return_converters),
3533 ):
3534 print(title + ":")
3535 longest = -1
3536 for name, short_name in ids:
3537 longest = max(longest, len(short_name))
3538 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
3539 cls = module[name]
3540 callable = getattr(cls, attribute, None)
3541 if not callable:
3542 continue
3543 signature = inspect.signature(callable)
3544 parameters = []
3545 for parameter_name, parameter in signature.parameters.items():
3546 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
3547 if parameter.default != inspect.Parameter.empty:
3548 s = '{}={!r}'.format(parameter_name, parameter.default)
3549 else:
3550 s = parameter_name
3551 parameters.append(s)
3552 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07003553 print()
Larry Hastings2a727912014-01-16 11:32:01 -08003554 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
3555 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07003556 sys.exit(0)
3557
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003558 if ns.make:
3559 if ns.output or ns.filename:
3560 print("Usage error: can't use -o or filenames with --make.")
3561 print()
3562 cmdline.print_usage()
3563 sys.exit(-1)
3564 for root, dirs, files in os.walk('.'):
3565 for rcs_dir in ('.svn', '.git', '.hg'):
3566 if rcs_dir in dirs:
3567 dirs.remove(rcs_dir)
3568 for filename in files:
3569 if not filename.endswith('.c'):
3570 continue
3571 path = os.path.join(root, filename)
3572 parse_file(path, verify=not ns.force)
3573 return
3574
Larry Hastings31826802013-10-19 00:09:25 -07003575 if not ns.filename:
3576 cmdline.print_usage()
3577 sys.exit(-1)
3578
3579 if ns.output and len(ns.filename) > 1:
3580 print("Usage error: can't use -o with multiple filenames.")
3581 print()
3582 cmdline.print_usage()
3583 sys.exit(-1)
3584
3585 for filename in ns.filename:
3586 parse_file(filename, output=ns.output, verify=not ns.force)
3587
3588
3589if __name__ == "__main__":
3590 sys.exit(main(sys.argv[1:]))