blob: ba7cb88404fd6d7ea4a2c28a107b7c166893d2b1 [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
Larry Hastings7726ac92014-01-31 22:03:12 -080013import copy
14import cpp
Larry Hastings31826802013-10-19 00:09:25 -070015import functools
16import hashlib
17import inspect
18import io
19import itertools
20import os
Larry Hastingsbebf7352014-01-17 17:47:17 -080021import pprint
Larry Hastings31826802013-10-19 00:09:25 -070022import re
23import shlex
Larry Hastings581ee362014-01-28 05:00:08 -080024import string
Larry Hastings31826802013-10-19 00:09:25 -070025import sys
26import tempfile
27import textwrap
Georg Brandlaabebde2014-01-16 06:53:54 +010028import traceback
Larry Hastingsbebf7352014-01-17 17:47:17 -080029import uuid
Larry Hastings31826802013-10-19 00:09:25 -070030
Larry Hastings31826802013-10-19 00:09:25 -070031# TODO:
Larry Hastings31826802013-10-19 00:09:25 -070032#
33# soon:
34#
35# * allow mixing any two of {positional-only, positional-or-keyword,
36# keyword-only}
37# * dict constructor uses positional-only and keyword-only
38# * max and min use positional only with an optional group
39# and keyword-only
40#
Larry Hastings31826802013-10-19 00:09:25 -070041
Larry Hastingsebdcb502013-11-23 14:54:00 -080042version = '1'
43
Larry Hastings31826802013-10-19 00:09:25 -070044_empty = inspect._empty
45_void = inspect._void
46
Larry Hastings4a55fc52014-01-12 11:09:57 -080047NoneType = type(None)
Larry Hastings31826802013-10-19 00:09:25 -070048
49class Unspecified:
50 def __repr__(self):
51 return '<Unspecified>'
52
53unspecified = Unspecified()
54
55
56class Null:
57 def __repr__(self):
58 return '<Null>'
59
60NULL = Null()
61
62
Larry Hastings2a727912014-01-16 11:32:01 -080063class Unknown:
64 def __repr__(self):
65 return '<Unknown>'
66
67unknown = Unknown()
68
Zachary Ware8ef887c2015-04-13 18:22:35 -050069sig_end_marker = '--'
70
Larry Hastings2a727912014-01-16 11:32:01 -080071
Larry Hastings0759f842015-04-03 13:09:02 -070072_text_accumulator_nt = collections.namedtuple("_text_accumulator", "text append output")
73
Larry Hastings31826802013-10-19 00:09:25 -070074def _text_accumulator():
75 text = []
76 def output():
77 s = ''.join(text)
78 text.clear()
79 return s
Larry Hastings0759f842015-04-03 13:09:02 -070080 return _text_accumulator_nt(text, text.append, output)
Larry Hastings31826802013-10-19 00:09:25 -070081
82
Larry Hastings0759f842015-04-03 13:09:02 -070083text_accumulator_nt = collections.namedtuple("text_accumulator", "text append")
84
Larry Hastings31826802013-10-19 00:09:25 -070085def text_accumulator():
86 """
87 Creates a simple text accumulator / joiner.
88
89 Returns a pair of callables:
90 append, output
91 "append" appends a string to the accumulator.
92 "output" returns the contents of the accumulator
93 joined together (''.join(accumulator)) and
94 empties the accumulator.
95 """
96 text, append, output = _text_accumulator()
Larry Hastings0759f842015-04-03 13:09:02 -070097 return text_accumulator_nt(append, output)
Larry Hastings31826802013-10-19 00:09:25 -070098
99
Larry Hastingsbebf7352014-01-17 17:47:17 -0800100def warn_or_fail(fail=False, *args, filename=None, line_number=None):
Larry Hastings31826802013-10-19 00:09:25 -0700101 joined = " ".join([str(a) for a in args])
102 add, output = text_accumulator()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800103 if fail:
104 add("Error")
105 else:
106 add("Warning")
Larry Hastings31826802013-10-19 00:09:25 -0700107 if clinic:
108 if filename is None:
109 filename = clinic.filename
Larry Hastings581ee362014-01-28 05:00:08 -0800110 if getattr(clinic, 'block_parser', None) and (line_number is None):
Larry Hastings31826802013-10-19 00:09:25 -0700111 line_number = clinic.block_parser.line_number
112 if filename is not None:
113 add(' in file "' + filename + '"')
114 if line_number is not None:
115 add(" on line " + str(line_number))
116 add(':\n')
117 add(joined)
118 print(output())
Larry Hastingsbebf7352014-01-17 17:47:17 -0800119 if fail:
120 sys.exit(-1)
Larry Hastings31826802013-10-19 00:09:25 -0700121
122
Larry Hastingsbebf7352014-01-17 17:47:17 -0800123def warn(*args, filename=None, line_number=None):
124 return warn_or_fail(False, *args, filename=filename, line_number=line_number)
125
126def fail(*args, filename=None, line_number=None):
127 return warn_or_fail(True, *args, filename=filename, line_number=line_number)
128
Larry Hastings31826802013-10-19 00:09:25 -0700129
130def quoted_for_c_string(s):
131 for old, new in (
Zachary Ware9d7849f2014-01-25 03:26:20 -0600132 ('\\', '\\\\'), # must be first!
Larry Hastings31826802013-10-19 00:09:25 -0700133 ('"', '\\"'),
134 ("'", "\\'"),
135 ):
136 s = s.replace(old, new)
137 return s
138
Larry Hastings4903e002014-01-18 00:26:16 -0800139def c_repr(s):
140 return '"' + s + '"'
141
142
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700143is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
144
145def is_legal_py_identifier(s):
146 return all(is_legal_c_identifier(field) for field in s.split('.'))
147
Larry Hastingsbebf7352014-01-17 17:47:17 -0800148# identifiers that are okay in Python but aren't a good idea in C.
149# so if they're used Argument Clinic will add "_value" to the end
150# of the name in C.
Larry Hastings31826802013-10-19 00:09:25 -0700151c_keywords = set("""
Larry Hastings5c661892014-01-24 06:17:25 -0800152asm auto break case char const continue default do double
153else enum extern float for goto if inline int long
154register return short signed sizeof static struct switch
Larry Hastingsbebf7352014-01-17 17:47:17 -0800155typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700156""".strip().split())
157
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700158def ensure_legal_c_identifier(s):
159 # for now, just complain if what we're given isn't legal
160 if not is_legal_c_identifier(s):
161 fail("Illegal C identifier: {}".format(s))
162 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700163 if s in c_keywords:
164 return s + "_value"
165 return s
166
167def rstrip_lines(s):
168 text, add, output = _text_accumulator()
169 for line in s.split('\n'):
170 add(line.rstrip())
171 add('\n')
172 text.pop()
173 return output()
174
175def linear_format(s, **kwargs):
176 """
177 Perform str.format-like substitution, except:
178 * The strings substituted must be on lines by
179 themselves. (This line is the "source line".)
180 * If the substitution text is empty, the source line
181 is removed in the output.
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800182 * If the field is not recognized, the original line
183 is passed unmodified through to the output.
Larry Hastings31826802013-10-19 00:09:25 -0700184 * If the substitution text is not empty:
185 * Each line of the substituted text is indented
186 by the indent of the source line.
187 * A newline will be added to the end.
188 """
189
190 add, output = text_accumulator()
191 for line in s.split('\n'):
192 indent, curly, trailing = line.partition('{')
193 if not curly:
194 add(line)
195 add('\n')
196 continue
197
198 name, curl, trailing = trailing.partition('}')
199 if not curly or name not in kwargs:
200 add(line)
201 add('\n')
202 continue
203
204 if trailing:
205 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
206 if indent.strip():
207 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
208
209 value = kwargs[name]
210 if not value:
211 continue
212
213 value = textwrap.indent(rstrip_lines(value), indent)
214 add(value)
215 add('\n')
216
217 return output()[:-1]
218
Larry Hastingsbebf7352014-01-17 17:47:17 -0800219def indent_all_lines(s, prefix):
220 """
221 Returns 's', with 'prefix' prepended to all lines.
222
223 If the last line is empty, prefix is not prepended
224 to it. (If s is blank, returns s unchanged.)
225
226 (textwrap.indent only adds to non-blank lines.)
227 """
228 split = s.split('\n')
229 last = split.pop()
230 final = []
231 for line in split:
232 final.append(prefix)
233 final.append(line)
234 final.append('\n')
235 if last:
236 final.append(prefix)
237 final.append(last)
238 return ''.join(final)
239
240def suffix_all_lines(s, suffix):
241 """
242 Returns 's', with 'suffix' appended to all lines.
243
244 If the last line is empty, suffix is not appended
245 to it. (If s is blank, returns s unchanged.)
246 """
247 split = s.split('\n')
248 last = split.pop()
249 final = []
250 for line in split:
251 final.append(line)
252 final.append(suffix)
253 final.append('\n')
254 if last:
255 final.append(last)
256 final.append(suffix)
257 return ''.join(final)
258
259
Larry Hastingsebdcb502013-11-23 14:54:00 -0800260def version_splitter(s):
261 """Splits a version string into a tuple of integers.
262
263 The following ASCII characters are allowed, and employ
264 the following conversions:
265 a -> -3
266 b -> -2
267 c -> -1
268 (This permits Python-style version strings such as "1.4b3".)
269 """
270 version = []
271 accumulator = []
272 def flush():
273 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800274 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800275 version.append(int(''.join(accumulator)))
276 accumulator.clear()
277
278 for c in s:
279 if c.isdigit():
280 accumulator.append(c)
281 elif c == '.':
282 flush()
283 elif c in 'abc':
284 flush()
285 version.append('abc'.index(c) - 3)
286 else:
287 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
288 flush()
289 return tuple(version)
290
291def version_comparitor(version1, version2):
292 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
293 for i, (a, b) in enumerate(iterator):
294 if a < b:
295 return -1
296 if a > b:
297 return 1
298 return 0
299
Larry Hastings31826802013-10-19 00:09:25 -0700300
301class CRenderData:
302 def __init__(self):
303
304 # The C statements to declare variables.
305 # Should be full lines with \n eol characters.
306 self.declarations = []
307
308 # The C statements required to initialize the variables before the parse call.
309 # Should be full lines with \n eol characters.
310 self.initializers = []
311
Larry Hastingsc2047262014-01-25 20:43:29 -0800312 # The C statements needed to dynamically modify the values
313 # parsed by the parse call, before calling the impl.
314 self.modifications = []
315
Larry Hastings31826802013-10-19 00:09:25 -0700316 # The entries for the "keywords" array for PyArg_ParseTuple.
317 # Should be individual strings representing the names.
318 self.keywords = []
319
320 # The "format units" for PyArg_ParseTuple.
321 # Should be individual strings that will get
322 self.format_units = []
323
324 # The varargs arguments for PyArg_ParseTuple.
325 self.parse_arguments = []
326
327 # The parameter declarations for the impl function.
328 self.impl_parameters = []
329
330 # The arguments to the impl function at the time it's called.
331 self.impl_arguments = []
332
333 # For return converters: the name of the variable that
334 # should receive the value returned by the impl.
335 self.return_value = "return_value"
336
337 # For return converters: the code to convert the return
338 # value from the parse function. This is also where
339 # you should check the _return_value for errors, and
340 # "goto exit" if there are any.
341 self.return_conversion = []
342
343 # The C statements required to clean up after the impl call.
344 self.cleanup = []
345
346
Larry Hastings581ee362014-01-28 05:00:08 -0800347class FormatCounterFormatter(string.Formatter):
348 """
349 This counts how many instances of each formatter
350 "replacement string" appear in the format string.
351
352 e.g. after evaluating "string {a}, {b}, {c}, {a}"
353 the counts dict would now look like
354 {'a': 2, 'b': 1, 'c': 1}
355 """
356 def __init__(self):
357 self.counts = collections.Counter()
358
359 def get_value(self, key, args, kwargs):
360 self.counts[key] += 1
361 return ''
362
Larry Hastings31826802013-10-19 00:09:25 -0700363class Language(metaclass=abc.ABCMeta):
364
365 start_line = ""
366 body_prefix = ""
367 stop_line = ""
368 checksum_line = ""
369
Larry Hastings7726ac92014-01-31 22:03:12 -0800370 def __init__(self, filename):
371 pass
372
Larry Hastings31826802013-10-19 00:09:25 -0700373 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800374 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700375 pass
376
Larry Hastings7726ac92014-01-31 22:03:12 -0800377 def parse_line(self, line):
378 pass
379
Larry Hastings31826802013-10-19 00:09:25 -0700380 def validate(self):
Larry Hastings581ee362014-01-28 05:00:08 -0800381 def assert_only_one(attr, *additional_fields):
382 """
383 Ensures that the string found at getattr(self, attr)
384 contains exactly one formatter replacement string for
385 each valid field. The list of valid fields is
386 ['dsl_name'] extended by additional_fields.
387
388 e.g.
389 self.fmt = "{dsl_name} {a} {b}"
390
391 # this passes
392 self.assert_only_one('fmt', 'a', 'b')
393
394 # this fails, the format string has a {b} in it
395 self.assert_only_one('fmt', 'a')
396
397 # this fails, the format string doesn't have a {c} in it
398 self.assert_only_one('fmt', 'a', 'b', 'c')
399
400 # this fails, the format string has two {a}s in it,
401 # it must contain exactly one
402 self.fmt2 = '{dsl_name} {a} {a}'
403 self.assert_only_one('fmt2', 'a')
404
405 """
406 fields = ['dsl_name']
407 fields.extend(additional_fields)
408 line = getattr(self, attr)
409 fcf = FormatCounterFormatter()
410 fcf.format(line)
411 def local_fail(should_be_there_but_isnt):
412 if should_be_there_but_isnt:
413 fail("{} {} must contain {{{}}} exactly once!".format(
414 self.__class__.__name__, attr, name))
415 else:
416 fail("{} {} must not contain {{{}}}!".format(
417 self.__class__.__name__, attr, name))
418
419 for name, count in fcf.counts.items():
420 if name in fields:
421 if count > 1:
422 local_fail(True)
423 else:
424 local_fail(False)
425 for name in fields:
426 if fcf.counts.get(name) != 1:
427 local_fail(True)
428
Larry Hastings31826802013-10-19 00:09:25 -0700429 assert_only_one('start_line')
430 assert_only_one('stop_line')
Larry Hastings31826802013-10-19 00:09:25 -0700431
Larry Hastings581ee362014-01-28 05:00:08 -0800432 field = "arguments" if "{arguments}" in self.checksum_line else "checksum"
433 assert_only_one('checksum_line', field)
Larry Hastings31826802013-10-19 00:09:25 -0700434
435
436
437class PythonLanguage(Language):
438
439 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800440 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700441 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800442 stop_line = "#[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800443 checksum_line = "#/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700444
445
446def permute_left_option_groups(l):
447 """
448 Given [1, 2, 3], should yield:
449 ()
450 (3,)
451 (2, 3)
452 (1, 2, 3)
453 """
454 yield tuple()
455 accumulator = []
456 for group in reversed(l):
457 accumulator = list(group) + accumulator
458 yield tuple(accumulator)
459
460
461def permute_right_option_groups(l):
462 """
463 Given [1, 2, 3], should yield:
464 ()
465 (1,)
466 (1, 2)
467 (1, 2, 3)
468 """
469 yield tuple()
470 accumulator = []
471 for group in l:
472 accumulator.extend(group)
473 yield tuple(accumulator)
474
475
476def permute_optional_groups(left, required, right):
477 """
478 Generator function that computes the set of acceptable
479 argument lists for the provided iterables of
480 argument groups. (Actually it generates a tuple of tuples.)
481
482 Algorithm: prefer left options over right options.
483
484 If required is empty, left must also be empty.
485 """
486 required = tuple(required)
487 result = []
488
489 if not required:
490 assert not left
491
492 accumulator = []
493 counts = set()
494 for r in permute_right_option_groups(right):
495 for l in permute_left_option_groups(left):
496 t = l + required + r
497 if len(t) in counts:
498 continue
499 counts.add(len(t))
500 accumulator.append(t)
501
502 accumulator.sort(key=len)
503 return tuple(accumulator)
504
505
Larry Hastings7726ac92014-01-31 22:03:12 -0800506def strip_leading_and_trailing_blank_lines(s):
507 lines = s.rstrip().split('\n')
508 while lines:
509 line = lines[0]
510 if line.strip():
511 break
512 del lines[0]
513 return '\n'.join(lines)
514
515@functools.lru_cache()
516def normalize_snippet(s, *, indent=0):
517 """
518 Reformats s:
519 * removes leading and trailing blank lines
520 * ensures that it does not end with a newline
521 * dedents so the first nonwhite character on any line is at column "indent"
522 """
523 s = strip_leading_and_trailing_blank_lines(s)
524 s = textwrap.dedent(s)
525 if indent:
526 s = textwrap.indent(s, ' ' * indent)
527 return s
528
529
Larry Hastings89964c42015-04-14 18:07:59 -0400530def wrap_declarations(text, length=78):
531 """
532 A simple-minded text wrapper for C function declarations.
533
534 It views a declaration line as looking like this:
535 xxxxxxxx(xxxxxxxxx,xxxxxxxxx)
536 If called with length=30, it would wrap that line into
537 xxxxxxxx(xxxxxxxxx,
538 xxxxxxxxx)
539 (If the declaration has zero or one parameters, this
540 function won't wrap it.)
541
542 If this doesn't work properly, it's probably better to
543 start from scratch with a more sophisticated algorithm,
544 rather than try and improve/debug this dumb little function.
545 """
546 lines = []
547 for line in text.split('\n'):
548 prefix, _, after_l_paren = line.partition('(')
549 if not after_l_paren:
550 lines.append(line)
551 continue
552 parameters, _, after_r_paren = after_l_paren.partition(')')
553 if not _:
554 lines.append(line)
555 continue
556 if ',' not in parameters:
557 lines.append(line)
558 continue
559 parameters = [x.strip() + ", " for x in parameters.split(',')]
560 prefix += "("
561 if len(prefix) < length:
562 spaces = " " * len(prefix)
563 else:
564 spaces = " " * 4
565
566 while parameters:
567 line = prefix
568 first = True
569 while parameters:
570 if (not first and
571 (len(line) + len(parameters[0]) > length)):
572 break
573 line += parameters.pop(0)
574 first = False
575 if not parameters:
576 line = line.rstrip(", ") + ")" + after_r_paren
577 lines.append(line.rstrip())
578 prefix = spaces
579 return "\n".join(lines)
580
581
Larry Hastings31826802013-10-19 00:09:25 -0700582class CLanguage(Language):
583
Larry Hastings61272b72014-01-07 12:41:53 -0800584 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700585 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800586 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700587 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800588 stop_line = "[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800589 checksum_line = "/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700590
Larry Hastings7726ac92014-01-31 22:03:12 -0800591 def __init__(self, filename):
592 super().__init__(filename)
593 self.cpp = cpp.Monitor(filename)
594 self.cpp.fail = fail
595
596 def parse_line(self, line):
597 self.cpp.writeline(line)
598
Larry Hastingsbebf7352014-01-17 17:47:17 -0800599 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700600 function = None
601 for o in signatures:
602 if isinstance(o, Function):
603 if function:
604 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
605 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800606 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700607
608 def docstring_for_c_string(self, f):
609 text, add, output = _text_accumulator()
610 # turn docstring into a properly quoted C string
611 for line in f.docstring.split('\n'):
612 add('"')
613 add(quoted_for_c_string(line))
614 add('\\n"\n')
615
Zachary Ware8ef887c2015-04-13 18:22:35 -0500616 if text[-2] == sig_end_marker:
617 # If we only have a signature, add the blank line that the
618 # __text_signature__ getter expects to be there.
619 add('"\\n"')
620 else:
621 text.pop()
622 add('"')
Larry Hastings31826802013-10-19 00:09:25 -0700623 return ''.join(text)
624
Larry Hastingsbebf7352014-01-17 17:47:17 -0800625 def output_templates(self, f):
626 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800627 assert parameters
628 assert isinstance(parameters[0].converter, self_converter)
629 del parameters[0]
Larry Hastingsbebf7352014-01-17 17:47:17 -0800630 converters = [p.converter for p in parameters]
631
632 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
633 default_return_converter = (not f.return_converter or
634 f.return_converter.type == 'PyObject *')
635
636 positional = parameters and (parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY)
637 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
638 first_optional = len(parameters)
639 for i, p in enumerate(parameters):
640 c = p.converter
641 if type(c) != object_converter:
642 break
643 if c.format_unit != 'O':
644 break
645 if p.default is not unspecified:
646 first_optional = min(first_optional, i)
647 else:
648 all_boring_objects = True
649
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800650 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
651
Larry Hastingsbebf7352014-01-17 17:47:17 -0800652 meth_o = (len(parameters) == 1 and
653 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
654 not converters[0].is_optional() and
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800655 not new_or_init)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800656
Larry Hastings7726ac92014-01-31 22:03:12 -0800657 # we have to set these things before we're done:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800658 #
659 # docstring_prototype
660 # docstring_definition
661 # impl_prototype
662 # methoddef_define
663 # parser_prototype
664 # parser_definition
665 # impl_definition
Larry Hastings7726ac92014-01-31 22:03:12 -0800666 # cpp_if
667 # cpp_endif
668 # methoddef_ifndef
Larry Hastingsbebf7352014-01-17 17:47:17 -0800669
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800670 return_value_declaration = "PyObject *return_value = NULL;"
Larry Hastings31826802013-10-19 00:09:25 -0700671
Larry Hastings7726ac92014-01-31 22:03:12 -0800672 methoddef_define = normalize_snippet("""
673 #define {methoddef_name} \\
674 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
675 """)
Larry Hastings5c661892014-01-24 06:17:25 -0800676 if new_or_init and not f.docstring:
677 docstring_prototype = docstring_definition = ''
678 else:
Larry Hastings7726ac92014-01-31 22:03:12 -0800679 docstring_prototype = normalize_snippet("""
680 PyDoc_VAR({c_basename}__doc__);
681 """)
682 docstring_definition = normalize_snippet("""
683 PyDoc_STRVAR({c_basename}__doc__,
684 {docstring});
685 """)
686 impl_definition = normalize_snippet("""
687 static {impl_return_type}
688 {c_basename}_impl({impl_parameters})
689 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800690 impl_prototype = parser_prototype = parser_definition = None
691
Larry Hastings7726ac92014-01-31 22:03:12 -0800692 parser_prototype_keyword = normalize_snippet("""
693 static PyObject *
694 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
695 """)
696
697 parser_prototype_varargs = normalize_snippet("""
698 static PyObject *
699 {c_basename}({self_type}{self_name}, PyObject *args)
700 """)
701
702 # parser_body_fields remembers the fields passed in to the
703 # previous call to parser_body. this is used for an awful hack.
Larry Hastingsc2047262014-01-25 20:43:29 -0800704 parser_body_fields = ()
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800705 def parser_body(prototype, *fields):
706 nonlocal parser_body_fields
707 add, output = text_accumulator()
708 add(prototype)
709 parser_body_fields = fields
Larry Hastings7726ac92014-01-31 22:03:12 -0800710
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800711 fields = list(fields)
Larry Hastings7726ac92014-01-31 22:03:12 -0800712 fields.insert(0, normalize_snippet("""
713 {{
714 {return_value_declaration}
715 {declarations}
716 {initializers}
717 """) + "\n")
718 # just imagine--your code is here in the middle
719 fields.append(normalize_snippet("""
720 {modifications}
721 {return_value} = {c_basename}_impl({impl_arguments});
722 {return_conversion}
723
724 {exit_label}
725 {cleanup}
726 return return_value;
727 }}
728 """))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800729 for field in fields:
730 add('\n')
Larry Hastings7726ac92014-01-31 22:03:12 -0800731 add(field)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800732 return output()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800733
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800734 def insert_keywords(s):
735 return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
Larry Hastingsbebf7352014-01-17 17:47:17 -0800736
737 if not parameters:
738 # no parameters, METH_NOARGS
739
740 flags = "METH_NOARGS"
741
Larry Hastings7726ac92014-01-31 22:03:12 -0800742 parser_prototype = normalize_snippet("""
743 static PyObject *
744 {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
745 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800746 parser_definition = parser_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800747
748 if default_return_converter:
Larry Hastings7726ac92014-01-31 22:03:12 -0800749 parser_definition = parser_prototype + '\n' + normalize_snippet("""
750 {{
751 return {c_basename}_impl({impl_arguments});
752 }}
753 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800754 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800755 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700756
Larry Hastingsbebf7352014-01-17 17:47:17 -0800757 elif meth_o:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800758 flags = "METH_O"
Larry Hastings7726ac92014-01-31 22:03:12 -0800759
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300760 if (isinstance(converters[0], object_converter) and
761 converters[0].format_unit == 'O'):
762 meth_o_prototype = normalize_snippet("""
763 static PyObject *
764 {c_basename}({impl_parameters})
765 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800766
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300767 if default_return_converter:
768 # maps perfectly to METH_O, doesn't need a return converter.
769 # so we skip making a parse function
770 # and call directly into the impl function.
771 impl_prototype = parser_prototype = parser_definition = ''
772 impl_definition = meth_o_prototype
773 else:
774 # SLIGHT HACK
775 # use impl_parameters for the parser here!
776 parser_prototype = meth_o_prototype
777 parser_definition = parser_body(parser_prototype)
778
Larry Hastingsbebf7352014-01-17 17:47:17 -0800779 else:
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300780 argname = 'arg'
781 if parameters[0].name == argname:
782 argname += '_'
783 parser_prototype = normalize_snippet("""
784 static PyObject *
785 {c_basename}({self_type}{self_name}, PyObject *%s)
786 """ % argname)
787
788 parser_definition = parser_body(parser_prototype, normalize_snippet("""
789 if (!PyArg_Parse(%s,
790 "{format_units}:{name}",
791 {parse_arguments}))
792 goto exit;
793 """ % argname, indent=4))
Larry Hastings31826802013-10-19 00:09:25 -0700794
Larry Hastingsbebf7352014-01-17 17:47:17 -0800795 elif has_option_groups:
796 # positional parameters with option groups
797 # (we have to generate lots of PyArg_ParseTuple calls
798 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700799
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800800 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800801 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700802
Larry Hastings7726ac92014-01-31 22:03:12 -0800803 parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')
Larry Hastings31826802013-10-19 00:09:25 -0700804
Larry Hastingsbebf7352014-01-17 17:47:17 -0800805 elif positional and all_boring_objects:
806 # positional-only, but no option groups,
807 # and nothing but normal objects:
808 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700809
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800810 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800811 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700812
Larry Hastings7726ac92014-01-31 22:03:12 -0800813 parser_definition = parser_body(parser_prototype, normalize_snippet("""
814 if (!PyArg_UnpackTuple(args, "{name}",
815 {unpack_min}, {unpack_max},
816 {parse_arguments}))
817 goto exit;
818 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800819
820 elif positional:
821 # positional-only, but no option groups
822 # we only need one call to PyArg_ParseTuple
823
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800824 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800825 parser_prototype = parser_prototype_varargs
Larry Hastingsbebf7352014-01-17 17:47:17 -0800826
Larry Hastings7726ac92014-01-31 22:03:12 -0800827 parser_definition = parser_body(parser_prototype, normalize_snippet("""
828 if (!PyArg_ParseTuple(args,
829 "{format_units}:{name}",
830 {parse_arguments}))
831 goto exit;
832 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800833
834 else:
835 # positional-or-keyword arguments
836 flags = "METH_VARARGS|METH_KEYWORDS"
837
Larry Hastings7726ac92014-01-31 22:03:12 -0800838 parser_prototype = parser_prototype_keyword
Larry Hastingsbebf7352014-01-17 17:47:17 -0800839
Larry Hastings7726ac92014-01-31 22:03:12 -0800840 body = normalize_snippet("""
841 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
842 "{format_units}:{name}", _keywords,
843 {parse_arguments}))
844 goto exit;
845 """, indent=4)
846 parser_definition = parser_body(parser_prototype, normalize_snippet("""
847 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
848 "{format_units}:{name}", _keywords,
849 {parse_arguments}))
850 goto exit;
851 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800852 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700853
Larry Hastings31826802013-10-19 00:09:25 -0700854
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800855 if new_or_init:
856 methoddef_define = ''
857
858 if f.kind == METHOD_NEW:
Larry Hastings7726ac92014-01-31 22:03:12 -0800859 parser_prototype = parser_prototype_keyword
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800860 else:
861 return_value_declaration = "int return_value = -1;"
Larry Hastings7726ac92014-01-31 22:03:12 -0800862 parser_prototype = normalize_snippet("""
863 static int
864 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
865 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800866
867 fields = list(parser_body_fields)
868 parses_positional = 'METH_NOARGS' not in flags
869 parses_keywords = 'METH_KEYWORDS' in flags
870 if parses_keywords:
871 assert parses_positional
872
873 if not parses_keywords:
Larry Hastings7726ac92014-01-31 22:03:12 -0800874 fields.insert(0, normalize_snippet("""
875 if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs))
876 goto exit;
877 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800878 if not parses_positional:
Larry Hastings7726ac92014-01-31 22:03:12 -0800879 fields.insert(0, normalize_snippet("""
880 if ({self_type_check}!_PyArg_NoPositional("{name}", args))
881 goto exit;
882 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800883
884 parser_definition = parser_body(parser_prototype, *fields)
885 if parses_keywords:
886 parser_definition = insert_keywords(parser_definition)
887
Larry Hastings31826802013-10-19 00:09:25 -0700888
Larry Hastingsbebf7352014-01-17 17:47:17 -0800889 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800890 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700891
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800892 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700893
Larry Hastings7726ac92014-01-31 22:03:12 -0800894 methoddef_ifndef = ''
895 conditional = self.cpp.condition()
896 if not conditional:
897 cpp_if = cpp_endif = ''
898 else:
899 cpp_if = "#if " + conditional
900 cpp_endif = "#endif /* " + conditional + " */"
901
Larry Hastings0759f842015-04-03 13:09:02 -0700902 if methoddef_define and f.name not in clinic.ifndef_symbols:
903 clinic.ifndef_symbols.add(f.name)
Larry Hastings7726ac92014-01-31 22:03:12 -0800904 methoddef_ifndef = normalize_snippet("""
905 #ifndef {methoddef_name}
906 #define {methoddef_name}
907 #endif /* !defined({methoddef_name}) */
908 """)
909
910
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800911 # add ';' to the end of parser_prototype and impl_prototype
912 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800913 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800914 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800915 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800916 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700917
Larry Hastingsbebf7352014-01-17 17:47:17 -0800918 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800919 impl_prototype = impl_definition
920 if impl_prototype:
921 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700922
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800923 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800924
925 d = {
926 "docstring_prototype" : docstring_prototype,
927 "docstring_definition" : docstring_definition,
928 "impl_prototype" : impl_prototype,
929 "methoddef_define" : methoddef_define,
930 "parser_prototype" : parser_prototype,
931 "parser_definition" : parser_definition,
932 "impl_definition" : impl_definition,
Larry Hastings7726ac92014-01-31 22:03:12 -0800933 "cpp_if" : cpp_if,
934 "cpp_endif" : cpp_endif,
935 "methoddef_ifndef" : methoddef_ifndef,
Larry Hastingsbebf7352014-01-17 17:47:17 -0800936 }
937
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800938 # make sure we didn't forget to assign something,
939 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -0800940 d2 = {}
941 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800942 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800943 if value:
944 value = '\n' + value + '\n'
945 d2[name] = value
946 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700947
948 @staticmethod
949 def group_to_variable_name(group):
950 adjective = "left_" if group < 0 else "right_"
951 return "group_" + adjective + str(abs(group))
952
953 def render_option_group_parsing(self, f, template_dict):
954 # positional only, grouped, optional arguments!
955 # can be optional on the left or right.
956 # here's an example:
957 #
958 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
959 #
960 # Here group D are required, and all other groups are optional.
961 # (Group D's "group" is actually None.)
962 # We can figure out which sets of arguments we have based on
963 # how many arguments are in the tuple.
964 #
965 # Note that you need to count up on both sides. For example,
966 # you could have groups C+D, or C+D+E, or C+D+E+F.
967 #
968 # What if the number of arguments leads us to an ambiguous result?
969 # Clinic prefers groups on the left. So in the above example,
970 # five arguments would map to B+C, not C+D.
971
972 add, output = text_accumulator()
973 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800974 if isinstance(parameters[0].converter, self_converter):
975 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -0700976
977 groups = []
978 group = None
979 left = []
980 right = []
981 required = []
982 last = unspecified
983
984 for p in parameters:
985 group_id = p.group
986 if group_id != last:
987 last = group_id
988 group = []
989 if group_id < 0:
990 left.append(group)
991 elif group_id == 0:
992 group = required
993 else:
994 right.append(group)
995 group.append(p)
996
997 count_min = sys.maxsize
998 count_max = -1
999
Larry Hastings2a727912014-01-16 11:32:01 -08001000 add("switch (PyTuple_GET_SIZE(args)) {{\n")
Larry Hastings31826802013-10-19 00:09:25 -07001001 for subset in permute_optional_groups(left, required, right):
1002 count = len(subset)
1003 count_min = min(count_min, count)
1004 count_max = max(count_max, count)
1005
Larry Hastings583baa82014-01-12 08:49:30 -08001006 if count == 0:
1007 add(""" case 0:
1008 break;
1009""")
1010 continue
1011
Larry Hastings31826802013-10-19 00:09:25 -07001012 group_ids = {p.group for p in subset} # eliminate duplicates
1013 d = {}
1014 d['count'] = count
1015 d['name'] = f.name
1016 d['groups'] = sorted(group_ids)
1017 d['format_units'] = "".join(p.converter.format_unit for p in subset)
1018
1019 parse_arguments = []
1020 for p in subset:
1021 p.converter.parse_argument(parse_arguments)
1022 d['parse_arguments'] = ", ".join(parse_arguments)
1023
1024 group_ids.discard(0)
1025 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
1026 lines = "\n".join(lines)
1027
1028 s = """
1029 case {count}:
1030 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
Larry Hastings46258262014-01-22 03:05:49 -08001031 goto exit;
Larry Hastings31826802013-10-19 00:09:25 -07001032 {group_booleans}
1033 break;
1034"""[1:]
1035 s = linear_format(s, group_booleans=lines)
1036 s = s.format_map(d)
1037 add(s)
1038
1039 add(" default:\n")
1040 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
1041 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -08001042 add(' goto exit;\n')
Larry Hastings31826802013-10-19 00:09:25 -07001043 add("}}")
1044 template_dict['option_group_parsing'] = output()
1045
Larry Hastingsbebf7352014-01-17 17:47:17 -08001046 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -07001047 if not f:
1048 return ""
1049
1050 add, output = text_accumulator()
1051 data = CRenderData()
1052
Larry Hastings7726ac92014-01-31 22:03:12 -08001053 assert f.parameters, "We should always have a 'self' at this point!"
1054 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07001055 converters = [p.converter for p in parameters]
1056
Larry Hastings5c661892014-01-24 06:17:25 -08001057 templates = self.output_templates(f)
1058
1059 f_self = parameters[0]
1060 selfless = parameters[1:]
1061 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
1062
1063 last_group = 0
1064 first_optional = len(selfless)
1065 positional = selfless and selfless[-1].kind == inspect.Parameter.POSITIONAL_ONLY
1066 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
1067 default_return_converter = (not f.return_converter or
1068 f.return_converter.type == 'PyObject *')
1069 has_option_groups = False
1070
1071 # offset i by -1 because first_optional needs to ignore self
1072 for i, p in enumerate(parameters, -1):
1073 c = p.converter
1074
1075 if (i != -1) and (p.default is not unspecified):
1076 first_optional = min(first_optional, i)
1077
1078 # insert group variable
1079 group = p.group
1080 if last_group != group:
1081 last_group = group
1082 if group:
1083 group_name = self.group_to_variable_name(group)
1084 data.impl_arguments.append(group_name)
1085 data.declarations.append("int " + group_name + " = 0;")
1086 data.impl_parameters.append("int " + group_name)
1087 has_option_groups = True
1088
1089 c.render(p, data)
1090
1091 if has_option_groups and (not positional):
1092 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
1093
1094 # HACK
1095 # when we're METH_O, but have a custom return converter,
1096 # we use "impl_parameters" for the parsing function
1097 # because that works better. but that means we must
Berker Peksagf23530f2014-10-19 18:04:38 +03001098 # suppress actually declaring the impl's parameters
Larry Hastings5c661892014-01-24 06:17:25 -08001099 # as variables in the parsing function. but since it's
1100 # METH_O, we have exactly one anyway, so we know exactly
1101 # where it is.
1102 if ("METH_O" in templates['methoddef_define'] and
Serhiy Storchaka92e8af62015-04-04 00:12:11 +03001103 '{impl_parameters}' in templates['parser_prototype']):
Larry Hastings5c661892014-01-24 06:17:25 -08001104 data.declarations.pop(0)
1105
Larry Hastings31826802013-10-19 00:09:25 -07001106 template_dict = {}
1107
1108 full_name = f.full_name
1109 template_dict['full_name'] = full_name
1110
Larry Hastings5c661892014-01-24 06:17:25 -08001111 if new_or_init:
1112 name = f.cls.name
1113 else:
1114 name = f.name
1115
Larry Hastings31826802013-10-19 00:09:25 -07001116 template_dict['name'] = name
1117
Larry Hastings8666e652014-01-12 14:12:59 -08001118 if f.c_basename:
1119 c_basename = f.c_basename
1120 else:
1121 fields = full_name.split(".")
1122 if fields[-1] == '__new__':
1123 fields.pop()
1124 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001125
Larry Hastings31826802013-10-19 00:09:25 -07001126 template_dict['c_basename'] = c_basename
1127
1128 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1129 template_dict['methoddef_name'] = methoddef_name
1130
1131 template_dict['docstring'] = self.docstring_for_c_string(f)
1132
Larry Hastingsc2047262014-01-25 20:43:29 -08001133 template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
Larry Hastings5c661892014-01-24 06:17:25 -08001134 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001135
Larry Hastings31826802013-10-19 00:09:25 -07001136 f.return_converter.render(f, data)
1137 template_dict['impl_return_type'] = f.return_converter.type
1138
1139 template_dict['declarations'] = "\n".join(data.declarations)
1140 template_dict['initializers'] = "\n\n".join(data.initializers)
Larry Hastingsc2047262014-01-25 20:43:29 -08001141 template_dict['modifications'] = '\n\n'.join(data.modifications)
Larry Hastings31826802013-10-19 00:09:25 -07001142 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1143 template_dict['format_units'] = ''.join(data.format_units)
1144 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1145 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1146 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
1147 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
1148 template_dict['cleanup'] = "".join(data.cleanup)
1149 template_dict['return_value'] = data.return_value
1150
Larry Hastings5c661892014-01-24 06:17:25 -08001151 # used by unpack tuple code generator
1152 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1153 unpack_min = first_optional
1154 unpack_max = len(selfless)
1155 template_dict['unpack_min'] = str(unpack_min)
1156 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001157
Larry Hastingsbebf7352014-01-17 17:47:17 -08001158 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001159 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001160
Larry Hastings0759f842015-04-03 13:09:02 -07001161 # buffers, not destination
1162 for name, destination in clinic.destination_buffers.items():
Larry Hastingsbebf7352014-01-17 17:47:17 -08001163 template = templates[name]
1164 if has_option_groups:
1165 template = linear_format(template,
1166 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001167 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001168 declarations=template_dict['declarations'],
1169 return_conversion=template_dict['return_conversion'],
1170 initializers=template_dict['initializers'],
Larry Hastingsc2047262014-01-25 20:43:29 -08001171 modifications=template_dict['modifications'],
Larry Hastingsbebf7352014-01-17 17:47:17 -08001172 cleanup=template_dict['cleanup'],
1173 )
Larry Hastings31826802013-10-19 00:09:25 -07001174
Larry Hastingsbebf7352014-01-17 17:47:17 -08001175 # Only generate the "exit:" label
1176 # if we have any gotos
1177 need_exit_label = "goto exit;" in template
1178 template = linear_format(template,
1179 exit_label="exit:" if need_exit_label else ''
1180 )
Larry Hastings31826802013-10-19 00:09:25 -07001181
Larry Hastingsbebf7352014-01-17 17:47:17 -08001182 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001183
Larry Hastings89964c42015-04-14 18:07:59 -04001184 # mild hack:
1185 # reflow long impl declarations
1186 if name in {"impl_prototype", "impl_definition"}:
1187 s = wrap_declarations(s)
1188
Larry Hastingsbebf7352014-01-17 17:47:17 -08001189 if clinic.line_prefix:
1190 s = indent_all_lines(s, clinic.line_prefix)
1191 if clinic.line_suffix:
1192 s = suffix_all_lines(s, clinic.line_suffix)
1193
1194 destination.append(s)
1195
1196 return clinic.get_destination('block').dump()
1197
Larry Hastings31826802013-10-19 00:09:25 -07001198
1199
Larry Hastings5c661892014-01-24 06:17:25 -08001200
Larry Hastings31826802013-10-19 00:09:25 -07001201@contextlib.contextmanager
1202def OverrideStdioWith(stdout):
1203 saved_stdout = sys.stdout
1204 sys.stdout = stdout
1205 try:
1206 yield
1207 finally:
1208 assert sys.stdout is stdout
1209 sys.stdout = saved_stdout
1210
1211
Larry Hastings2623c8c2014-02-08 22:15:29 -08001212def create_regex(before, after, word=True, whole_line=True):
Larry Hastings31826802013-10-19 00:09:25 -07001213 """Create an re object for matching marker lines."""
Larry Hastings581ee362014-01-28 05:00:08 -08001214 group_re = "\w+" if word else ".+"
Larry Hastings2623c8c2014-02-08 22:15:29 -08001215 pattern = r'{}({}){}'
1216 if whole_line:
1217 pattern = '^' + pattern + '$'
Larry Hastings581ee362014-01-28 05:00:08 -08001218 pattern = pattern.format(re.escape(before), group_re, re.escape(after))
1219 return re.compile(pattern)
Larry Hastings31826802013-10-19 00:09:25 -07001220
1221
1222class Block:
1223 r"""
1224 Represents a single block of text embedded in
1225 another file. If dsl_name is None, the block represents
1226 verbatim text, raw original text from the file, in
1227 which case "input" will be the only non-false member.
1228 If dsl_name is not None, the block represents a Clinic
1229 block.
1230
1231 input is always str, with embedded \n characters.
1232 input represents the original text from the file;
1233 if it's a Clinic block, it is the original text with
1234 the body_prefix and redundant leading whitespace removed.
1235
1236 dsl_name is either str or None. If str, it's the text
1237 found on the start line of the block between the square
1238 brackets.
1239
1240 signatures is either list or None. If it's a list,
1241 it may only contain clinic.Module, clinic.Class, and
1242 clinic.Function objects. At the moment it should
1243 contain at most one of each.
1244
1245 output is either str or None. If str, it's the output
1246 from this block, with embedded '\n' characters.
1247
1248 indent is either str or None. It's the leading whitespace
1249 that was found on every line of input. (If body_prefix is
1250 not empty, this is the indent *after* removing the
1251 body_prefix.)
1252
1253 preindent is either str or None. It's the whitespace that
1254 was found in front of every line of input *before* the
1255 "body_prefix" (see the Language object). If body_prefix
1256 is empty, preindent must always be empty too.
1257
1258 To illustrate indent and preindent: Assume that '_'
1259 represents whitespace. If the block processed was in a
1260 Python file, and looked like this:
1261 ____#/*[python]
1262 ____#__for a in range(20):
1263 ____#____print(a)
1264 ____#[python]*/
1265 "preindent" would be "____" and "indent" would be "__".
1266
1267 """
1268 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1269 assert isinstance(input, str)
1270 self.input = input
1271 self.dsl_name = dsl_name
1272 self.signatures = signatures or []
1273 self.output = output
1274 self.indent = indent
1275 self.preindent = preindent
1276
Larry Hastings581ee362014-01-28 05:00:08 -08001277 def __repr__(self):
1278 dsl_name = self.dsl_name or "text"
1279 def summarize(s):
1280 s = repr(s)
1281 if len(s) > 30:
1282 return s[:26] + "..." + s[0]
1283 return s
1284 return "".join((
1285 "<Block ", dsl_name, " input=", summarize(self.input), " output=", summarize(self.output), ">"))
1286
Larry Hastings31826802013-10-19 00:09:25 -07001287
1288class BlockParser:
1289 """
1290 Block-oriented parser for Argument Clinic.
1291 Iterator, yields Block objects.
1292 """
1293
1294 def __init__(self, input, language, *, verify=True):
1295 """
1296 "input" should be a str object
1297 with embedded \n characters.
1298
1299 "language" should be a Language object.
1300 """
1301 language.validate()
1302
1303 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1304 self.block_start_line_number = self.line_number = 0
1305
1306 self.language = language
1307 before, _, after = language.start_line.partition('{dsl_name}')
1308 assert _ == '{dsl_name}'
Larry Hastings2623c8c2014-02-08 22:15:29 -08001309 self.find_start_re = create_regex(before, after, whole_line=False)
Larry Hastings31826802013-10-19 00:09:25 -07001310 self.start_re = create_regex(before, after)
1311 self.verify = verify
1312 self.last_checksum_re = None
1313 self.last_dsl_name = None
1314 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001315 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001316
1317 def __iter__(self):
1318 return self
1319
1320 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001321 while True:
1322 if not self.input:
1323 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001324
Larry Hastingsbebf7352014-01-17 17:47:17 -08001325 if self.dsl_name:
1326 return_value = self.parse_clinic_block(self.dsl_name)
1327 self.dsl_name = None
1328 self.first_block = False
1329 return return_value
1330 block = self.parse_verbatim_block()
1331 if self.first_block and not block.input:
1332 continue
1333 self.first_block = False
1334 return block
1335
Larry Hastings31826802013-10-19 00:09:25 -07001336
1337 def is_start_line(self, line):
1338 match = self.start_re.match(line.lstrip())
1339 return match.group(1) if match else None
1340
Larry Hastingse1b82532014-07-27 16:22:20 +02001341 def _line(self, lookahead=False):
Larry Hastings31826802013-10-19 00:09:25 -07001342 self.line_number += 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001343 line = self.input.pop()
Larry Hastingse1b82532014-07-27 16:22:20 +02001344 if not lookahead:
1345 self.language.parse_line(line)
Larry Hastings7726ac92014-01-31 22:03:12 -08001346 return line
Larry Hastings31826802013-10-19 00:09:25 -07001347
1348 def parse_verbatim_block(self):
1349 add, output = text_accumulator()
1350 self.block_start_line_number = self.line_number
1351
1352 while self.input:
1353 line = self._line()
1354 dsl_name = self.is_start_line(line)
1355 if dsl_name:
1356 self.dsl_name = dsl_name
1357 break
1358 add(line)
1359
1360 return Block(output())
1361
1362 def parse_clinic_block(self, dsl_name):
1363 input_add, input_output = text_accumulator()
1364 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001365 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001366 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1367
Larry Hastings90261132014-01-07 12:21:08 -08001368 def is_stop_line(line):
1369 # make sure to recognize stop line even if it
1370 # doesn't end with EOL (it could be the very end of the file)
1371 if not line.startswith(stop_line):
1372 return False
1373 remainder = line[len(stop_line):]
1374 return (not remainder) or remainder.isspace()
1375
Larry Hastings31826802013-10-19 00:09:25 -07001376 # consume body of program
1377 while self.input:
1378 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001379 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001380 break
1381 if body_prefix:
1382 line = line.lstrip()
1383 assert line.startswith(body_prefix)
1384 line = line[len(body_prefix):]
1385 input_add(line)
1386
1387 # consume output and checksum line, if present.
1388 if self.last_dsl_name == dsl_name:
1389 checksum_re = self.last_checksum_re
1390 else:
Larry Hastings581ee362014-01-28 05:00:08 -08001391 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, arguments='{arguments}').partition('{arguments}')
1392 assert _ == '{arguments}'
1393 checksum_re = create_regex(before, after, word=False)
Larry Hastings31826802013-10-19 00:09:25 -07001394 self.last_dsl_name = dsl_name
1395 self.last_checksum_re = checksum_re
1396
1397 # scan forward for checksum line
1398 output_add, output_output = text_accumulator()
Larry Hastings581ee362014-01-28 05:00:08 -08001399 arguments = None
Larry Hastings31826802013-10-19 00:09:25 -07001400 while self.input:
Larry Hastingse1b82532014-07-27 16:22:20 +02001401 line = self._line(lookahead=True)
Larry Hastings31826802013-10-19 00:09:25 -07001402 match = checksum_re.match(line.lstrip())
Larry Hastings581ee362014-01-28 05:00:08 -08001403 arguments = match.group(1) if match else None
1404 if arguments:
Larry Hastings31826802013-10-19 00:09:25 -07001405 break
1406 output_add(line)
1407 if self.is_start_line(line):
1408 break
1409
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001410 output = output_output()
Larry Hastings581ee362014-01-28 05:00:08 -08001411 if arguments:
1412 d = {}
1413 for field in shlex.split(arguments):
1414 name, equals, value = field.partition('=')
1415 if not equals:
1416 fail("Mangled Argument Clinic marker line: {!r}".format(line))
1417 d[name.strip()] = value.strip()
1418
Larry Hastings31826802013-10-19 00:09:25 -07001419 if self.verify:
Larry Hastings581ee362014-01-28 05:00:08 -08001420 if 'input' in d:
1421 checksum = d['output']
1422 input_checksum = d['input']
1423 else:
1424 checksum = d['checksum']
1425 input_checksum = None
1426
1427 computed = compute_checksum(output, len(checksum))
Larry Hastings31826802013-10-19 00:09:25 -07001428 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001429 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1430 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001431 "the end marker,\n"
1432 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001433 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001434 else:
1435 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001436 output_lines = output.splitlines(keepends=True)
1437 self.line_number -= len(output_lines)
1438 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001439 output = None
1440
1441 return Block(input_output(), dsl_name, output=output)
1442
1443
1444class BlockPrinter:
1445
1446 def __init__(self, language, f=None):
1447 self.language = language
1448 self.f = f or io.StringIO()
1449
1450 def print_block(self, block):
1451 input = block.input
1452 output = block.output
1453 dsl_name = block.dsl_name
1454 write = self.f.write
1455
Larry Hastings31826802013-10-19 00:09:25 -07001456 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1457
1458 if not dsl_name:
1459 write(input)
1460 return
1461
1462 write(self.language.start_line.format(dsl_name=dsl_name))
1463 write("\n")
1464
1465 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1466 if not body_prefix:
1467 write(input)
1468 else:
1469 for line in input.split('\n'):
1470 write(body_prefix)
1471 write(line)
1472 write("\n")
1473
1474 write(self.language.stop_line.format(dsl_name=dsl_name))
1475 write("\n")
1476
Larry Hastings581ee362014-01-28 05:00:08 -08001477 input = ''.join(block.input)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001478 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001479 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001480 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001481 output += '\n'
1482 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001483
Larry Hastings581ee362014-01-28 05:00:08 -08001484 arguments="output={} input={}".format(compute_checksum(output, 16), compute_checksum(input, 16))
1485 write(self.language.checksum_line.format(dsl_name=dsl_name, arguments=arguments))
Larry Hastings31826802013-10-19 00:09:25 -07001486 write("\n")
1487
Larry Hastingsbebf7352014-01-17 17:47:17 -08001488 def write(self, text):
1489 self.f.write(text)
1490
1491
Larry Hastings0759f842015-04-03 13:09:02 -07001492class BufferSeries:
1493 """
1494 Behaves like a "defaultlist".
1495 When you ask for an index that doesn't exist yet,
1496 the object grows the list until that item exists.
1497 So o[n] will always work.
1498
1499 Supports negative indices for actual items.
1500 e.g. o[-1] is an element immediately preceding o[0].
1501 """
1502
1503 def __init__(self):
1504 self._start = 0
1505 self._array = []
1506 self._constructor = _text_accumulator
1507
1508 def __getitem__(self, i):
1509 i -= self._start
1510 if i < 0:
1511 self._start += i
1512 prefix = [self._constructor() for x in range(-i)]
1513 self._array = prefix + self._array
1514 i = 0
1515 while i >= len(self._array):
1516 self._array.append(self._constructor())
1517 return self._array[i]
1518
1519 def clear(self):
1520 for ta in self._array:
1521 ta._text.clear()
1522
1523 def dump(self):
1524 texts = [ta.output() for ta in self._array]
1525 return "".join(texts)
1526
1527
Larry Hastingsbebf7352014-01-17 17:47:17 -08001528class Destination:
1529 def __init__(self, name, type, clinic, *args):
1530 self.name = name
1531 self.type = type
1532 self.clinic = clinic
Larry Hastings0759f842015-04-03 13:09:02 -07001533 valid_types = ('buffer', 'file', 'suppress')
Larry Hastingsbebf7352014-01-17 17:47:17 -08001534 if type not in valid_types:
1535 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1536 extra_arguments = 1 if type == "file" else 0
1537 if len(args) < extra_arguments:
1538 fail("Not enough arguments for destination " + name + " new " + type)
1539 if len(args) > extra_arguments:
1540 fail("Too many arguments for destination " + name + " new " + type)
1541 if type =='file':
1542 d = {}
Larry Hastingsc2047262014-01-25 20:43:29 -08001543 filename = clinic.filename
1544 d['path'] = filename
1545 dirname, basename = os.path.split(filename)
1546 if not dirname:
1547 dirname = '.'
1548 d['dirname'] = dirname
1549 d['basename'] = basename
1550 d['basename_root'], d['basename_extension'] = os.path.splitext(filename)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001551 self.filename = args[0].format_map(d)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001552
Larry Hastings0759f842015-04-03 13:09:02 -07001553 self.buffers = BufferSeries()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001554
1555 def __repr__(self):
1556 if self.type == 'file':
1557 file_repr = " " + repr(self.filename)
1558 else:
1559 file_repr = ''
1560 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1561
1562 def clear(self):
1563 if self.type != 'buffer':
1564 fail("Can't clear destination" + self.name + " , it's not of type buffer")
Larry Hastings0759f842015-04-03 13:09:02 -07001565 self.buffers.clear()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001566
1567 def dump(self):
Larry Hastings0759f842015-04-03 13:09:02 -07001568 return self.buffers.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001569
Larry Hastings31826802013-10-19 00:09:25 -07001570
1571# maps strings to Language objects.
1572# "languages" maps the name of the language ("C", "Python").
1573# "extensions" maps the file extension ("c", "py").
1574languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001575extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1576extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001577
1578
1579# maps strings to callables.
1580# these callables must be of the form:
1581# def foo(name, default, *, ...)
1582# The callable may have any number of keyword-only parameters.
1583# The callable must return a CConverter object.
1584# The callable should not call builtins.print.
1585converters = {}
1586
1587# maps strings to callables.
1588# these callables follow the same rules as those for "converters" above.
1589# note however that they will never be called with keyword-only parameters.
1590legacy_converters = {}
1591
1592
1593# maps strings to callables.
1594# these callables must be of the form:
1595# def foo(*, ...)
1596# The callable may have any number of keyword-only parameters.
1597# The callable must return a CConverter object.
1598# The callable should not call builtins.print.
1599return_converters = {}
1600
Larry Hastings7726ac92014-01-31 22:03:12 -08001601clinic = None
Larry Hastings31826802013-10-19 00:09:25 -07001602class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001603
1604 presets_text = """
Larry Hastings7726ac92014-01-31 22:03:12 -08001605preset block
1606everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001607methoddef_ifndef buffer 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001608docstring_prototype suppress
1609parser_prototype suppress
1610cpp_if suppress
1611cpp_endif suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001612
Larry Hastingsbebf7352014-01-17 17:47:17 -08001613preset original
1614everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001615methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001616docstring_prototype suppress
1617parser_prototype suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001618cpp_if suppress
1619cpp_endif suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001620
1621preset file
1622everything file
Larry Hastings0759f842015-04-03 13:09:02 -07001623methoddef_ifndef file 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001624docstring_prototype suppress
1625parser_prototype suppress
1626impl_definition block
1627
1628preset buffer
1629everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001630methoddef_ifndef buffer 1
1631impl_definition block
Larry Hastingsbebf7352014-01-17 17:47:17 -08001632docstring_prototype suppress
1633impl_prototype suppress
1634parser_prototype suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001635
1636preset partial-buffer
1637everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001638methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001639docstring_prototype block
1640impl_prototype suppress
1641methoddef_define block
1642parser_prototype block
1643impl_definition block
1644
Larry Hastingsbebf7352014-01-17 17:47:17 -08001645"""
1646
Larry Hastings581ee362014-01-28 05:00:08 -08001647 def __init__(self, language, printer=None, *, force=False, verify=True, filename=None):
Larry Hastings31826802013-10-19 00:09:25 -07001648 # maps strings to Parser objects.
1649 # (instantiated from the "parsers" global.)
1650 self.parsers = {}
1651 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001652 if printer:
1653 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001654 self.printer = printer or BlockPrinter(language)
1655 self.verify = verify
Larry Hastings581ee362014-01-28 05:00:08 -08001656 self.force = force
Larry Hastings31826802013-10-19 00:09:25 -07001657 self.filename = filename
1658 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001659 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001660 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001661
Larry Hastingsbebf7352014-01-17 17:47:17 -08001662 self.line_prefix = self.line_suffix = ''
1663
1664 self.destinations = {}
1665 self.add_destination("block", "buffer")
1666 self.add_destination("suppress", "suppress")
1667 self.add_destination("buffer", "buffer")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001668 if filename:
Larry Hastingsc2047262014-01-25 20:43:29 -08001669 self.add_destination("file", "file", "{dirname}/clinic/{basename}.h")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001670
Larry Hastings0759f842015-04-03 13:09:02 -07001671 d = self.get_destination_buffer
1672 self.destination_buffers = collections.OrderedDict((
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001673 ('cpp_if', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001674 ('docstring_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001675 ('docstring_definition', d('file')),
1676 ('methoddef_define', d('file')),
1677 ('impl_prototype', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001678 ('parser_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001679 ('parser_definition', d('file')),
1680 ('cpp_endif', d('file')),
1681 ('methoddef_ifndef', d('file', 1)),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001682 ('impl_definition', d('block')),
1683 ))
1684
Larry Hastings0759f842015-04-03 13:09:02 -07001685 self.destination_buffers_stack = []
1686 self.ifndef_symbols = set()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001687
1688 self.presets = {}
1689 preset = None
1690 for line in self.presets_text.strip().split('\n'):
1691 line = line.strip()
1692 if not line:
1693 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001694 name, value, *options = line.split()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001695 if name == 'preset':
1696 self.presets[value] = preset = collections.OrderedDict()
1697 continue
1698
Larry Hastings0759f842015-04-03 13:09:02 -07001699 if len(options):
1700 index = int(options[0])
1701 else:
1702 index = 0
1703 buffer = self.get_destination_buffer(value, index)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001704
1705 if name == 'everything':
Larry Hastings0759f842015-04-03 13:09:02 -07001706 for name in self.destination_buffers:
1707 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001708 continue
1709
Larry Hastings0759f842015-04-03 13:09:02 -07001710 assert name in self.destination_buffers
1711 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001712
Larry Hastings31826802013-10-19 00:09:25 -07001713 global clinic
1714 clinic = self
1715
Larry Hastingsbebf7352014-01-17 17:47:17 -08001716 def add_destination(self, name, type, *args):
1717 if name in self.destinations:
1718 fail("Destination already exists: " + repr(name))
1719 self.destinations[name] = Destination(name, type, self, *args)
1720
Larry Hastings0759f842015-04-03 13:09:02 -07001721 def get_destination(self, name):
1722 d = self.destinations.get(name)
1723 if not d:
1724 fail("Destination does not exist: " + repr(name))
1725 return d
1726
1727 def get_destination_buffer(self, name, item=0):
1728 d = self.get_destination(name)
1729 return d.buffers[item]
1730
Larry Hastings31826802013-10-19 00:09:25 -07001731 def parse(self, input):
1732 printer = self.printer
1733 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1734 for block in self.block_parser:
1735 dsl_name = block.dsl_name
1736 if dsl_name:
1737 if dsl_name not in self.parsers:
1738 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1739 self.parsers[dsl_name] = parsers[dsl_name](self)
1740 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001741 try:
1742 parser.parse(block)
1743 except Exception:
1744 fail('Exception raised during parsing:\n' +
1745 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001746 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001747
1748 second_pass_replacements = {}
1749
Larry Hastings0759f842015-04-03 13:09:02 -07001750 # these are destinations not buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08001751 for name, destination in self.destinations.items():
1752 if destination.type == 'suppress':
1753 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001754 output = destination.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001755
1756 if output:
1757
1758 block = Block("", dsl_name="clinic", output=output)
1759
1760 if destination.type == 'buffer':
1761 block.input = "dump " + name + "\n"
1762 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1763 printer.write("\n")
1764 printer.print_block(block)
1765 continue
1766
1767 if destination.type == 'file':
1768 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08001769 dirname = os.path.dirname(destination.filename)
1770 try:
1771 os.makedirs(dirname)
1772 except FileExistsError:
1773 if not os.path.isdir(dirname):
1774 fail("Can't write to destination {}, "
1775 "can't make directory {}!".format(
1776 destination.filename, dirname))
Larry Hastings581ee362014-01-28 05:00:08 -08001777 if self.verify:
1778 with open(destination.filename, "rt") as f:
1779 parser_2 = BlockParser(f.read(), language=self.language)
1780 blocks = list(parser_2)
1781 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1782 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001783 except FileNotFoundError:
1784 pass
1785
1786 block.input = 'preserve\n'
1787 printer_2 = BlockPrinter(self.language)
1788 printer_2.print_block(block)
1789 with open(destination.filename, "wt") as f:
1790 f.write(printer_2.f.getvalue())
1791 continue
1792 text = printer.f.getvalue()
1793
1794 if second_pass_replacements:
1795 printer_2 = BlockPrinter(self.language)
1796 parser_2 = BlockParser(text, self.language)
1797 changed = False
1798 for block in parser_2:
1799 if block.dsl_name:
1800 for id, replacement in second_pass_replacements.items():
1801 if id in block.output:
1802 changed = True
1803 block.output = block.output.replace(id, replacement)
1804 printer_2.print_block(block)
1805 if changed:
1806 text = printer_2.f.getvalue()
1807
1808 return text
1809
Larry Hastings31826802013-10-19 00:09:25 -07001810
1811 def _module_and_class(self, fields):
1812 """
1813 fields should be an iterable of field names.
1814 returns a tuple of (module, class).
1815 the module object could actually be self (a clinic object).
1816 this function is only ever used to find the parent of where
1817 a new class/module should go.
1818 """
1819 in_classes = False
1820 parent = module = self
1821 cls = None
1822 so_far = []
1823
1824 for field in fields:
1825 so_far.append(field)
1826 if not in_classes:
1827 child = parent.modules.get(field)
1828 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001829 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001830 continue
1831 in_classes = True
1832 if not hasattr(parent, 'classes'):
1833 return module, cls
1834 child = parent.classes.get(field)
1835 if not child:
1836 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1837 cls = parent = child
1838
1839 return module, cls
1840
1841
Larry Hastings581ee362014-01-28 05:00:08 -08001842def parse_file(filename, *, force=False, verify=True, output=None, encoding='utf-8'):
Larry Hastings31826802013-10-19 00:09:25 -07001843 extension = os.path.splitext(filename)[1][1:]
1844 if not extension:
1845 fail("Can't extract file type for file " + repr(filename))
1846
1847 try:
Larry Hastings7726ac92014-01-31 22:03:12 -08001848 language = extensions[extension](filename)
Larry Hastings31826802013-10-19 00:09:25 -07001849 except KeyError:
1850 fail("Can't identify file type for file " + repr(filename))
1851
Larry Hastings31826802013-10-19 00:09:25 -07001852 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001853 raw = f.read()
1854
Larry Hastings2623c8c2014-02-08 22:15:29 -08001855 # exit quickly if there are no clinic markers in the file
1856 find_start_re = BlockParser("", language).find_start_re
1857 if not find_start_re.search(raw):
1858 return
1859
1860 clinic = Clinic(language, force=force, verify=verify, filename=filename)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001861 cooked = clinic.parse(raw)
Larry Hastings581ee362014-01-28 05:00:08 -08001862 if (cooked == raw) and not force:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001863 return
Larry Hastings31826802013-10-19 00:09:25 -07001864
1865 directory = os.path.dirname(filename) or '.'
1866
1867 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001868 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001869 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1870 with open(tmpfilename, "wb") as f:
1871 f.write(bytes)
1872 os.replace(tmpfilename, output or filename)
1873
1874
Larry Hastings581ee362014-01-28 05:00:08 -08001875def compute_checksum(input, length=None):
Larry Hastings31826802013-10-19 00:09:25 -07001876 input = input or ''
Larry Hastings581ee362014-01-28 05:00:08 -08001877 s = hashlib.sha1(input.encode('utf-8')).hexdigest()
1878 if length:
1879 s = s[:length]
1880 return s
Larry Hastings31826802013-10-19 00:09:25 -07001881
1882
1883
1884
1885class PythonParser:
1886 def __init__(self, clinic):
1887 pass
1888
1889 def parse(self, block):
1890 s = io.StringIO()
1891 with OverrideStdioWith(s):
1892 exec(block.input)
1893 block.output = s.getvalue()
1894
1895
1896class Module:
1897 def __init__(self, name, module=None):
1898 self.name = name
1899 self.module = self.parent = module
1900
1901 self.modules = collections.OrderedDict()
1902 self.classes = collections.OrderedDict()
1903 self.functions = []
1904
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001905 def __repr__(self):
1906 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1907
Larry Hastings31826802013-10-19 00:09:25 -07001908class Class:
Larry Hastingsc2047262014-01-25 20:43:29 -08001909 def __init__(self, name, module=None, cls=None, typedef=None, type_object=None):
Larry Hastings31826802013-10-19 00:09:25 -07001910 self.name = name
1911 self.module = module
1912 self.cls = cls
Larry Hastingsc2047262014-01-25 20:43:29 -08001913 self.typedef = typedef
1914 self.type_object = type_object
Larry Hastings31826802013-10-19 00:09:25 -07001915 self.parent = cls or module
1916
1917 self.classes = collections.OrderedDict()
1918 self.functions = []
1919
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001920 def __repr__(self):
1921 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1922
Larry Hastings8666e652014-01-12 14:12:59 -08001923unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001924
Larry Hastings8666e652014-01-12 14:12:59 -08001925__abs__
1926__add__
1927__and__
1928__bytes__
1929__call__
1930__complex__
1931__delitem__
1932__divmod__
1933__eq__
1934__float__
1935__floordiv__
1936__ge__
1937__getattr__
1938__getattribute__
1939__getitem__
1940__gt__
1941__hash__
1942__iadd__
1943__iand__
Larry Hastings8666e652014-01-12 14:12:59 -08001944__ifloordiv__
1945__ilshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001946__imatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001947__imod__
1948__imul__
1949__index__
1950__int__
1951__invert__
1952__ior__
1953__ipow__
1954__irshift__
1955__isub__
1956__iter__
1957__itruediv__
1958__ixor__
1959__le__
1960__len__
1961__lshift__
1962__lt__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001963__matmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001964__mod__
1965__mul__
1966__neg__
1967__new__
1968__next__
1969__or__
1970__pos__
1971__pow__
1972__radd__
1973__rand__
1974__rdivmod__
1975__repr__
1976__rfloordiv__
1977__rlshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001978__rmatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001979__rmod__
1980__rmul__
1981__ror__
1982__round__
1983__rpow__
1984__rrshift__
1985__rshift__
1986__rsub__
1987__rtruediv__
1988__rxor__
1989__setattr__
1990__setitem__
1991__str__
1992__sub__
1993__truediv__
1994__xor__
1995
1996""".strip().split())
1997
1998
Larry Hastings5c661892014-01-24 06:17:25 -08001999INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
2000INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
2001""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07002002
2003class Function:
2004 """
2005 Mutable duck type for inspect.Function.
2006
2007 docstring - a str containing
2008 * embedded line breaks
2009 * text outdented to the left margin
2010 * no trailing whitespace.
2011 It will always be true that
2012 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
2013 """
2014
2015 def __init__(self, parameters=None, *, name,
2016 module, cls=None, c_basename=None,
2017 full_name=None,
2018 return_converter, return_annotation=_empty,
Larry Hastings581ee362014-01-28 05:00:08 -08002019 docstring=None, kind=CALLABLE, coexist=False,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002020 docstring_only=False):
Larry Hastings31826802013-10-19 00:09:25 -07002021 self.parameters = parameters or collections.OrderedDict()
2022 self.return_annotation = return_annotation
2023 self.name = name
2024 self.full_name = full_name
2025 self.module = module
2026 self.cls = cls
2027 self.parent = cls or module
2028 self.c_basename = c_basename
2029 self.return_converter = return_converter
2030 self.docstring = docstring or ''
2031 self.kind = kind
2032 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08002033 self.self_converter = None
Larry Hastings2623c8c2014-02-08 22:15:29 -08002034 # docstring_only means "don't generate a machine-readable
2035 # signature, just a normal docstring". it's True for
2036 # functions with optional groups because we can't represent
2037 # those accurately with inspect.Signature in 3.4.
2038 self.docstring_only = docstring_only
Larry Hastingsebdcb502013-11-23 14:54:00 -08002039
Larry Hastings7726ac92014-01-31 22:03:12 -08002040 self.rendered_parameters = None
2041
2042 __render_parameters__ = None
2043 @property
2044 def render_parameters(self):
2045 if not self.__render_parameters__:
2046 self.__render_parameters__ = l = []
2047 for p in self.parameters.values():
2048 p = p.copy()
2049 p.converter.pre_render()
2050 l.append(p)
2051 return self.__render_parameters__
2052
Larry Hastingsebdcb502013-11-23 14:54:00 -08002053 @property
2054 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08002055 if self.kind in (METHOD_INIT, METHOD_NEW):
2056 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002057 flags = []
2058 if self.kind == CLASS_METHOD:
2059 flags.append('METH_CLASS')
2060 elif self.kind == STATIC_METHOD:
2061 flags.append('METH_STATIC')
2062 else:
2063 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
2064 if self.coexist:
2065 flags.append('METH_COEXIST')
2066 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07002067
2068 def __repr__(self):
2069 return '<clinic.Function ' + self.name + '>'
2070
Larry Hastings7726ac92014-01-31 22:03:12 -08002071 def copy(self, **overrides):
2072 kwargs = {
2073 'name': self.name, 'module': self.module, 'parameters': self.parameters,
2074 'cls': self.cls, 'c_basename': self.c_basename,
2075 'full_name': self.full_name,
2076 'return_converter': self.return_converter, 'return_annotation': self.return_annotation,
2077 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002078 'docstring_only': self.docstring_only,
Larry Hastings7726ac92014-01-31 22:03:12 -08002079 }
2080 kwargs.update(overrides)
2081 f = Function(**kwargs)
2082
2083 parameters = collections.OrderedDict()
2084 for name, value in f.parameters.items():
2085 value = value.copy(function=f)
2086 parameters[name] = value
2087 f.parameters = parameters
2088 return f
2089
Larry Hastings31826802013-10-19 00:09:25 -07002090
2091class Parameter:
2092 """
2093 Mutable duck type of inspect.Parameter.
2094 """
2095
2096 def __init__(self, name, kind, *, default=_empty,
2097 function, converter, annotation=_empty,
2098 docstring=None, group=0):
2099 self.name = name
2100 self.kind = kind
2101 self.default = default
2102 self.function = function
2103 self.converter = converter
2104 self.annotation = annotation
2105 self.docstring = docstring or ''
2106 self.group = group
2107
2108 def __repr__(self):
2109 return '<clinic.Parameter ' + self.name + '>'
2110
2111 def is_keyword_only(self):
2112 return self.kind == inspect.Parameter.KEYWORD_ONLY
2113
Larry Hastings2623c8c2014-02-08 22:15:29 -08002114 def is_positional_only(self):
2115 return self.kind == inspect.Parameter.POSITIONAL_ONLY
2116
Larry Hastings7726ac92014-01-31 22:03:12 -08002117 def copy(self, **overrides):
2118 kwargs = {
2119 'name': self.name, 'kind': self.kind, 'default':self.default,
2120 'function': self.function, 'converter': self.converter, 'annotation': self.annotation,
2121 'docstring': self.docstring, 'group': self.group,
2122 }
2123 kwargs.update(overrides)
2124 if 'converter' not in overrides:
2125 converter = copy.copy(self.converter)
2126 converter.function = kwargs['function']
2127 kwargs['converter'] = converter
2128 return Parameter(**kwargs)
2129
2130
2131
2132class LandMine:
2133 # try to access any
2134 def __init__(self, message):
2135 self.__message__ = message
2136
2137 def __repr__(self):
2138 return '<LandMine ' + repr(self.__message__) + ">"
2139
2140 def __getattribute__(self, name):
2141 if name in ('__repr__', '__message__'):
2142 return super().__getattribute__(name)
2143 # raise RuntimeError(repr(name))
2144 fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__)
Larry Hastings31826802013-10-19 00:09:25 -07002145
Larry Hastings31826802013-10-19 00:09:25 -07002146
2147def add_c_converter(f, name=None):
2148 if not name:
2149 name = f.__name__
2150 if not name.endswith('_converter'):
2151 return f
2152 name = name[:-len('_converter')]
2153 converters[name] = f
2154 return f
2155
2156def add_default_legacy_c_converter(cls):
2157 # automatically add converter for default format unit
2158 # (but without stomping on the existing one if it's already
2159 # set, in case you subclass)
Larry Hastingsf1503782014-06-11 04:31:29 -07002160 if ((cls.format_unit not in ('O&', '')) and
Larry Hastings31826802013-10-19 00:09:25 -07002161 (cls.format_unit not in legacy_converters)):
2162 legacy_converters[cls.format_unit] = cls
2163 return cls
2164
2165def add_legacy_c_converter(format_unit, **kwargs):
2166 """
2167 Adds a legacy converter.
2168 """
2169 def closure(f):
2170 if not kwargs:
2171 added_f = f
2172 else:
2173 added_f = functools.partial(f, **kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002174 if format_unit:
2175 legacy_converters[format_unit] = added_f
Larry Hastings31826802013-10-19 00:09:25 -07002176 return f
2177 return closure
2178
2179class CConverterAutoRegister(type):
2180 def __init__(cls, name, bases, classdict):
2181 add_c_converter(cls)
2182 add_default_legacy_c_converter(cls)
2183
2184class CConverter(metaclass=CConverterAutoRegister):
2185 """
2186 For the init function, self, name, function, and default
2187 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08002188 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07002189 """
2190
Larry Hastings7726ac92014-01-31 22:03:12 -08002191 # The C name to use for this variable.
2192 name = None
2193
2194 # The Python name to use for this variable.
2195 py_name = None
2196
Larry Hastings78cf85c2014-01-04 12:44:57 -08002197 # The C type to use for this variable.
2198 # 'type' should be a Python string specifying the type, e.g. "int".
2199 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002200 type = None
Larry Hastings31826802013-10-19 00:09:25 -07002201
2202 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08002203 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08002204 # Or the magic value "unknown" if this value is a cannot be evaluated
2205 # at Argument-Clinic-preprocessing time (but is presumed to be valid
2206 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07002207 default = unspecified
2208
Larry Hastings4a55fc52014-01-12 11:09:57 -08002209 # If not None, default must be isinstance() of this type.
2210 # (You can also specify a tuple of types.)
2211 default_type = None
2212
Larry Hastings31826802013-10-19 00:09:25 -07002213 # "default" converted into a C value, as a string.
2214 # Or None if there is no default.
2215 c_default = None
2216
Larry Hastings2a727912014-01-16 11:32:01 -08002217 # "default" converted into a Python value, as a string.
2218 # Or None if there is no default.
2219 py_default = None
2220
Larry Hastingsabc716b2013-11-20 09:13:52 -08002221 # The default value used to initialize the C variable when
2222 # there is no default, but not specifying a default may
2223 # result in an "uninitialized variable" warning. This can
2224 # easily happen when using option groups--although
2225 # properly-written code won't actually use the variable,
2226 # the variable does get passed in to the _impl. (Ah, if
2227 # only dataflow analysis could inline the static function!)
2228 #
2229 # This value is specified as a string.
2230 # Every non-abstract subclass should supply a valid value.
2231 c_ignored_default = 'NULL'
2232
Larry Hastings31826802013-10-19 00:09:25 -07002233 # The C converter *function* to be used, if any.
2234 # (If this is not None, format_unit must be 'O&'.)
2235 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002236
Larry Hastings78cf85c2014-01-04 12:44:57 -08002237 # Should Argument Clinic add a '&' before the name of
2238 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07002239 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08002240
2241 # Should Argument Clinic add a '&' before the name of
2242 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07002243 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08002244
2245 #############################################################
2246 #############################################################
2247 ## You shouldn't need to read anything below this point to ##
2248 ## write your own converter functions. ##
2249 #############################################################
2250 #############################################################
2251
2252 # The "format unit" to specify for this variable when
2253 # parsing arguments using PyArg_ParseTuple (AndKeywords).
2254 # Custom converters should always use the default value of 'O&'.
2255 format_unit = 'O&'
2256
2257 # What encoding do we want for this variable? Only used
2258 # by format units starting with 'e'.
2259 encoding = None
2260
Larry Hastings77561cc2014-01-07 12:13:13 -08002261 # Should this object be required to be a subclass of a specific type?
2262 # If not None, should be a string representing a pointer to a
2263 # PyTypeObject (e.g. "&PyUnicode_Type").
2264 # Only used by the 'O!' format unit (and the "object" converter).
2265 subclass_of = None
2266
Larry Hastings78cf85c2014-01-04 12:44:57 -08002267 # Do we want an adjacent '_length' variable for this variable?
2268 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07002269 length = False
2270
Larry Hastings5c661892014-01-24 06:17:25 -08002271 # Should we show this parameter in the generated
2272 # __text_signature__? This is *almost* always True.
Larry Hastingsc2047262014-01-25 20:43:29 -08002273 # (It's only False for __new__, __init__, and METH_STATIC functions.)
Larry Hastings5c661892014-01-24 06:17:25 -08002274 show_in_signature = True
2275
2276 # Overrides the name used in a text signature.
2277 # The name used for a "self" parameter must be one of
2278 # self, type, or module; however users can set their own.
2279 # This lets the self_converter overrule the user-settable
2280 # name, *just* for the text signature.
2281 # Only set by self_converter.
2282 signature_name = None
2283
2284 # keep in sync with self_converter.__init__!
Larry Hastings7726ac92014-01-31 22:03:12 -08002285 def __init__(self, name, py_name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs):
Larry Hastings31826802013-10-19 00:09:25 -07002286 self.name = name
Larry Hastings7726ac92014-01-31 22:03:12 -08002287 self.py_name = py_name
Larry Hastings31826802013-10-19 00:09:25 -07002288
2289 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08002290 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002291 if isinstance(self.default_type, type):
2292 types_str = self.default_type.__name__
2293 else:
2294 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2295 fail("{}: default value {!r} for field {} is not of type {}".format(
2296 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002297 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002298
Larry Hastingsb4705752014-01-18 21:54:15 -08002299 if c_default:
2300 self.c_default = c_default
2301 if py_default:
2302 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002303
Larry Hastings31826802013-10-19 00:09:25 -07002304 if annotation != unspecified:
2305 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings7726ac92014-01-31 22:03:12 -08002306
2307 # this is deliberate, to prevent you from caching information
2308 # about the function in the init.
2309 # (that breaks if we get cloned.)
2310 # so after this change we will noisily fail.
2311 self.function = LandMine("Don't access members of self.function inside converter_init!")
Larry Hastings31826802013-10-19 00:09:25 -07002312 self.converter_init(**kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002313 self.function = function
Larry Hastings31826802013-10-19 00:09:25 -07002314
2315 def converter_init(self):
2316 pass
2317
2318 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002319 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002320
Larry Hastings5c661892014-01-24 06:17:25 -08002321 def _render_self(self, parameter, data):
2322 self.parameter = parameter
2323 original_name = self.name
2324 name = ensure_legal_c_identifier(original_name)
2325
2326 # impl_arguments
2327 s = ("&" if self.impl_by_reference else "") + name
2328 data.impl_arguments.append(s)
2329 if self.length:
2330 data.impl_arguments.append(self.length_name())
2331
2332 # impl_parameters
2333 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2334 if self.length:
2335 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2336
2337 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002338 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002339 original_name = self.name
2340 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002341
2342 # declarations
2343 d = self.declaration()
2344 data.declarations.append(d)
2345
2346 # initializers
2347 initializers = self.initialize()
2348 if initializers:
2349 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2350
Larry Hastingsc2047262014-01-25 20:43:29 -08002351 # modifications
2352 modifications = self.modify()
2353 if modifications:
2354 data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2355
Larry Hastings31826802013-10-19 00:09:25 -07002356 # keywords
Larry Hastings7726ac92014-01-31 22:03:12 -08002357 data.keywords.append(parameter.name)
Larry Hastings31826802013-10-19 00:09:25 -07002358
2359 # format_units
2360 if self.is_optional() and '|' not in data.format_units:
2361 data.format_units.append('|')
2362 if parameter.is_keyword_only() and '$' not in data.format_units:
2363 data.format_units.append('$')
2364 data.format_units.append(self.format_unit)
2365
2366 # parse_arguments
2367 self.parse_argument(data.parse_arguments)
2368
Larry Hastings31826802013-10-19 00:09:25 -07002369 # cleanup
2370 cleanup = self.cleanup()
2371 if cleanup:
2372 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2373
Larry Hastings5c661892014-01-24 06:17:25 -08002374 def render(self, parameter, data):
2375 """
2376 parameter is a clinic.Parameter instance.
2377 data is a CRenderData instance.
2378 """
2379 self._render_self(parameter, data)
2380 self._render_non_self(parameter, data)
2381
Larry Hastingsebdcb502013-11-23 14:54:00 -08002382 def length_name(self):
2383 """Computes the name of the associated "length" variable."""
2384 if not self.length:
2385 return None
2386 return ensure_legal_c_identifier(self.name) + "_length"
2387
Larry Hastings31826802013-10-19 00:09:25 -07002388 # Why is this one broken out separately?
2389 # For "positional-only" function parsing,
2390 # which generates a bunch of PyArg_ParseTuple calls.
2391 def parse_argument(self, list):
2392 assert not (self.converter and self.encoding)
2393 if self.format_unit == 'O&':
2394 assert self.converter
2395 list.append(self.converter)
2396
2397 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002398 list.append(c_repr(self.encoding))
2399 elif self.subclass_of:
2400 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002401
Larry Hastingsebdcb502013-11-23 14:54:00 -08002402 legal_name = ensure_legal_c_identifier(self.name)
2403 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002404 list.append(s)
2405
Larry Hastingsebdcb502013-11-23 14:54:00 -08002406 if self.length:
2407 list.append("&" + self.length_name())
2408
Larry Hastings31826802013-10-19 00:09:25 -07002409 #
2410 # All the functions after here are intended as extension points.
2411 #
2412
2413 def simple_declaration(self, by_reference=False):
2414 """
2415 Computes the basic declaration of the variable.
2416 Used in computing the prototype declaration and the
2417 variable declaration.
2418 """
2419 prototype = [self.type]
2420 if by_reference or not self.type.endswith('*'):
2421 prototype.append(" ")
2422 if by_reference:
2423 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002424 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002425 return "".join(prototype)
2426
2427 def declaration(self):
2428 """
2429 The C statement to declare this variable.
2430 """
2431 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002432 default = self.c_default
2433 if not default and self.parameter.group:
2434 default = self.c_ignored_default
2435 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002436 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002437 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002438 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002439 if self.length:
2440 declaration.append('\nPy_ssize_clean_t ')
2441 declaration.append(self.length_name())
2442 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002443 s = "".join(declaration)
2444 # double up curly-braces, this string will be used
2445 # as part of a format_map() template later
2446 s = s.replace("{", "{{")
2447 s = s.replace("}", "}}")
2448 return s
Larry Hastings31826802013-10-19 00:09:25 -07002449
2450 def initialize(self):
2451 """
2452 The C statements required to set up this variable before parsing.
2453 Returns a string containing this code indented at column 0.
2454 If no initialization is necessary, returns an empty string.
2455 """
2456 return ""
2457
Larry Hastingsc2047262014-01-25 20:43:29 -08002458 def modify(self):
2459 """
2460 The C statements required to modify this variable after parsing.
2461 Returns a string containing this code indented at column 0.
2462 If no initialization is necessary, returns an empty string.
2463 """
2464 return ""
2465
Larry Hastings31826802013-10-19 00:09:25 -07002466 def cleanup(self):
2467 """
2468 The C statements required to clean up after this variable.
2469 Returns a string containing this code indented at column 0.
2470 If no cleanup is necessary, returns an empty string.
2471 """
2472 return ""
2473
Larry Hastings7726ac92014-01-31 22:03:12 -08002474 def pre_render(self):
2475 """
2476 A second initialization function, like converter_init,
2477 called just before rendering.
2478 You are permitted to examine self.function here.
2479 """
2480 pass
2481
Larry Hastings31826802013-10-19 00:09:25 -07002482
2483class bool_converter(CConverter):
2484 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002485 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002486 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002487 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002488
2489 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002490 if self.default is not unspecified:
2491 self.default = bool(self.default)
2492 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002493
2494class char_converter(CConverter):
2495 type = 'char'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002496 default_type = (bytes, bytearray)
Larry Hastings31826802013-10-19 00:09:25 -07002497 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002498 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002499
Larry Hastings4a55fc52014-01-12 11:09:57 -08002500 def converter_init(self):
Larry Hastings7f90cba2015-04-15 23:02:12 -04002501 if isinstance(self.default, self.default_type) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002502 fail("char_converter: illegal default value " + repr(self.default))
2503
2504
Larry Hastings31826802013-10-19 00:09:25 -07002505@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002506class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002507 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002508 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002509 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002510 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002511
2512 def converter_init(self, *, bitwise=False):
2513 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002514 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002515
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002516class byte_converter(unsigned_char_converter): pass
2517
Larry Hastings31826802013-10-19 00:09:25 -07002518class short_converter(CConverter):
2519 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002520 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002521 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002522 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002523
2524class unsigned_short_converter(CConverter):
2525 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002526 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002527 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002528 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002529
2530 def converter_init(self, *, bitwise=False):
2531 if not bitwise:
2532 fail("Unsigned shorts must be bitwise (for now).")
2533
Larry Hastings7f90cba2015-04-15 23:02:12 -04002534@add_legacy_c_converter('C', types={'str'})
Larry Hastings31826802013-10-19 00:09:25 -07002535class int_converter(CConverter):
2536 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002537 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002538 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002539 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002540
Larry Hastings7f90cba2015-04-15 23:02:12 -04002541 def converter_init(self, *, types={'int'}, type=None):
2542 if types == {'str'}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002543 self.format_unit = 'C'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002544 elif types != {'int'}:
2545 fail("int_converter: illegal 'types' argument " + repr(types))
Larry Hastingsdfbeb162014-10-13 10:39:41 +01002546 if type != None:
2547 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002548
2549class unsigned_int_converter(CConverter):
2550 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002551 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002552 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002553 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002554
2555 def converter_init(self, *, bitwise=False):
2556 if not bitwise:
2557 fail("Unsigned ints must be bitwise (for now).")
2558
2559class long_converter(CConverter):
2560 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002561 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002562 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002563 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002564
2565class unsigned_long_converter(CConverter):
2566 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002567 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002568 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002569 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002570
2571 def converter_init(self, *, bitwise=False):
2572 if not bitwise:
2573 fail("Unsigned longs must be bitwise (for now).")
2574
2575class PY_LONG_LONG_converter(CConverter):
2576 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002577 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002578 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002579 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002580
2581class unsigned_PY_LONG_LONG_converter(CConverter):
2582 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002583 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002584 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002585 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002586
2587 def converter_init(self, *, bitwise=False):
2588 if not bitwise:
2589 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2590
2591class Py_ssize_t_converter(CConverter):
2592 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002593 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002594 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002595 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002596
2597
2598class float_converter(CConverter):
2599 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002600 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002601 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002602 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002603
2604class double_converter(CConverter):
2605 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002606 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002607 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002608 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002609
2610
2611class Py_complex_converter(CConverter):
2612 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002613 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002614 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002615 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002616
2617
2618class object_converter(CConverter):
2619 type = 'PyObject *'
2620 format_unit = 'O'
2621
Larry Hastings4a55fc52014-01-12 11:09:57 -08002622 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2623 if converter:
2624 if subclass_of:
2625 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2626 self.format_unit = 'O&'
2627 self.converter = converter
2628 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002629 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002630 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002631
Larry Hastings77561cc2014-01-07 12:13:13 -08002632 if type is not None:
2633 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002634
2635
Larry Hastings7f90cba2015-04-15 23:02:12 -04002636#
2637# We define three string conventions for buffer types in the 'types' argument:
2638# 'buffer' : any object supporting the buffer interface
2639# 'rwbuffer': any object supporting the buffer interface, but must be writeable
2640# 'robuffer': any object supporting the buffer interface, but must not be writeable
2641#
2642
2643@add_legacy_c_converter('s#', types={"str", "robuffer"}, length=True)
2644@add_legacy_c_converter('y', types={"robuffer"})
2645@add_legacy_c_converter('y#', types={"robuffer"}, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002646@add_legacy_c_converter('z', nullable=True)
Larry Hastings7f90cba2015-04-15 23:02:12 -04002647@add_legacy_c_converter('z#', types={"str", "robuffer"}, nullable=True, length=True)
2648# add_legacy_c_converter not supported for es, es#, et, et#
2649# because of their extra encoding argument
Larry Hastings31826802013-10-19 00:09:25 -07002650class str_converter(CConverter):
2651 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002652 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002653 format_unit = 's'
2654
Larry Hastings7f90cba2015-04-15 23:02:12 -04002655 def converter_init(self, *, encoding=None, types={"str"},
Larry Hastingsebdcb502013-11-23 14:54:00 -08002656 length=False, nullable=False, zeroes=False):
2657
Larry Hastingsebdcb502013-11-23 14:54:00 -08002658 self.length = bool(length)
Larry Hastings7f90cba2015-04-15 23:02:12 -04002659
2660 is_b_or_ba = types == {"bytes", "bytearray"}
2661 is_str = types == {"str"}
2662 is_robuffer = types == {"robuffer"}
2663 is_str_or_robuffer = types == {"str", "robuffer"}
2664
Larry Hastingsebdcb502013-11-23 14:54:00 -08002665 format_unit = None
2666
2667 if encoding:
2668 self.encoding = encoding
2669
Larry Hastings7f90cba2015-04-15 23:02:12 -04002670 if is_str and not length and not zeroes and not nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002671 format_unit = 'es'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002672 elif is_str and length and zeroes and nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002673 format_unit = 'es#'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002674 elif is_b_or_ba and not length and not zeroes and not nullable:
2675 format_unit = 'et'
2676 elif is_b_or_ba and length and zeroes and nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002677 format_unit = 'et#'
2678
Larry Hastingsebdcb502013-11-23 14:54:00 -08002679 else:
2680 if zeroes:
2681 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
2682
Larry Hastings7f90cba2015-04-15 23:02:12 -04002683 if is_str and not length and not nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002684 format_unit = 's'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002685 elif is_str and not length and nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002686 format_unit = 'z'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002687 elif is_robuffer and not length and not nullable:
2688 format_unit = 'y'
2689 elif is_robuffer and length and not nullable:
2690 format_unit = 'y#'
2691 elif is_str_or_robuffer and length and not nullable:
2692 format_unit = 's#'
2693 elif is_str_or_robuffer and length and nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002694 format_unit = 'z#'
2695
2696 if not format_unit:
2697 fail("str_converter: illegal combination of arguments")
2698 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002699
2700
2701class PyBytesObject_converter(CConverter):
2702 type = 'PyBytesObject *'
2703 format_unit = 'S'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002704 # types = {'bytes'}
Larry Hastings31826802013-10-19 00:09:25 -07002705
2706class PyByteArrayObject_converter(CConverter):
2707 type = 'PyByteArrayObject *'
2708 format_unit = 'Y'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002709 # types = {'bytearray'}
Larry Hastings31826802013-10-19 00:09:25 -07002710
2711class unicode_converter(CConverter):
2712 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002713 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002714 format_unit = 'U'
2715
Larry Hastingsebdcb502013-11-23 14:54:00 -08002716@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002717@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002718@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002719class Py_UNICODE_converter(CConverter):
2720 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002721 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002722 format_unit = 'u'
2723
Larry Hastingsebdcb502013-11-23 14:54:00 -08002724 def converter_init(self, *, nullable=False, length=False):
2725 format_unit = 'Z' if nullable else 'u'
2726 if length:
2727 format_unit += '#'
2728 self.length = True
2729 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002730
Larry Hastings7f90cba2015-04-15 23:02:12 -04002731@add_legacy_c_converter('s*', types={'str', 'buffer'})
2732@add_legacy_c_converter('z*', types={'str', 'buffer'}, nullable=True)
2733@add_legacy_c_converter('w*', types={'rwbuffer'})
Larry Hastings31826802013-10-19 00:09:25 -07002734class Py_buffer_converter(CConverter):
2735 type = 'Py_buffer'
2736 format_unit = 'y*'
2737 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002738 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002739
Larry Hastings7f90cba2015-04-15 23:02:12 -04002740 def converter_init(self, *, types={'buffer'}, nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002741 if self.default not in (unspecified, None):
2742 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08002743 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002744
2745 format_unit = None
Larry Hastings7f90cba2015-04-15 23:02:12 -04002746 if types == {'str', 'buffer'}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002747 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07002748 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002749 if nullable:
2750 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
Larry Hastings7f90cba2015-04-15 23:02:12 -04002751 elif types == {'buffer'}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002752 format_unit = 'y*'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002753 elif types == {'rwbuffer'}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002754 format_unit = 'w*'
2755 if not format_unit:
2756 fail("Py_buffer_converter: illegal combination of arguments")
2757
2758 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002759
2760 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002761 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002762 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002763
2764
Larry Hastings5c661892014-01-24 06:17:25 -08002765def correct_name_for_self(f):
2766 if f.kind in (CALLABLE, METHOD_INIT):
2767 if f.cls:
2768 return "PyObject *", "self"
2769 return "PyModuleDef *", "module"
2770 if f.kind == STATIC_METHOD:
2771 return "void *", "null"
2772 if f.kind in (CLASS_METHOD, METHOD_NEW):
2773 return "PyTypeObject *", "type"
2774 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2775
Larry Hastingsc2047262014-01-25 20:43:29 -08002776def required_type_for_self_for_parser(f):
2777 type, _ = correct_name_for_self(f)
2778 if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2779 return type
2780 return None
2781
Larry Hastings5c661892014-01-24 06:17:25 -08002782
Larry Hastingsebdcb502013-11-23 14:54:00 -08002783class self_converter(CConverter):
2784 """
2785 A special-case converter:
2786 this is the default converter used for "self".
2787 """
Larry Hastings5c661892014-01-24 06:17:25 -08002788 type = None
2789 format_unit = ''
2790
Larry Hastings78cf85c2014-01-04 12:44:57 -08002791 def converter_init(self, *, type=None):
Larry Hastings7726ac92014-01-31 22:03:12 -08002792 self.specified_type = type
2793
2794 def pre_render(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002795 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002796 default_type, default_name = correct_name_for_self(f)
2797 self.signature_name = default_name
Larry Hastings7726ac92014-01-31 22:03:12 -08002798 self.type = self.specified_type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002799
Larry Hastings5c661892014-01-24 06:17:25 -08002800 kind = self.function.kind
2801 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2802
2803 if (kind == STATIC_METHOD) or new_or_init:
2804 self.show_in_signature = False
2805
2806 # tp_new (METHOD_NEW) functions are of type newfunc:
2807 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2808 # PyTypeObject is a typedef for struct _typeobject.
2809 #
2810 # tp_init (METHOD_INIT) functions are of type initproc:
2811 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2812 #
2813 # All other functions generated by Argument Clinic are stored in
2814 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2815 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2816 # However! We habitually cast these functions to PyCFunction,
2817 # since functions that accept keyword arguments don't fit this signature
2818 # but are stored there anyway. So strict type equality isn't important
2819 # for these functions.
2820 #
2821 # So:
2822 #
2823 # * The name of the first parameter to the impl and the parsing function will always
2824 # be self.name.
2825 #
2826 # * The type of the first parameter to the impl will always be of self.type.
2827 #
2828 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2829 # * The type of the first parameter to the parsing function is also self.type.
2830 # This means that if you step into the parsing function, your "self" parameter
2831 # is of the correct type, which may make debugging more pleasant.
2832 #
2833 # * Else if the function is tp_new (METHOD_NEW):
2834 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2835 # so the type signature of the function call is an exact match.
2836 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2837 # in the impl call.
2838 #
2839 # * Else if the function is tp_init (METHOD_INIT):
2840 # * The type of the first parameter to the parsing function is "PyObject *",
2841 # so the type signature of the function call is an exact match.
2842 # * If self.type != "PyObject *", we cast the first parameter to self.type
2843 # in the impl call.
2844
2845 @property
2846 def parser_type(self):
Larry Hastingsc2047262014-01-25 20:43:29 -08002847 return required_type_for_self_for_parser(self.function) or self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002848
Larry Hastingsebdcb502013-11-23 14:54:00 -08002849 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002850 """
2851 parameter is a clinic.Parameter instance.
2852 data is a CRenderData instance.
2853 """
2854 if self.function.kind == STATIC_METHOD:
2855 return
2856
2857 self._render_self(parameter, data)
2858
2859 if self.type != self.parser_type:
2860 # insert cast to impl_argument[0], aka self.
2861 # we know we're in the first slot in all the CRenderData lists,
2862 # because we render parameters in order, and self is always first.
2863 assert len(data.impl_arguments) == 1
2864 assert data.impl_arguments[0] == self.name
2865 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2866
2867 def set_template_dict(self, template_dict):
2868 template_dict['self_name'] = self.name
2869 template_dict['self_type'] = self.parser_type
Larry Hastingsf0537e82014-01-25 22:01:12 -08002870 kind = self.function.kind
2871 cls = self.function.cls
2872
2873 if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef):
2874 if kind == METHOD_NEW:
2875 passed_in_type = self.name
2876 else:
2877 passed_in_type = 'Py_TYPE({})'.format(self.name)
2878
2879 line = '({passed_in_type} == {type_object}) &&\n '
2880 d = {
2881 'type_object': self.function.cls.type_object,
2882 'passed_in_type': passed_in_type
2883 }
2884 template_dict['self_type_check'] = line.format_map(d)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002885
Larry Hastings31826802013-10-19 00:09:25 -07002886
2887
2888def add_c_return_converter(f, name=None):
2889 if not name:
2890 name = f.__name__
2891 if not name.endswith('_return_converter'):
2892 return f
2893 name = name[:-len('_return_converter')]
2894 return_converters[name] = f
2895 return f
2896
2897
2898class CReturnConverterAutoRegister(type):
2899 def __init__(cls, name, bases, classdict):
2900 add_c_return_converter(cls)
2901
2902class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2903
Larry Hastings78cf85c2014-01-04 12:44:57 -08002904 # The C type to use for this variable.
2905 # 'type' should be a Python string specifying the type, e.g. "int".
2906 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002907 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002908
2909 # The Python default value for this parameter, as a Python value.
2910 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002911 default = None
2912
Larry Hastings2a727912014-01-16 11:32:01 -08002913 def __init__(self, *, py_default=None, **kwargs):
2914 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002915 try:
2916 self.return_converter_init(**kwargs)
2917 except TypeError as e:
2918 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2919 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2920
2921 def return_converter_init(self):
2922 pass
2923
2924 def declare(self, data, name="_return_value"):
2925 line = []
2926 add = line.append
2927 add(self.type)
2928 if not self.type.endswith('*'):
2929 add(' ')
2930 add(name + ';')
2931 data.declarations.append(''.join(line))
2932 data.return_value = name
2933
2934 def err_occurred_if(self, expr, data):
2935 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2936
2937 def err_occurred_if_null_pointer(self, variable, data):
2938 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2939
2940 def render(self, function, data):
2941 """
2942 function is a clinic.Function instance.
2943 data is a CRenderData instance.
2944 """
2945 pass
2946
2947add_c_return_converter(CReturnConverter, 'object')
2948
Larry Hastings78cf85c2014-01-04 12:44:57 -08002949class NoneType_return_converter(CReturnConverter):
2950 def render(self, function, data):
2951 self.declare(data)
2952 data.return_conversion.append('''
2953if (_return_value != Py_None)
2954 goto exit;
2955return_value = Py_None;
2956Py_INCREF(Py_None);
2957'''.strip())
2958
Larry Hastings4a55fc52014-01-12 11:09:57 -08002959class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002960 type = 'int'
2961
2962 def render(self, function, data):
2963 self.declare(data)
2964 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002965 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002966
2967class long_return_converter(CReturnConverter):
2968 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002969 conversion_fn = 'PyLong_FromLong'
2970 cast = ''
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002971 unsigned_cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002972
2973 def render(self, function, data):
2974 self.declare(data)
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002975 self.err_occurred_if("_return_value == {}-1".format(self.unsigned_cast), data)
Larry Hastings31826802013-10-19 00:09:25 -07002976 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002977 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002978
Larry Hastings4a55fc52014-01-12 11:09:57 -08002979class int_return_converter(long_return_converter):
2980 type = 'int'
2981 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002982
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002983class init_return_converter(long_return_converter):
2984 """
2985 Special return converter for __init__ functions.
2986 """
2987 type = 'int'
2988 cast = '(long)'
2989
2990 def render(self, function, data):
2991 pass
2992
Larry Hastings4a55fc52014-01-12 11:09:57 -08002993class unsigned_long_return_converter(long_return_converter):
2994 type = 'unsigned long'
2995 conversion_fn = 'PyLong_FromUnsignedLong'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002996 unsigned_cast = '(unsigned long)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002997
2998class unsigned_int_return_converter(unsigned_long_return_converter):
2999 type = 'unsigned int'
3000 cast = '(unsigned long)'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003001 unsigned_cast = '(unsigned int)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003002
3003class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07003004 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003005 conversion_fn = 'PyLong_FromSsize_t'
3006
3007class size_t_return_converter(long_return_converter):
3008 type = 'size_t'
3009 conversion_fn = 'PyLong_FromSize_t'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003010 unsigned_cast = '(size_t)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003011
3012
3013class double_return_converter(CReturnConverter):
3014 type = 'double'
3015 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07003016
3017 def render(self, function, data):
3018 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08003019 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07003020 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08003021 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
3022
3023class float_return_converter(double_return_converter):
3024 type = 'float'
3025 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07003026
3027
3028class DecodeFSDefault_return_converter(CReturnConverter):
3029 type = 'char *'
3030
3031 def render(self, function, data):
3032 self.declare(data)
3033 self.err_occurred_if_null_pointer("_return_value", data)
3034 data.return_conversion.append(
3035 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
3036
3037
3038class IndentStack:
3039 def __init__(self):
3040 self.indents = []
3041 self.margin = None
3042
3043 def _ensure(self):
3044 if not self.indents:
3045 fail('IndentStack expected indents, but none are defined.')
3046
3047 def measure(self, line):
3048 """
3049 Returns the length of the line's margin.
3050 """
3051 if '\t' in line:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003052 fail('Tab characters are illegal in the Argument Clinic DSL.')
Larry Hastings31826802013-10-19 00:09:25 -07003053 stripped = line.lstrip()
3054 if not len(stripped):
3055 # we can't tell anything from an empty line
3056 # so just pretend it's indented like our current indent
3057 self._ensure()
3058 return self.indents[-1]
3059 return len(line) - len(stripped)
3060
3061 def infer(self, line):
3062 """
3063 Infer what is now the current margin based on this line.
3064 Returns:
3065 1 if we have indented (or this is the first margin)
3066 0 if the margin has not changed
3067 -N if we have dedented N times
3068 """
3069 indent = self.measure(line)
3070 margin = ' ' * indent
3071 if not self.indents:
3072 self.indents.append(indent)
3073 self.margin = margin
3074 return 1
3075 current = self.indents[-1]
3076 if indent == current:
3077 return 0
3078 if indent > current:
3079 self.indents.append(indent)
3080 self.margin = margin
3081 return 1
3082 # indent < current
3083 if indent not in self.indents:
3084 fail("Illegal outdent.")
3085 outdent_count = 0
3086 while indent != current:
3087 self.indents.pop()
3088 current = self.indents[-1]
3089 outdent_count -= 1
3090 self.margin = margin
3091 return outdent_count
3092
3093 @property
3094 def depth(self):
3095 """
3096 Returns how many margins are currently defined.
3097 """
3098 return len(self.indents)
3099
3100 def indent(self, line):
3101 """
3102 Indents a line by the currently defined margin.
3103 """
3104 return self.margin + line
3105
3106 def dedent(self, line):
3107 """
3108 Dedents a line by the currently defined margin.
3109 (The inverse of 'indent'.)
3110 """
3111 margin = self.margin
3112 indent = self.indents[-1]
3113 if not line.startswith(margin):
3114 fail('Cannot dedent, line does not start with the previous margin:')
3115 return line[indent:]
3116
3117
3118class DSLParser:
3119 def __init__(self, clinic):
3120 self.clinic = clinic
3121
3122 self.directives = {}
3123 for name in dir(self):
3124 # functions that start with directive_ are added to directives
3125 _, s, key = name.partition("directive_")
3126 if s:
3127 self.directives[key] = getattr(self, name)
3128
3129 # functions that start with at_ are too, with an @ in front
3130 _, s, key = name.partition("at_")
3131 if s:
3132 self.directives['@' + key] = getattr(self, name)
3133
3134 self.reset()
3135
3136 def reset(self):
3137 self.function = None
3138 self.state = self.state_dsl_start
3139 self.parameter_indent = None
3140 self.keyword_only = False
3141 self.group = 0
3142 self.parameter_state = self.ps_start
Larry Hastingsc2047262014-01-25 20:43:29 -08003143 self.seen_positional_with_default = False
Larry Hastings31826802013-10-19 00:09:25 -07003144 self.indent = IndentStack()
3145 self.kind = CALLABLE
3146 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08003147 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08003148 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07003149
Larry Hastingsebdcb502013-11-23 14:54:00 -08003150 def directive_version(self, required):
3151 global version
3152 if version_comparitor(version, required) < 0:
3153 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
3154
Larry Hastings31826802013-10-19 00:09:25 -07003155 def directive_module(self, name):
3156 fields = name.split('.')
3157 new = fields.pop()
3158 module, cls = self.clinic._module_and_class(fields)
3159 if cls:
3160 fail("Can't nest a module inside a class!")
Larry Hastingsc2047262014-01-25 20:43:29 -08003161
3162 if name in module.classes:
3163 fail("Already defined module " + repr(name) + "!")
3164
Larry Hastings31826802013-10-19 00:09:25 -07003165 m = Module(name, module)
3166 module.modules[name] = m
3167 self.block.signatures.append(m)
3168
Larry Hastingsc2047262014-01-25 20:43:29 -08003169 def directive_class(self, name, typedef, type_object):
Larry Hastings31826802013-10-19 00:09:25 -07003170 fields = name.split('.')
3171 in_classes = False
3172 parent = self
3173 name = fields.pop()
3174 so_far = []
3175 module, cls = self.clinic._module_and_class(fields)
3176
Larry Hastingsc2047262014-01-25 20:43:29 -08003177 parent = cls or module
3178 if name in parent.classes:
3179 fail("Already defined class " + repr(name) + "!")
3180
3181 c = Class(name, module, cls, typedef, type_object)
3182 parent.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07003183 self.block.signatures.append(c)
3184
Larry Hastingsbebf7352014-01-17 17:47:17 -08003185 def directive_set(self, name, value):
3186 if name not in ("line_prefix", "line_suffix"):
3187 fail("unknown variable", repr(name))
3188
3189 value = value.format_map({
3190 'block comment start': '/*',
3191 'block comment end': '*/',
3192 })
3193
3194 self.clinic.__dict__[name] = value
3195
3196 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06003197 if command == 'new':
3198 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003199 return
3200
Zachary Ware071baa62014-01-21 23:07:12 -06003201 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08003202 self.clinic.get_destination(name).clear()
3203 fail("unknown destination command", repr(command))
3204
3205
Larry Hastings0759f842015-04-03 13:09:02 -07003206 def directive_output(self, command_or_name, destination=''):
3207 fd = self.clinic.destination_buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08003208
Larry Hastings0759f842015-04-03 13:09:02 -07003209 if command_or_name == "preset":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003210 preset = self.clinic.presets.get(destination)
3211 if not preset:
3212 fail("Unknown preset " + repr(destination) + "!")
3213 fd.update(preset)
3214 return
3215
Larry Hastings0759f842015-04-03 13:09:02 -07003216 if command_or_name == "push":
3217 self.clinic.destination_buffers_stack.append(fd.copy())
Larry Hastingsbebf7352014-01-17 17:47:17 -08003218 return
3219
Larry Hastings0759f842015-04-03 13:09:02 -07003220 if command_or_name == "pop":
3221 if not self.clinic.destination_buffers_stack:
Larry Hastingsbebf7352014-01-17 17:47:17 -08003222 fail("Can't 'output pop', stack is empty!")
Larry Hastings0759f842015-04-03 13:09:02 -07003223 previous_fd = self.clinic.destination_buffers_stack.pop()
Larry Hastingsbebf7352014-01-17 17:47:17 -08003224 fd.update(previous_fd)
3225 return
3226
3227 # secret command for debugging!
Larry Hastings0759f842015-04-03 13:09:02 -07003228 if command_or_name == "print":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003229 self.block.output.append(pprint.pformat(fd))
3230 self.block.output.append('\n')
3231 return
3232
3233 d = self.clinic.get_destination(destination)
3234
Larry Hastings0759f842015-04-03 13:09:02 -07003235 if command_or_name == "everything":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003236 for name in list(fd):
3237 fd[name] = d
3238 return
3239
Larry Hastings0759f842015-04-03 13:09:02 -07003240 if command_or_name not in fd:
3241 fail("Invalid command / destination name " + repr(command_or_name) + ", must be one of:\n preset push pop print everything " + " ".join(fd))
3242 fd[command_or_name] = d
Larry Hastingsbebf7352014-01-17 17:47:17 -08003243
3244 def directive_dump(self, name):
3245 self.block.output.append(self.clinic.get_destination(name).dump())
3246
3247 def directive_print(self, *args):
3248 self.block.output.append(' '.join(args))
3249 self.block.output.append('\n')
3250
3251 def directive_preserve(self):
3252 if self.preserve_output:
3253 fail("Can't have preserve twice in one block!")
3254 self.preserve_output = True
3255
Larry Hastings31826802013-10-19 00:09:25 -07003256 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003257 if self.kind is not CALLABLE:
3258 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003259 self.kind = CLASS_METHOD
3260
3261 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003262 if self.kind is not CALLABLE:
3263 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003264 self.kind = STATIC_METHOD
3265
3266 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003267 if self.coexist:
3268 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07003269 self.coexist = True
3270
3271 def parse(self, block):
3272 self.reset()
3273 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08003274 self.saved_output = self.block.output
3275 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07003276 block_start = self.clinic.block_parser.line_number
3277 lines = block.input.split('\n')
3278 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
3279 if '\t' in line:
3280 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
3281 self.state(line)
3282
3283 self.next(self.state_terminal)
3284 self.state(None)
3285
Larry Hastingsbebf7352014-01-17 17:47:17 -08003286 block.output.extend(self.clinic.language.render(clinic, block.signatures))
3287
3288 if self.preserve_output:
3289 if block.output:
3290 fail("'preserve' only works for blocks that don't produce any output!")
3291 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07003292
3293 @staticmethod
3294 def ignore_line(line):
3295 # ignore comment-only lines
3296 if line.lstrip().startswith('#'):
3297 return True
3298
3299 # Ignore empty lines too
3300 # (but not in docstring sections!)
3301 if not line.strip():
3302 return True
3303
3304 return False
3305
3306 @staticmethod
3307 def calculate_indent(line):
3308 return len(line) - len(line.strip())
3309
3310 def next(self, state, line=None):
3311 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3312 self.state = state
3313 if line is not None:
3314 self.state(line)
3315
3316 def state_dsl_start(self, line):
3317 # self.block = self.ClinicOutputBlock(self)
3318 if self.ignore_line(line):
3319 return
Larry Hastings7726ac92014-01-31 22:03:12 -08003320
3321 # is it a directive?
3322 fields = shlex.split(line)
3323 directive_name = fields[0]
3324 directive = self.directives.get(directive_name, None)
3325 if directive:
3326 try:
3327 directive(*fields[1:])
3328 except TypeError as e:
3329 fail(str(e))
3330 return
3331
Larry Hastings31826802013-10-19 00:09:25 -07003332 self.next(self.state_modulename_name, line)
3333
3334 def state_modulename_name(self, line):
3335 # looking for declaration, which establishes the leftmost column
3336 # line should be
3337 # modulename.fnname [as c_basename] [-> return annotation]
3338 # square brackets denote optional syntax.
3339 #
Larry Hastings4a714d42014-01-14 22:22:41 -08003340 # alternatively:
3341 # modulename.fnname [as c_basename] = modulename.existing_fn_name
3342 # clones the parameters and return converter from that
3343 # function. you can't modify them. you must enter a
3344 # new docstring.
3345 #
Larry Hastings31826802013-10-19 00:09:25 -07003346 # (but we might find a directive first!)
3347 #
3348 # this line is permitted to start with whitespace.
3349 # we'll call this number of spaces F (for "function").
3350
3351 if not line.strip():
3352 return
3353
3354 self.indent.infer(line)
3355
Larry Hastings4a714d42014-01-14 22:22:41 -08003356 # are we cloning?
3357 before, equals, existing = line.rpartition('=')
3358 if equals:
3359 full_name, _, c_basename = before.partition(' as ')
3360 full_name = full_name.strip()
3361 c_basename = c_basename.strip()
3362 existing = existing.strip()
3363 if (is_legal_py_identifier(full_name) and
3364 (not c_basename or is_legal_c_identifier(c_basename)) and
3365 is_legal_py_identifier(existing)):
3366 # we're cloning!
3367 fields = [x.strip() for x in existing.split('.')]
3368 function_name = fields.pop()
3369 module, cls = self.clinic._module_and_class(fields)
3370
3371 for existing_function in (cls or module).functions:
3372 if existing_function.name == function_name:
3373 break
3374 else:
3375 existing_function = None
3376 if not existing_function:
Larry Hastings7726ac92014-01-31 22:03:12 -08003377 print("class", cls, "module", module, "existing", existing)
Larry Hastingsc2047262014-01-25 20:43:29 -08003378 print("cls. functions", cls.functions)
Larry Hastings4a714d42014-01-14 22:22:41 -08003379 fail("Couldn't find existing function " + repr(existing) + "!")
3380
3381 fields = [x.strip() for x in full_name.split('.')]
3382 function_name = fields.pop()
3383 module, cls = self.clinic._module_and_class(fields)
3384
3385 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3386 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
Larry Hastings7726ac92014-01-31 22:03:12 -08003387 self.function = existing_function.copy(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename, docstring='')
Larry Hastings4a714d42014-01-14 22:22:41 -08003388
3389 self.block.signatures.append(self.function)
3390 (cls or module).functions.append(self.function)
3391 self.next(self.state_function_docstring)
3392 return
3393
Larry Hastings31826802013-10-19 00:09:25 -07003394 line, _, returns = line.partition('->')
3395
3396 full_name, _, c_basename = line.partition(' as ')
3397 full_name = full_name.strip()
3398 c_basename = c_basename.strip() or None
3399
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003400 if not is_legal_py_identifier(full_name):
3401 fail("Illegal function name: {}".format(full_name))
3402 if c_basename and not is_legal_c_identifier(c_basename):
3403 fail("Illegal C basename: {}".format(c_basename))
3404
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003405 return_converter = None
3406 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003407 ast_input = "def x() -> {}: pass".format(returns)
3408 module = None
3409 try:
3410 module = ast.parse(ast_input)
3411 except SyntaxError:
3412 pass
3413 if not module:
3414 fail("Badly-formed annotation for " + full_name + ": " + returns)
3415 try:
3416 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003417 if legacy:
3418 fail("Legacy converter {!r} not allowed as a return converter"
3419 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003420 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003421 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003422 return_converter = return_converters[name](**kwargs)
3423 except ValueError:
3424 fail("Badly-formed annotation for " + full_name + ": " + returns)
3425
3426 fields = [x.strip() for x in full_name.split('.')]
3427 function_name = fields.pop()
3428 module, cls = self.clinic._module_and_class(fields)
3429
Larry Hastings8666e652014-01-12 14:12:59 -08003430 fields = full_name.split('.')
3431 if fields[-1] == '__new__':
3432 if (self.kind != CLASS_METHOD) or (not cls):
3433 fail("__new__ must be a class method!")
3434 self.kind = METHOD_NEW
3435 elif fields[-1] == '__init__':
3436 if (self.kind != CALLABLE) or (not cls):
3437 fail("__init__ must be a normal method, not a class or static method!")
3438 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003439 if not return_converter:
3440 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003441 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003442 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003443
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003444 if not return_converter:
3445 return_converter = CReturnConverter()
3446
Larry Hastings31826802013-10-19 00:09:25 -07003447 if not module:
3448 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3449 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3450 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3451 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003452
3453 # insert a self converter automatically
Larry Hastingsc2047262014-01-25 20:43:29 -08003454 type, name = correct_name_for_self(self.function)
3455 kwargs = {}
3456 if cls and type == "PyObject *":
3457 kwargs['type'] = cls.typedef
Larry Hastings7726ac92014-01-31 22:03:12 -08003458 sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs)
Larry Hastings5c661892014-01-24 06:17:25 -08003459 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3460 self.function.parameters[sc.name] = p_self
3461
Larry Hastings4a714d42014-01-14 22:22:41 -08003462 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003463 self.next(self.state_parameters_start)
3464
3465 # Now entering the parameters section. The rules, formally stated:
3466 #
3467 # * All lines must be indented with spaces only.
3468 # * The first line must be a parameter declaration.
3469 # * The first line must be indented.
3470 # * This first line establishes the indent for parameters.
3471 # * We'll call this number of spaces P (for "parameter").
3472 # * Thenceforth:
3473 # * Lines indented with P spaces specify a parameter.
3474 # * Lines indented with > P spaces are docstrings for the previous
3475 # parameter.
3476 # * We'll call this number of spaces D (for "docstring").
3477 # * All subsequent lines indented with >= D spaces are stored as
3478 # part of the per-parameter docstring.
3479 # * All lines will have the first D spaces of the indent stripped
3480 # before they are stored.
3481 # * It's illegal to have a line starting with a number of spaces X
3482 # such that P < X < D.
3483 # * A line with < P spaces is the first line of the function
3484 # docstring, which ends processing for parameters and per-parameter
3485 # docstrings.
3486 # * The first line of the function docstring must be at the same
3487 # indent as the function declaration.
3488 # * It's illegal to have any line in the parameters section starting
3489 # with X spaces such that F < X < P. (As before, F is the indent
3490 # of the function declaration.)
3491 #
Larry Hastings31826802013-10-19 00:09:25 -07003492 # Also, currently Argument Clinic places the following restrictions on groups:
3493 # * Each group must contain at least one parameter.
3494 # * Each group may contain at most one group, which must be the furthest
3495 # thing in the group from the required parameters. (The nested group
3496 # must be the first in the group when it's before the required
3497 # parameters, and the last thing in the group when after the required
3498 # parameters.)
3499 # * There may be at most one (top-level) group to the left or right of
3500 # the required parameters.
3501 # * You must specify a slash, and it must be after all parameters.
3502 # (In other words: either all parameters are positional-only,
3503 # or none are.)
3504 #
3505 # Said another way:
3506 # * Each group must contain at least one parameter.
3507 # * All left square brackets before the required parameters must be
3508 # consecutive. (You can't have a left square bracket followed
3509 # by a parameter, then another left square bracket. You can't
3510 # have a left square bracket, a parameter, a right square bracket,
3511 # and then a left square bracket.)
3512 # * All right square brackets after the required parameters must be
3513 # consecutive.
3514 #
3515 # These rules are enforced with a single state variable:
3516 # "parameter_state". (Previously the code was a miasma of ifs and
3517 # separate boolean state variables.) The states are:
3518 #
Larry Hastingsc2047262014-01-25 20:43:29 -08003519 # [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ] / <- line
3520 # 01 2 3 4 5 6 7 <- state transitions
Larry Hastings31826802013-10-19 00:09:25 -07003521 #
3522 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3523 # 1: ps_left_square_before. left square brackets before required parameters.
3524 # 2: ps_group_before. in a group, before required parameters.
Larry Hastingsc2047262014-01-25 20:43:29 -08003525 # 3: ps_required. required parameters, positional-or-keyword or positional-only
3526 # (we don't know yet). (renumber left groups!)
3527 # 4: ps_optional. positional-or-keyword or positional-only parameters that
3528 # now must have default values.
3529 # 5: ps_group_after. in a group, after required parameters.
3530 # 6: ps_right_square_after. right square brackets after required parameters.
3531 # 7: ps_seen_slash. seen slash.
Larry Hastings31826802013-10-19 00:09:25 -07003532 ps_start, ps_left_square_before, ps_group_before, ps_required, \
Larry Hastingsc2047262014-01-25 20:43:29 -08003533 ps_optional, ps_group_after, ps_right_square_after, ps_seen_slash = range(8)
Larry Hastings31826802013-10-19 00:09:25 -07003534
3535 def state_parameters_start(self, line):
3536 if self.ignore_line(line):
3537 return
3538
3539 # if this line is not indented, we have no parameters
3540 if not self.indent.infer(line):
3541 return self.next(self.state_function_docstring, line)
3542
Larry Hastings2a727912014-01-16 11:32:01 -08003543 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003544 return self.next(self.state_parameter, line)
3545
3546
3547 def to_required(self):
3548 """
3549 Transition to the "required" parameter state.
3550 """
3551 if self.parameter_state != self.ps_required:
3552 self.parameter_state = self.ps_required
3553 for p in self.function.parameters.values():
3554 p.group = -p.group
3555
3556 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003557 if self.parameter_continuation:
3558 line = self.parameter_continuation + ' ' + line.lstrip()
3559 self.parameter_continuation = ''
3560
Larry Hastings31826802013-10-19 00:09:25 -07003561 if self.ignore_line(line):
3562 return
3563
3564 assert self.indent.depth == 2
3565 indent = self.indent.infer(line)
3566 if indent == -1:
3567 # we outdented, must be to definition column
3568 return self.next(self.state_function_docstring, line)
3569
3570 if indent == 1:
3571 # we indented, must be to new parameter docstring column
3572 return self.next(self.state_parameter_docstring_start, line)
3573
Larry Hastings2a727912014-01-16 11:32:01 -08003574 line = line.rstrip()
3575 if line.endswith('\\'):
3576 self.parameter_continuation = line[:-1]
3577 return
3578
Larry Hastings31826802013-10-19 00:09:25 -07003579 line = line.lstrip()
3580
3581 if line in ('*', '/', '[', ']'):
3582 self.parse_special_symbol(line)
3583 return
3584
3585 if self.parameter_state in (self.ps_start, self.ps_required):
3586 self.to_required()
3587 elif self.parameter_state == self.ps_left_square_before:
3588 self.parameter_state = self.ps_group_before
3589 elif self.parameter_state == self.ps_group_before:
3590 if not self.group:
3591 self.to_required()
Larry Hastingsc2047262014-01-25 20:43:29 -08003592 elif self.parameter_state in (self.ps_group_after, self.ps_optional):
Larry Hastings31826802013-10-19 00:09:25 -07003593 pass
3594 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003595 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
Larry Hastings31826802013-10-19 00:09:25 -07003596
Larry Hastings7726ac92014-01-31 22:03:12 -08003597 # handle "as" for parameters too
3598 c_name = None
3599 name, have_as_token, trailing = line.partition(' as ')
3600 if have_as_token:
3601 name = name.strip()
3602 if ' ' not in name:
3603 fields = trailing.strip().split(' ')
3604 if not fields:
3605 fail("Invalid 'as' clause!")
3606 c_name = fields[0]
3607 if c_name.endswith(':'):
3608 name += ':'
3609 c_name = c_name[:-1]
3610 fields[0] = name
3611 line = ' '.join(fields)
3612
Larry Hastings2a727912014-01-16 11:32:01 -08003613 base, equals, default = line.rpartition('=')
3614 if not equals:
3615 base = default
3616 default = None
Larry Hastingsc2047262014-01-25 20:43:29 -08003617
Larry Hastings31826802013-10-19 00:09:25 -07003618 module = None
3619 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003620 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003621 module = ast.parse(ast_input)
3622 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003623 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08003624 # the last = was probably inside a function call, like
3625 # i: int(nullable=True)
3626 # so assume there was no actual default value.
Larry Hastings2a727912014-01-16 11:32:01 -08003627 default = None
3628 ast_input = "def x({}): pass".format(line)
3629 module = ast.parse(ast_input)
3630 except SyntaxError:
3631 pass
Larry Hastings31826802013-10-19 00:09:25 -07003632 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003633 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003634
3635 function_args = module.body[0].args
3636 parameter = function_args.args[0]
3637
Larry Hastings16c51912014-01-07 11:53:01 -08003638 parameter_name = parameter.arg
3639 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3640
Larry Hastings2a727912014-01-16 11:32:01 -08003641 if not default:
Larry Hastingsc2047262014-01-25 20:43:29 -08003642 if self.parameter_state == self.ps_optional:
3643 fail("Can't have a parameter without a default (" + repr(parameter_name) + ")\nafter a parameter with a default!")
Larry Hastings2a727912014-01-16 11:32:01 -08003644 value = unspecified
3645 if 'py_default' in kwargs:
3646 fail("You can't specify py_default without specifying a default value!")
3647 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003648 if self.parameter_state == self.ps_required:
3649 self.parameter_state = self.ps_optional
Larry Hastings2a727912014-01-16 11:32:01 -08003650 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003651 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003652 ast_input = "x = {}".format(default)
Larry Hastingsc2047262014-01-25 20:43:29 -08003653 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003654 try:
3655 module = ast.parse(ast_input)
3656
Larry Hastings5c661892014-01-24 06:17:25 -08003657 if 'c_default' not in kwargs:
3658 # we can only represent very simple data values in C.
3659 # detect whether default is okay, via a blacklist
3660 # of disallowed ast nodes.
3661 class DetectBadNodes(ast.NodeVisitor):
3662 bad = False
3663 def bad_node(self, node):
3664 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003665
Larry Hastings5c661892014-01-24 06:17:25 -08003666 # inline function call
3667 visit_Call = bad_node
3668 # inline if statement ("x = 3 if y else z")
3669 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003670
Larry Hastings5c661892014-01-24 06:17:25 -08003671 # comprehensions and generator expressions
3672 visit_ListComp = visit_SetComp = bad_node
3673 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003674
Larry Hastings5c661892014-01-24 06:17:25 -08003675 # literals for advanced types
3676 visit_Dict = visit_Set = bad_node
3677 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003678
Larry Hastings5c661892014-01-24 06:17:25 -08003679 # "starred": "a = [1, 2, 3]; *a"
3680 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003681
Larry Hastings5c661892014-01-24 06:17:25 -08003682 # allow ellipsis, for now
3683 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003684
Larry Hastings5c661892014-01-24 06:17:25 -08003685 blacklist = DetectBadNodes()
3686 blacklist.visit(module)
3687 bad = blacklist.bad
3688 else:
3689 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003690 # but at least make an attempt at ensuring it's a valid expression.
3691 try:
3692 value = eval(default)
3693 if value == unspecified:
3694 fail("'unspecified' is not a legal default value!")
3695 except NameError:
3696 pass # probably a named constant
3697 except Exception as e:
3698 fail("Malformed expression given as default value\n"
3699 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003700 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003701 fail("Unsupported expression as default value: " + repr(default))
3702
3703 expr = module.body[0].value
3704 # mild hack: explicitly support NULL as a default value
3705 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3706 value = NULL
3707 py_default = 'None'
3708 c_default = "NULL"
3709 elif (isinstance(expr, ast.BinOp) or
3710 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3711 c_default = kwargs.get("c_default")
3712 if not (isinstance(c_default, str) and c_default):
3713 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3714 py_default = default
3715 value = unknown
3716 elif isinstance(expr, ast.Attribute):
3717 a = []
3718 n = expr
3719 while isinstance(n, ast.Attribute):
3720 a.append(n.attr)
3721 n = n.value
3722 if not isinstance(n, ast.Name):
3723 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3724 a.append(n.id)
3725 py_default = ".".join(reversed(a))
3726
3727 c_default = kwargs.get("c_default")
3728 if not (isinstance(c_default, str) and c_default):
3729 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3730
3731 try:
3732 value = eval(py_default)
3733 except NameError:
3734 value = unknown
3735 else:
3736 value = ast.literal_eval(expr)
3737 py_default = repr(value)
3738 if isinstance(value, (bool, None.__class__)):
3739 c_default = "Py_" + py_default
3740 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003741 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003742 else:
3743 c_default = py_default
3744
3745 except SyntaxError as e:
3746 fail("Syntax error: " + repr(e.text))
3747 except (ValueError, AttributeError):
3748 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003749 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003750 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003751 if not (isinstance(c_default, str) and c_default):
3752 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3753
Larry Hastings2a727912014-01-16 11:32:01 -08003754 kwargs.setdefault('c_default', c_default)
3755 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003756
Larry Hastings31826802013-10-19 00:09:25 -07003757 dict = legacy_converters if legacy else converters
3758 legacy_str = "legacy " if legacy else ""
3759 if name not in dict:
3760 fail('{} is not a valid {}converter'.format(name, legacy_str))
Larry Hastings7726ac92014-01-31 22:03:12 -08003761 # if you use a c_name for the parameter, we just give that name to the converter
3762 # but the parameter object gets the python name
3763 converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
Larry Hastings31826802013-10-19 00:09:25 -07003764
3765 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003766
3767 if isinstance(converter, self_converter):
3768 if len(self.function.parameters) == 1:
3769 if (self.parameter_state != self.ps_required):
3770 fail("A 'self' parameter cannot be marked optional.")
3771 if value is not unspecified:
3772 fail("A 'self' parameter cannot have a default value.")
3773 if self.group:
3774 fail("A 'self' parameter cannot be in an optional group.")
3775 kind = inspect.Parameter.POSITIONAL_ONLY
3776 self.parameter_state = self.ps_start
3777 self.function.parameters.clear()
3778 else:
3779 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3780
Larry Hastings31826802013-10-19 00:09:25 -07003781 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003782
3783 if parameter_name in self.function.parameters:
3784 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003785 self.function.parameters[parameter_name] = p
3786
3787 def parse_converter(self, annotation):
3788 if isinstance(annotation, ast.Str):
3789 return annotation.s, True, {}
3790
3791 if isinstance(annotation, ast.Name):
3792 return annotation.id, False, {}
3793
Larry Hastings4a55fc52014-01-12 11:09:57 -08003794 if not isinstance(annotation, ast.Call):
3795 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003796
3797 name = annotation.func.id
3798 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
3799 return name, False, kwargs
3800
3801 def parse_special_symbol(self, symbol):
3802 if self.parameter_state == self.ps_seen_slash:
3803 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3804
3805 if symbol == '*':
3806 if self.keyword_only:
3807 fail("Function " + self.function.name + " uses '*' more than once.")
3808 self.keyword_only = True
3809 elif symbol == '[':
3810 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3811 self.parameter_state = self.ps_left_square_before
3812 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3813 self.parameter_state = self.ps_group_after
3814 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003815 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
Larry Hastings31826802013-10-19 00:09:25 -07003816 self.group += 1
Larry Hastings2623c8c2014-02-08 22:15:29 -08003817 self.function.docstring_only = True
Larry Hastings31826802013-10-19 00:09:25 -07003818 elif symbol == ']':
3819 if not self.group:
3820 fail("Function " + self.function.name + " has a ] without a matching [.")
3821 if not any(p.group == self.group for p in self.function.parameters.values()):
3822 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3823 self.group -= 1
3824 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3825 self.parameter_state = self.ps_group_before
3826 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3827 self.parameter_state = self.ps_right_square_after
3828 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003829 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
Larry Hastings31826802013-10-19 00:09:25 -07003830 elif symbol == '/':
Larry Hastingsc2047262014-01-25 20:43:29 -08003831 # ps_required and ps_optional are allowed here, that allows positional-only without option groups
Larry Hastings31826802013-10-19 00:09:25 -07003832 # to work (and have default values!)
Larry Hastingsc2047262014-01-25 20:43:29 -08003833 if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
3834 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
Larry Hastings31826802013-10-19 00:09:25 -07003835 if self.keyword_only:
3836 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3837 self.parameter_state = self.ps_seen_slash
Berker Peksagf23530f2014-10-19 18:04:38 +03003838 # fixup preceding parameters
Larry Hastings31826802013-10-19 00:09:25 -07003839 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003840 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003841 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3842 p.kind = inspect.Parameter.POSITIONAL_ONLY
3843
3844 def state_parameter_docstring_start(self, line):
3845 self.parameter_docstring_indent = len(self.indent.margin)
3846 assert self.indent.depth == 3
3847 return self.next(self.state_parameter_docstring, line)
3848
3849 # every line of the docstring must start with at least F spaces,
3850 # where F > P.
3851 # these F spaces will be stripped.
3852 def state_parameter_docstring(self, line):
3853 stripped = line.strip()
3854 if stripped.startswith('#'):
3855 return
3856
3857 indent = self.indent.measure(line)
3858 if indent < self.parameter_docstring_indent:
3859 self.indent.infer(line)
3860 assert self.indent.depth < 3
3861 if self.indent.depth == 2:
3862 # back to a parameter
3863 return self.next(self.state_parameter, line)
3864 assert self.indent.depth == 1
3865 return self.next(self.state_function_docstring, line)
3866
3867 assert self.function.parameters
3868 last_parameter = next(reversed(list(self.function.parameters.values())))
3869
3870 new_docstring = last_parameter.docstring
3871
3872 if new_docstring:
3873 new_docstring += '\n'
3874 if stripped:
3875 new_docstring += self.indent.dedent(line)
3876
3877 last_parameter.docstring = new_docstring
3878
3879 # the final stanza of the DSL is the docstring.
3880 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003881 if self.group:
3882 fail("Function " + self.function.name + " has a ] without a matching [.")
3883
3884 stripped = line.strip()
3885 if stripped.startswith('#'):
3886 return
3887
3888 new_docstring = self.function.docstring
3889 if new_docstring:
3890 new_docstring += "\n"
3891 if stripped:
3892 line = self.indent.dedent(line).rstrip()
3893 else:
3894 line = ''
3895 new_docstring += line
3896 self.function.docstring = new_docstring
3897
3898 def format_docstring(self):
3899 f = self.function
3900
Larry Hastings5c661892014-01-24 06:17:25 -08003901 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3902 if new_or_init and not f.docstring:
3903 # don't render a docstring at all, no signature, nothing.
3904 return f.docstring
3905
Larry Hastings2623c8c2014-02-08 22:15:29 -08003906 text, add, output = _text_accumulator()
Larry Hastings7726ac92014-01-31 22:03:12 -08003907 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07003908
3909 ##
3910 ## docstring first line
3911 ##
3912
Larry Hastings2623c8c2014-02-08 22:15:29 -08003913 if new_or_init:
3914 # classes get *just* the name of the class
3915 # not __new__, not __init__, and not module.classname
3916 assert f.cls
3917 add(f.cls.name)
Larry Hastings46258262014-01-22 03:05:49 -08003918 else:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003919 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003920 add('(')
3921
3922 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003923 assert parameters, "We should always have a self parameter. " + repr(f)
3924 assert isinstance(parameters[0].converter, self_converter)
3925 parameters[0].right_bracket_count = 0
3926 parameters_after_self = parameters[1:]
3927 if parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003928 # for now, the only way Clinic supports positional-only parameters
Larry Hastings5c661892014-01-24 06:17:25 -08003929 # is if all of them are positional-only...
3930 #
3931 # ... except for self! self is always positional-only.
3932
3933 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters_after_self]
3934 if parameters_after_self[0].kind == inspect.Parameter.POSITIONAL_ONLY:
Larry Hastings31826802013-10-19 00:09:25 -07003935 assert all(positional_only_parameters)
3936 for p in parameters:
3937 p.right_bracket_count = abs(p.group)
3938 else:
3939 # don't put any right brackets around non-positional-only parameters, ever.
Larry Hastings5c661892014-01-24 06:17:25 -08003940 for p in parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003941 p.right_bracket_count = 0
3942
3943 right_bracket_count = 0
3944
3945 def fix_right_bracket_count(desired):
3946 nonlocal right_bracket_count
3947 s = ''
3948 while right_bracket_count < desired:
3949 s += '['
3950 right_bracket_count += 1
3951 while right_bracket_count > desired:
3952 s += ']'
3953 right_bracket_count -= 1
3954 return s
3955
Larry Hastings2623c8c2014-02-08 22:15:29 -08003956 need_slash = False
3957 added_slash = False
3958 need_a_trailing_slash = False
3959
3960 # we only need a trailing slash:
3961 # * if this is not a "docstring_only" signature
3962 # * and if the last *shown* parameter is
3963 # positional only
3964 if not f.docstring_only:
3965 for p in reversed(parameters):
3966 if not p.converter.show_in_signature:
3967 continue
3968 if p.is_positional_only():
3969 need_a_trailing_slash = True
3970 break
3971
3972
Larry Hastings31826802013-10-19 00:09:25 -07003973 added_star = False
Larry Hastings2623c8c2014-02-08 22:15:29 -08003974
3975 first_parameter = True
3976 last_p = parameters[-1]
3977 line_length = len(''.join(text))
3978 indent = " " * line_length
3979 def add_parameter(text):
3980 nonlocal line_length
3981 nonlocal first_parameter
3982 if first_parameter:
3983 s = text
3984 first_parameter = False
3985 else:
3986 s = ' ' + text
3987 if line_length + len(s) >= 72:
3988 add('\n')
3989 add(indent)
3990 line_length = len(indent)
3991 s = text
3992 line_length += len(s)
3993 add(s)
Larry Hastings31826802013-10-19 00:09:25 -07003994
3995 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08003996 if not p.converter.show_in_signature:
3997 continue
Larry Hastings31826802013-10-19 00:09:25 -07003998 assert p.name
3999
Larry Hastings2623c8c2014-02-08 22:15:29 -08004000 is_self = isinstance(p.converter, self_converter)
4001 if is_self and f.docstring_only:
4002 # this isn't a real machine-parsable signature,
4003 # so let's not print the "self" parameter
4004 continue
4005
4006 if p.is_positional_only():
4007 need_slash = not f.docstring_only
4008 elif need_slash and not (added_slash or p.is_positional_only()):
4009 added_slash = True
4010 add_parameter('/,')
4011
Larry Hastings31826802013-10-19 00:09:25 -07004012 if p.is_keyword_only() and not added_star:
4013 added_star = True
Larry Hastings2623c8c2014-02-08 22:15:29 -08004014 add_parameter('*,')
4015
4016 p_add, p_output = text_accumulator()
4017 p_add(fix_right_bracket_count(p.right_bracket_count))
4018
4019 if isinstance(p.converter, self_converter):
4020 # annotate first parameter as being a "self".
4021 #
4022 # if inspect.Signature gets this function,
4023 # and it's already bound, the self parameter
4024 # will be stripped off.
4025 #
4026 # if it's not bound, it should be marked
4027 # as positional-only.
4028 #
4029 # note: we don't print "self" for __init__,
4030 # because this isn't actually the signature
4031 # for __init__. (it can't be, __init__ doesn't
4032 # have a docstring.) if this is an __init__
4033 # (or __new__), then this signature is for
Berker Peksagf23530f2014-10-19 18:04:38 +03004034 # calling the class to construct a new instance.
Larry Hastings2623c8c2014-02-08 22:15:29 -08004035 p_add('$')
Larry Hastings31826802013-10-19 00:09:25 -07004036
Larry Hastings5c661892014-01-24 06:17:25 -08004037 name = p.converter.signature_name or p.name
Larry Hastings2623c8c2014-02-08 22:15:29 -08004038 p_add(name)
Larry Hastings581ee362014-01-28 05:00:08 -08004039
Larry Hastings31826802013-10-19 00:09:25 -07004040 if p.converter.is_optional():
Larry Hastings2623c8c2014-02-08 22:15:29 -08004041 p_add('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08004042 value = p.converter.py_default
4043 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08004044 value = repr(p.converter.default)
Larry Hastings2623c8c2014-02-08 22:15:29 -08004045 p_add(value)
4046
4047 if (p != last_p) or need_a_trailing_slash:
4048 p_add(',')
4049
4050 add_parameter(p_output())
Larry Hastings31826802013-10-19 00:09:25 -07004051
4052 add(fix_right_bracket_count(0))
Larry Hastings2623c8c2014-02-08 22:15:29 -08004053 if need_a_trailing_slash:
4054 add_parameter('/')
Larry Hastings31826802013-10-19 00:09:25 -07004055 add(')')
4056
Larry Hastings2a727912014-01-16 11:32:01 -08004057 # PEP 8 says:
4058 #
4059 # The Python standard library will not use function annotations
4060 # as that would result in a premature commitment to a particular
4061 # annotation style. Instead, the annotations are left for users
4062 # to discover and experiment with useful annotation styles.
4063 #
4064 # therefore this is commented out:
4065 #
4066 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004067 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08004068 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07004069
Larry Hastings2623c8c2014-02-08 22:15:29 -08004070 if not f.docstring_only:
Zachary Ware8ef887c2015-04-13 18:22:35 -05004071 add("\n" + sig_end_marker + "\n")
Larry Hastings2623c8c2014-02-08 22:15:29 -08004072
Larry Hastings31826802013-10-19 00:09:25 -07004073 docstring_first_line = output()
4074
4075 # now fix up the places where the brackets look wrong
4076 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
4077
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004078 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07004079 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004080 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07004081 for p in parameters:
4082 if not p.docstring.strip():
4083 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004084 if spacer_line:
4085 add('\n')
4086 else:
4087 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07004088 add(" ")
4089 add(p.name)
4090 add('\n')
4091 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004092 parameters = output()
4093 if parameters:
4094 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07004095
4096 ##
4097 ## docstring body
4098 ##
4099
4100 docstring = f.docstring.rstrip()
4101 lines = [line.rstrip() for line in docstring.split('\n')]
4102
4103 # Enforce the summary line!
4104 # The first line of a docstring should be a summary of the function.
4105 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
4106 # by itself.
4107 #
4108 # Argument Clinic enforces the following rule:
4109 # * either the docstring is empty,
4110 # * or it must have a summary line.
4111 #
4112 # Guido said Clinic should enforce this:
4113 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
4114
4115 if len(lines) >= 2:
4116 if lines[1]:
4117 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
4118 "Every non-blank function docstring must start with\n" +
4119 "a single line summary followed by an empty line.")
4120 elif len(lines) == 1:
4121 # the docstring is only one line right now--the summary line.
4122 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004123 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07004124 lines.append('')
4125
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004126 parameters_marker_count = len(docstring.split('{parameters}')) - 1
4127 if parameters_marker_count > 1:
4128 fail('You may not specify {parameters} more than once in a docstring!')
4129
4130 if not parameters_marker_count:
4131 # insert after summary line
4132 lines.insert(2, '{parameters}')
4133
4134 # insert at front of docstring
4135 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07004136
4137 docstring = "\n".join(lines)
4138
4139 add(docstring)
4140 docstring = output()
4141
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004142 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07004143 docstring = docstring.rstrip()
4144
4145 return docstring
4146
4147 def state_terminal(self, line):
4148 """
4149 Called when processing the block is done.
4150 """
4151 assert not line
4152
4153 if not self.function:
4154 return
4155
4156 if self.keyword_only:
4157 values = self.function.parameters.values()
4158 if not values:
4159 no_parameter_after_star = True
4160 else:
4161 last_parameter = next(reversed(list(values)))
4162 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
4163 if no_parameter_after_star:
4164 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
4165
4166 # remove trailing whitespace from all parameter docstrings
4167 for name, value in self.function.parameters.items():
4168 if not value:
4169 continue
4170 value.docstring = value.docstring.rstrip()
4171
4172 self.function.docstring = self.format_docstring()
4173
4174
Larry Hastings5c661892014-01-24 06:17:25 -08004175
4176
Larry Hastings31826802013-10-19 00:09:25 -07004177# maps strings to callables.
4178# the callable should return an object
4179# that implements the clinic parser
4180# interface (__init__ and parse).
4181#
4182# example parsers:
4183# "clinic", handles the Clinic DSL
4184# "python", handles running Python code
4185#
4186parsers = {'clinic' : DSLParser, 'python': PythonParser}
4187
4188
4189clinic = None
4190
4191
4192def main(argv):
4193 import sys
4194
4195 if sys.version_info.major < 3 or sys.version_info.minor < 3:
4196 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
4197
4198 import argparse
4199 cmdline = argparse.ArgumentParser()
4200 cmdline.add_argument("-f", "--force", action='store_true')
4201 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08004202 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004203 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004204 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004205 cmdline.add_argument("filename", type=str, nargs="*")
4206 ns = cmdline.parse_args(argv)
4207
4208 if ns.converters:
4209 if ns.filename:
4210 print("Usage error: can't specify --converters and a filename at the same time.")
4211 print()
4212 cmdline.print_usage()
4213 sys.exit(-1)
4214 converters = []
4215 return_converters = []
4216 ignored = set("""
4217 add_c_converter
4218 add_c_return_converter
4219 add_default_legacy_c_converter
4220 add_legacy_c_converter
4221 """.strip().split())
4222 module = globals()
4223 for name in module:
4224 for suffix, ids in (
4225 ("_return_converter", return_converters),
4226 ("_converter", converters),
4227 ):
4228 if name in ignored:
4229 continue
4230 if name.endswith(suffix):
4231 ids.append((name, name[:-len(suffix)]))
4232 break
4233 print()
4234
4235 print("Legacy converters:")
4236 legacy = sorted(legacy_converters)
4237 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
4238 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
4239 print()
4240
4241 for title, attribute, ids in (
4242 ("Converters", 'converter_init', converters),
4243 ("Return converters", 'return_converter_init', return_converters),
4244 ):
4245 print(title + ":")
4246 longest = -1
4247 for name, short_name in ids:
4248 longest = max(longest, len(short_name))
4249 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
4250 cls = module[name]
4251 callable = getattr(cls, attribute, None)
4252 if not callable:
4253 continue
4254 signature = inspect.signature(callable)
4255 parameters = []
4256 for parameter_name, parameter in signature.parameters.items():
4257 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
4258 if parameter.default != inspect.Parameter.empty:
4259 s = '{}={!r}'.format(parameter_name, parameter.default)
4260 else:
4261 s = parameter_name
4262 parameters.append(s)
4263 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07004264 print()
Larry Hastings2a727912014-01-16 11:32:01 -08004265 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
4266 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07004267 sys.exit(0)
4268
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004269 if ns.make:
4270 if ns.output or ns.filename:
4271 print("Usage error: can't use -o or filenames with --make.")
4272 print()
4273 cmdline.print_usage()
4274 sys.exit(-1)
4275 for root, dirs, files in os.walk('.'):
Zachary Warebbbbe7e2015-04-13 18:33:41 -05004276 for rcs_dir in ('.svn', '.git', '.hg', 'build', 'externals'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004277 if rcs_dir in dirs:
4278 dirs.remove(rcs_dir)
4279 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08004280 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004281 continue
4282 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08004283 if ns.verbose:
4284 print(path)
Larry Hastings581ee362014-01-28 05:00:08 -08004285 parse_file(path, force=ns.force, verify=not ns.force)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004286 return
4287
Larry Hastings31826802013-10-19 00:09:25 -07004288 if not ns.filename:
4289 cmdline.print_usage()
4290 sys.exit(-1)
4291
4292 if ns.output and len(ns.filename) > 1:
4293 print("Usage error: can't use -o with multiple filenames.")
4294 print()
4295 cmdline.print_usage()
4296 sys.exit(-1)
4297
4298 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08004299 if ns.verbose:
4300 print(filename)
Larry Hastings581ee362014-01-28 05:00:08 -08004301 parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
Larry Hastings31826802013-10-19 00:09:25 -07004302
4303
4304if __name__ == "__main__":
4305 sys.exit(main(sys.argv[1:]))