blob: 5626dd9fdcd177af426c50f2ce6e9f3b865f1e72 [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("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300789 if (!PyArg_Parse(%s, "{format_units}:{name}", {parse_arguments}))
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300790 goto exit;
791 """ % argname, indent=4))
Larry Hastings31826802013-10-19 00:09:25 -0700792
Larry Hastingsbebf7352014-01-17 17:47:17 -0800793 elif has_option_groups:
794 # positional parameters with option groups
795 # (we have to generate lots of PyArg_ParseTuple calls
796 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700797
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800798 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800799 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700800
Larry Hastings7726ac92014-01-31 22:03:12 -0800801 parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')
Larry Hastings31826802013-10-19 00:09:25 -0700802
Larry Hastingsbebf7352014-01-17 17:47:17 -0800803 elif positional and all_boring_objects:
804 # positional-only, but no option groups,
805 # and nothing but normal objects:
806 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700807
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800808 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800809 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700810
Larry Hastings7726ac92014-01-31 22:03:12 -0800811 parser_definition = parser_body(parser_prototype, normalize_snippet("""
812 if (!PyArg_UnpackTuple(args, "{name}",
813 {unpack_min}, {unpack_max},
814 {parse_arguments}))
815 goto exit;
816 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800817
818 elif positional:
819 # positional-only, but no option groups
820 # we only need one call to PyArg_ParseTuple
821
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800822 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800823 parser_prototype = parser_prototype_varargs
Larry Hastingsbebf7352014-01-17 17:47:17 -0800824
Larry Hastings7726ac92014-01-31 22:03:12 -0800825 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300826 if (!PyArg_ParseTuple(args, "{format_units}:{name}",
Larry Hastings7726ac92014-01-31 22:03:12 -0800827 {parse_arguments}))
828 goto exit;
829 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800830
831 else:
832 # positional-or-keyword arguments
833 flags = "METH_VARARGS|METH_KEYWORDS"
834
Larry Hastings7726ac92014-01-31 22:03:12 -0800835 parser_prototype = parser_prototype_keyword
Larry Hastingsbebf7352014-01-17 17:47:17 -0800836
Larry Hastings7726ac92014-01-31 22:03:12 -0800837 body = normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300838 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords,
Larry Hastings7726ac92014-01-31 22:03:12 -0800839 {parse_arguments}))
840 goto exit;
841 """, indent=4)
842 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300843 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords,
Larry Hastings7726ac92014-01-31 22:03:12 -0800844 {parse_arguments}))
845 goto exit;
846 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800847 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700848
Larry Hastings31826802013-10-19 00:09:25 -0700849
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800850 if new_or_init:
851 methoddef_define = ''
852
853 if f.kind == METHOD_NEW:
Larry Hastings7726ac92014-01-31 22:03:12 -0800854 parser_prototype = parser_prototype_keyword
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800855 else:
856 return_value_declaration = "int return_value = -1;"
Larry Hastings7726ac92014-01-31 22:03:12 -0800857 parser_prototype = normalize_snippet("""
858 static int
859 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
860 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800861
862 fields = list(parser_body_fields)
863 parses_positional = 'METH_NOARGS' not in flags
864 parses_keywords = 'METH_KEYWORDS' in flags
865 if parses_keywords:
866 assert parses_positional
867
868 if not parses_keywords:
Larry Hastings7726ac92014-01-31 22:03:12 -0800869 fields.insert(0, normalize_snippet("""
870 if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs))
871 goto exit;
872 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800873 if not parses_positional:
Larry Hastings7726ac92014-01-31 22:03:12 -0800874 fields.insert(0, normalize_snippet("""
875 if ({self_type_check}!_PyArg_NoPositional("{name}", args))
876 goto exit;
877 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800878
879 parser_definition = parser_body(parser_prototype, *fields)
880 if parses_keywords:
881 parser_definition = insert_keywords(parser_definition)
882
Larry Hastings31826802013-10-19 00:09:25 -0700883
Larry Hastingsbebf7352014-01-17 17:47:17 -0800884 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800885 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700886
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800887 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700888
Larry Hastings7726ac92014-01-31 22:03:12 -0800889 methoddef_ifndef = ''
890 conditional = self.cpp.condition()
891 if not conditional:
892 cpp_if = cpp_endif = ''
893 else:
894 cpp_if = "#if " + conditional
895 cpp_endif = "#endif /* " + conditional + " */"
896
Larry Hastings0759f842015-04-03 13:09:02 -0700897 if methoddef_define and f.name not in clinic.ifndef_symbols:
898 clinic.ifndef_symbols.add(f.name)
Larry Hastings7726ac92014-01-31 22:03:12 -0800899 methoddef_ifndef = normalize_snippet("""
900 #ifndef {methoddef_name}
901 #define {methoddef_name}
902 #endif /* !defined({methoddef_name}) */
903 """)
904
905
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800906 # add ';' to the end of parser_prototype and impl_prototype
907 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800908 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800909 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800910 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800911 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700912
Larry Hastingsbebf7352014-01-17 17:47:17 -0800913 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800914 impl_prototype = impl_definition
915 if impl_prototype:
916 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700917
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800918 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800919
920 d = {
921 "docstring_prototype" : docstring_prototype,
922 "docstring_definition" : docstring_definition,
923 "impl_prototype" : impl_prototype,
924 "methoddef_define" : methoddef_define,
925 "parser_prototype" : parser_prototype,
926 "parser_definition" : parser_definition,
927 "impl_definition" : impl_definition,
Larry Hastings7726ac92014-01-31 22:03:12 -0800928 "cpp_if" : cpp_if,
929 "cpp_endif" : cpp_endif,
930 "methoddef_ifndef" : methoddef_ifndef,
Larry Hastingsbebf7352014-01-17 17:47:17 -0800931 }
932
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800933 # make sure we didn't forget to assign something,
934 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -0800935 d2 = {}
936 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800937 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800938 if value:
939 value = '\n' + value + '\n'
940 d2[name] = value
941 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700942
943 @staticmethod
944 def group_to_variable_name(group):
945 adjective = "left_" if group < 0 else "right_"
946 return "group_" + adjective + str(abs(group))
947
948 def render_option_group_parsing(self, f, template_dict):
949 # positional only, grouped, optional arguments!
950 # can be optional on the left or right.
951 # here's an example:
952 #
953 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
954 #
955 # Here group D are required, and all other groups are optional.
956 # (Group D's "group" is actually None.)
957 # We can figure out which sets of arguments we have based on
958 # how many arguments are in the tuple.
959 #
960 # Note that you need to count up on both sides. For example,
961 # you could have groups C+D, or C+D+E, or C+D+E+F.
962 #
963 # What if the number of arguments leads us to an ambiguous result?
964 # Clinic prefers groups on the left. So in the above example,
965 # five arguments would map to B+C, not C+D.
966
967 add, output = text_accumulator()
968 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800969 if isinstance(parameters[0].converter, self_converter):
970 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -0700971
972 groups = []
973 group = None
974 left = []
975 right = []
976 required = []
977 last = unspecified
978
979 for p in parameters:
980 group_id = p.group
981 if group_id != last:
982 last = group_id
983 group = []
984 if group_id < 0:
985 left.append(group)
986 elif group_id == 0:
987 group = required
988 else:
989 right.append(group)
990 group.append(p)
991
992 count_min = sys.maxsize
993 count_max = -1
994
Larry Hastings2a727912014-01-16 11:32:01 -0800995 add("switch (PyTuple_GET_SIZE(args)) {{\n")
Larry Hastings31826802013-10-19 00:09:25 -0700996 for subset in permute_optional_groups(left, required, right):
997 count = len(subset)
998 count_min = min(count_min, count)
999 count_max = max(count_max, count)
1000
Larry Hastings583baa82014-01-12 08:49:30 -08001001 if count == 0:
1002 add(""" case 0:
1003 break;
1004""")
1005 continue
1006
Larry Hastings31826802013-10-19 00:09:25 -07001007 group_ids = {p.group for p in subset} # eliminate duplicates
1008 d = {}
1009 d['count'] = count
1010 d['name'] = f.name
1011 d['groups'] = sorted(group_ids)
1012 d['format_units'] = "".join(p.converter.format_unit for p in subset)
1013
1014 parse_arguments = []
1015 for p in subset:
1016 p.converter.parse_argument(parse_arguments)
1017 d['parse_arguments'] = ", ".join(parse_arguments)
1018
1019 group_ids.discard(0)
1020 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
1021 lines = "\n".join(lines)
1022
1023 s = """
1024 case {count}:
1025 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
Larry Hastings46258262014-01-22 03:05:49 -08001026 goto exit;
Larry Hastings31826802013-10-19 00:09:25 -07001027 {group_booleans}
1028 break;
1029"""[1:]
1030 s = linear_format(s, group_booleans=lines)
1031 s = s.format_map(d)
1032 add(s)
1033
1034 add(" default:\n")
1035 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
1036 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -08001037 add(' goto exit;\n')
Larry Hastings31826802013-10-19 00:09:25 -07001038 add("}}")
1039 template_dict['option_group_parsing'] = output()
1040
Larry Hastingsbebf7352014-01-17 17:47:17 -08001041 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -07001042 if not f:
1043 return ""
1044
1045 add, output = text_accumulator()
1046 data = CRenderData()
1047
Larry Hastings7726ac92014-01-31 22:03:12 -08001048 assert f.parameters, "We should always have a 'self' at this point!"
1049 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07001050 converters = [p.converter for p in parameters]
1051
Larry Hastings5c661892014-01-24 06:17:25 -08001052 templates = self.output_templates(f)
1053
1054 f_self = parameters[0]
1055 selfless = parameters[1:]
1056 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
1057
1058 last_group = 0
1059 first_optional = len(selfless)
1060 positional = selfless and selfless[-1].kind == inspect.Parameter.POSITIONAL_ONLY
1061 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
1062 default_return_converter = (not f.return_converter or
1063 f.return_converter.type == 'PyObject *')
1064 has_option_groups = False
1065
1066 # offset i by -1 because first_optional needs to ignore self
1067 for i, p in enumerate(parameters, -1):
1068 c = p.converter
1069
1070 if (i != -1) and (p.default is not unspecified):
1071 first_optional = min(first_optional, i)
1072
1073 # insert group variable
1074 group = p.group
1075 if last_group != group:
1076 last_group = group
1077 if group:
1078 group_name = self.group_to_variable_name(group)
1079 data.impl_arguments.append(group_name)
1080 data.declarations.append("int " + group_name + " = 0;")
1081 data.impl_parameters.append("int " + group_name)
1082 has_option_groups = True
1083
1084 c.render(p, data)
1085
1086 if has_option_groups and (not positional):
1087 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
1088
1089 # HACK
1090 # when we're METH_O, but have a custom return converter,
1091 # we use "impl_parameters" for the parsing function
1092 # because that works better. but that means we must
Berker Peksagf23530f2014-10-19 18:04:38 +03001093 # suppress actually declaring the impl's parameters
Larry Hastings5c661892014-01-24 06:17:25 -08001094 # as variables in the parsing function. but since it's
1095 # METH_O, we have exactly one anyway, so we know exactly
1096 # where it is.
1097 if ("METH_O" in templates['methoddef_define'] and
Serhiy Storchaka92e8af62015-04-04 00:12:11 +03001098 '{impl_parameters}' in templates['parser_prototype']):
Larry Hastings5c661892014-01-24 06:17:25 -08001099 data.declarations.pop(0)
1100
Larry Hastings31826802013-10-19 00:09:25 -07001101 template_dict = {}
1102
1103 full_name = f.full_name
1104 template_dict['full_name'] = full_name
1105
Larry Hastings5c661892014-01-24 06:17:25 -08001106 if new_or_init:
1107 name = f.cls.name
1108 else:
1109 name = f.name
1110
Larry Hastings31826802013-10-19 00:09:25 -07001111 template_dict['name'] = name
1112
Larry Hastings8666e652014-01-12 14:12:59 -08001113 if f.c_basename:
1114 c_basename = f.c_basename
1115 else:
1116 fields = full_name.split(".")
1117 if fields[-1] == '__new__':
1118 fields.pop()
1119 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001120
Larry Hastings31826802013-10-19 00:09:25 -07001121 template_dict['c_basename'] = c_basename
1122
1123 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1124 template_dict['methoddef_name'] = methoddef_name
1125
1126 template_dict['docstring'] = self.docstring_for_c_string(f)
1127
Larry Hastingsc2047262014-01-25 20:43:29 -08001128 template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
Larry Hastings5c661892014-01-24 06:17:25 -08001129 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001130
Larry Hastings31826802013-10-19 00:09:25 -07001131 f.return_converter.render(f, data)
1132 template_dict['impl_return_type'] = f.return_converter.type
1133
1134 template_dict['declarations'] = "\n".join(data.declarations)
1135 template_dict['initializers'] = "\n\n".join(data.initializers)
Larry Hastingsc2047262014-01-25 20:43:29 -08001136 template_dict['modifications'] = '\n\n'.join(data.modifications)
Larry Hastings31826802013-10-19 00:09:25 -07001137 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1138 template_dict['format_units'] = ''.join(data.format_units)
1139 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1140 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1141 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
1142 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
1143 template_dict['cleanup'] = "".join(data.cleanup)
1144 template_dict['return_value'] = data.return_value
1145
Larry Hastings5c661892014-01-24 06:17:25 -08001146 # used by unpack tuple code generator
1147 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1148 unpack_min = first_optional
1149 unpack_max = len(selfless)
1150 template_dict['unpack_min'] = str(unpack_min)
1151 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001152
Larry Hastingsbebf7352014-01-17 17:47:17 -08001153 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001154 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001155
Larry Hastings0759f842015-04-03 13:09:02 -07001156 # buffers, not destination
1157 for name, destination in clinic.destination_buffers.items():
Larry Hastingsbebf7352014-01-17 17:47:17 -08001158 template = templates[name]
1159 if has_option_groups:
1160 template = linear_format(template,
1161 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001162 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001163 declarations=template_dict['declarations'],
1164 return_conversion=template_dict['return_conversion'],
1165 initializers=template_dict['initializers'],
Larry Hastingsc2047262014-01-25 20:43:29 -08001166 modifications=template_dict['modifications'],
Larry Hastingsbebf7352014-01-17 17:47:17 -08001167 cleanup=template_dict['cleanup'],
1168 )
Larry Hastings31826802013-10-19 00:09:25 -07001169
Larry Hastingsbebf7352014-01-17 17:47:17 -08001170 # Only generate the "exit:" label
1171 # if we have any gotos
1172 need_exit_label = "goto exit;" in template
1173 template = linear_format(template,
1174 exit_label="exit:" if need_exit_label else ''
1175 )
Larry Hastings31826802013-10-19 00:09:25 -07001176
Larry Hastingsbebf7352014-01-17 17:47:17 -08001177 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001178
Larry Hastings89964c42015-04-14 18:07:59 -04001179 # mild hack:
1180 # reflow long impl declarations
1181 if name in {"impl_prototype", "impl_definition"}:
1182 s = wrap_declarations(s)
1183
Larry Hastingsbebf7352014-01-17 17:47:17 -08001184 if clinic.line_prefix:
1185 s = indent_all_lines(s, clinic.line_prefix)
1186 if clinic.line_suffix:
1187 s = suffix_all_lines(s, clinic.line_suffix)
1188
1189 destination.append(s)
1190
1191 return clinic.get_destination('block').dump()
1192
Larry Hastings31826802013-10-19 00:09:25 -07001193
1194
Larry Hastings5c661892014-01-24 06:17:25 -08001195
Larry Hastings31826802013-10-19 00:09:25 -07001196@contextlib.contextmanager
1197def OverrideStdioWith(stdout):
1198 saved_stdout = sys.stdout
1199 sys.stdout = stdout
1200 try:
1201 yield
1202 finally:
1203 assert sys.stdout is stdout
1204 sys.stdout = saved_stdout
1205
1206
Larry Hastings2623c8c2014-02-08 22:15:29 -08001207def create_regex(before, after, word=True, whole_line=True):
Larry Hastings31826802013-10-19 00:09:25 -07001208 """Create an re object for matching marker lines."""
Larry Hastings581ee362014-01-28 05:00:08 -08001209 group_re = "\w+" if word else ".+"
Larry Hastings2623c8c2014-02-08 22:15:29 -08001210 pattern = r'{}({}){}'
1211 if whole_line:
1212 pattern = '^' + pattern + '$'
Larry Hastings581ee362014-01-28 05:00:08 -08001213 pattern = pattern.format(re.escape(before), group_re, re.escape(after))
1214 return re.compile(pattern)
Larry Hastings31826802013-10-19 00:09:25 -07001215
1216
1217class Block:
1218 r"""
1219 Represents a single block of text embedded in
1220 another file. If dsl_name is None, the block represents
1221 verbatim text, raw original text from the file, in
1222 which case "input" will be the only non-false member.
1223 If dsl_name is not None, the block represents a Clinic
1224 block.
1225
1226 input is always str, with embedded \n characters.
1227 input represents the original text from the file;
1228 if it's a Clinic block, it is the original text with
1229 the body_prefix and redundant leading whitespace removed.
1230
1231 dsl_name is either str or None. If str, it's the text
1232 found on the start line of the block between the square
1233 brackets.
1234
1235 signatures is either list or None. If it's a list,
1236 it may only contain clinic.Module, clinic.Class, and
1237 clinic.Function objects. At the moment it should
1238 contain at most one of each.
1239
1240 output is either str or None. If str, it's the output
1241 from this block, with embedded '\n' characters.
1242
1243 indent is either str or None. It's the leading whitespace
1244 that was found on every line of input. (If body_prefix is
1245 not empty, this is the indent *after* removing the
1246 body_prefix.)
1247
1248 preindent is either str or None. It's the whitespace that
1249 was found in front of every line of input *before* the
1250 "body_prefix" (see the Language object). If body_prefix
1251 is empty, preindent must always be empty too.
1252
1253 To illustrate indent and preindent: Assume that '_'
1254 represents whitespace. If the block processed was in a
1255 Python file, and looked like this:
1256 ____#/*[python]
1257 ____#__for a in range(20):
1258 ____#____print(a)
1259 ____#[python]*/
1260 "preindent" would be "____" and "indent" would be "__".
1261
1262 """
1263 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1264 assert isinstance(input, str)
1265 self.input = input
1266 self.dsl_name = dsl_name
1267 self.signatures = signatures or []
1268 self.output = output
1269 self.indent = indent
1270 self.preindent = preindent
1271
Larry Hastings581ee362014-01-28 05:00:08 -08001272 def __repr__(self):
1273 dsl_name = self.dsl_name or "text"
1274 def summarize(s):
1275 s = repr(s)
1276 if len(s) > 30:
1277 return s[:26] + "..." + s[0]
1278 return s
1279 return "".join((
1280 "<Block ", dsl_name, " input=", summarize(self.input), " output=", summarize(self.output), ">"))
1281
Larry Hastings31826802013-10-19 00:09:25 -07001282
1283class BlockParser:
1284 """
1285 Block-oriented parser for Argument Clinic.
1286 Iterator, yields Block objects.
1287 """
1288
1289 def __init__(self, input, language, *, verify=True):
1290 """
1291 "input" should be a str object
1292 with embedded \n characters.
1293
1294 "language" should be a Language object.
1295 """
1296 language.validate()
1297
1298 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1299 self.block_start_line_number = self.line_number = 0
1300
1301 self.language = language
1302 before, _, after = language.start_line.partition('{dsl_name}')
1303 assert _ == '{dsl_name}'
Larry Hastings2623c8c2014-02-08 22:15:29 -08001304 self.find_start_re = create_regex(before, after, whole_line=False)
Larry Hastings31826802013-10-19 00:09:25 -07001305 self.start_re = create_regex(before, after)
1306 self.verify = verify
1307 self.last_checksum_re = None
1308 self.last_dsl_name = None
1309 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001310 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001311
1312 def __iter__(self):
1313 return self
1314
1315 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001316 while True:
1317 if not self.input:
1318 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001319
Larry Hastingsbebf7352014-01-17 17:47:17 -08001320 if self.dsl_name:
1321 return_value = self.parse_clinic_block(self.dsl_name)
1322 self.dsl_name = None
1323 self.first_block = False
1324 return return_value
1325 block = self.parse_verbatim_block()
1326 if self.first_block and not block.input:
1327 continue
1328 self.first_block = False
1329 return block
1330
Larry Hastings31826802013-10-19 00:09:25 -07001331
1332 def is_start_line(self, line):
1333 match = self.start_re.match(line.lstrip())
1334 return match.group(1) if match else None
1335
Larry Hastingse1b82532014-07-27 16:22:20 +02001336 def _line(self, lookahead=False):
Larry Hastings31826802013-10-19 00:09:25 -07001337 self.line_number += 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001338 line = self.input.pop()
Larry Hastingse1b82532014-07-27 16:22:20 +02001339 if not lookahead:
1340 self.language.parse_line(line)
Larry Hastings7726ac92014-01-31 22:03:12 -08001341 return line
Larry Hastings31826802013-10-19 00:09:25 -07001342
1343 def parse_verbatim_block(self):
1344 add, output = text_accumulator()
1345 self.block_start_line_number = self.line_number
1346
1347 while self.input:
1348 line = self._line()
1349 dsl_name = self.is_start_line(line)
1350 if dsl_name:
1351 self.dsl_name = dsl_name
1352 break
1353 add(line)
1354
1355 return Block(output())
1356
1357 def parse_clinic_block(self, dsl_name):
1358 input_add, input_output = text_accumulator()
1359 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001360 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001361 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1362
Larry Hastings90261132014-01-07 12:21:08 -08001363 def is_stop_line(line):
1364 # make sure to recognize stop line even if it
1365 # doesn't end with EOL (it could be the very end of the file)
1366 if not line.startswith(stop_line):
1367 return False
1368 remainder = line[len(stop_line):]
1369 return (not remainder) or remainder.isspace()
1370
Larry Hastings31826802013-10-19 00:09:25 -07001371 # consume body of program
1372 while self.input:
1373 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001374 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001375 break
1376 if body_prefix:
1377 line = line.lstrip()
1378 assert line.startswith(body_prefix)
1379 line = line[len(body_prefix):]
1380 input_add(line)
1381
1382 # consume output and checksum line, if present.
1383 if self.last_dsl_name == dsl_name:
1384 checksum_re = self.last_checksum_re
1385 else:
Larry Hastings581ee362014-01-28 05:00:08 -08001386 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, arguments='{arguments}').partition('{arguments}')
1387 assert _ == '{arguments}'
1388 checksum_re = create_regex(before, after, word=False)
Larry Hastings31826802013-10-19 00:09:25 -07001389 self.last_dsl_name = dsl_name
1390 self.last_checksum_re = checksum_re
1391
1392 # scan forward for checksum line
1393 output_add, output_output = text_accumulator()
Larry Hastings581ee362014-01-28 05:00:08 -08001394 arguments = None
Larry Hastings31826802013-10-19 00:09:25 -07001395 while self.input:
Larry Hastingse1b82532014-07-27 16:22:20 +02001396 line = self._line(lookahead=True)
Larry Hastings31826802013-10-19 00:09:25 -07001397 match = checksum_re.match(line.lstrip())
Larry Hastings581ee362014-01-28 05:00:08 -08001398 arguments = match.group(1) if match else None
1399 if arguments:
Larry Hastings31826802013-10-19 00:09:25 -07001400 break
1401 output_add(line)
1402 if self.is_start_line(line):
1403 break
1404
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001405 output = output_output()
Larry Hastings581ee362014-01-28 05:00:08 -08001406 if arguments:
1407 d = {}
1408 for field in shlex.split(arguments):
1409 name, equals, value = field.partition('=')
1410 if not equals:
1411 fail("Mangled Argument Clinic marker line: {!r}".format(line))
1412 d[name.strip()] = value.strip()
1413
Larry Hastings31826802013-10-19 00:09:25 -07001414 if self.verify:
Larry Hastings581ee362014-01-28 05:00:08 -08001415 if 'input' in d:
1416 checksum = d['output']
1417 input_checksum = d['input']
1418 else:
1419 checksum = d['checksum']
1420 input_checksum = None
1421
1422 computed = compute_checksum(output, len(checksum))
Larry Hastings31826802013-10-19 00:09:25 -07001423 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001424 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1425 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001426 "the end marker,\n"
1427 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001428 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001429 else:
1430 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001431 output_lines = output.splitlines(keepends=True)
1432 self.line_number -= len(output_lines)
1433 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001434 output = None
1435
1436 return Block(input_output(), dsl_name, output=output)
1437
1438
1439class BlockPrinter:
1440
1441 def __init__(self, language, f=None):
1442 self.language = language
1443 self.f = f or io.StringIO()
1444
1445 def print_block(self, block):
1446 input = block.input
1447 output = block.output
1448 dsl_name = block.dsl_name
1449 write = self.f.write
1450
Larry Hastings31826802013-10-19 00:09:25 -07001451 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1452
1453 if not dsl_name:
1454 write(input)
1455 return
1456
1457 write(self.language.start_line.format(dsl_name=dsl_name))
1458 write("\n")
1459
1460 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1461 if not body_prefix:
1462 write(input)
1463 else:
1464 for line in input.split('\n'):
1465 write(body_prefix)
1466 write(line)
1467 write("\n")
1468
1469 write(self.language.stop_line.format(dsl_name=dsl_name))
1470 write("\n")
1471
Larry Hastings581ee362014-01-28 05:00:08 -08001472 input = ''.join(block.input)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001473 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001474 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001475 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001476 output += '\n'
1477 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001478
Larry Hastings581ee362014-01-28 05:00:08 -08001479 arguments="output={} input={}".format(compute_checksum(output, 16), compute_checksum(input, 16))
1480 write(self.language.checksum_line.format(dsl_name=dsl_name, arguments=arguments))
Larry Hastings31826802013-10-19 00:09:25 -07001481 write("\n")
1482
Larry Hastingsbebf7352014-01-17 17:47:17 -08001483 def write(self, text):
1484 self.f.write(text)
1485
1486
Larry Hastings0759f842015-04-03 13:09:02 -07001487class BufferSeries:
1488 """
1489 Behaves like a "defaultlist".
1490 When you ask for an index that doesn't exist yet,
1491 the object grows the list until that item exists.
1492 So o[n] will always work.
1493
1494 Supports negative indices for actual items.
1495 e.g. o[-1] is an element immediately preceding o[0].
1496 """
1497
1498 def __init__(self):
1499 self._start = 0
1500 self._array = []
1501 self._constructor = _text_accumulator
1502
1503 def __getitem__(self, i):
1504 i -= self._start
1505 if i < 0:
1506 self._start += i
1507 prefix = [self._constructor() for x in range(-i)]
1508 self._array = prefix + self._array
1509 i = 0
1510 while i >= len(self._array):
1511 self._array.append(self._constructor())
1512 return self._array[i]
1513
1514 def clear(self):
1515 for ta in self._array:
1516 ta._text.clear()
1517
1518 def dump(self):
1519 texts = [ta.output() for ta in self._array]
1520 return "".join(texts)
1521
1522
Larry Hastingsbebf7352014-01-17 17:47:17 -08001523class Destination:
1524 def __init__(self, name, type, clinic, *args):
1525 self.name = name
1526 self.type = type
1527 self.clinic = clinic
Larry Hastings0759f842015-04-03 13:09:02 -07001528 valid_types = ('buffer', 'file', 'suppress')
Larry Hastingsbebf7352014-01-17 17:47:17 -08001529 if type not in valid_types:
1530 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1531 extra_arguments = 1 if type == "file" else 0
1532 if len(args) < extra_arguments:
1533 fail("Not enough arguments for destination " + name + " new " + type)
1534 if len(args) > extra_arguments:
1535 fail("Too many arguments for destination " + name + " new " + type)
1536 if type =='file':
1537 d = {}
Larry Hastingsc2047262014-01-25 20:43:29 -08001538 filename = clinic.filename
1539 d['path'] = filename
1540 dirname, basename = os.path.split(filename)
1541 if not dirname:
1542 dirname = '.'
1543 d['dirname'] = dirname
1544 d['basename'] = basename
1545 d['basename_root'], d['basename_extension'] = os.path.splitext(filename)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001546 self.filename = args[0].format_map(d)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001547
Larry Hastings0759f842015-04-03 13:09:02 -07001548 self.buffers = BufferSeries()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001549
1550 def __repr__(self):
1551 if self.type == 'file':
1552 file_repr = " " + repr(self.filename)
1553 else:
1554 file_repr = ''
1555 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1556
1557 def clear(self):
1558 if self.type != 'buffer':
1559 fail("Can't clear destination" + self.name + " , it's not of type buffer")
Larry Hastings0759f842015-04-03 13:09:02 -07001560 self.buffers.clear()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001561
1562 def dump(self):
Larry Hastings0759f842015-04-03 13:09:02 -07001563 return self.buffers.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001564
Larry Hastings31826802013-10-19 00:09:25 -07001565
1566# maps strings to Language objects.
1567# "languages" maps the name of the language ("C", "Python").
1568# "extensions" maps the file extension ("c", "py").
1569languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001570extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1571extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001572
1573
1574# maps strings to callables.
1575# these callables must be of the form:
1576# def foo(name, default, *, ...)
1577# The callable may have any number of keyword-only parameters.
1578# The callable must return a CConverter object.
1579# The callable should not call builtins.print.
1580converters = {}
1581
1582# maps strings to callables.
1583# these callables follow the same rules as those for "converters" above.
1584# note however that they will never be called with keyword-only parameters.
1585legacy_converters = {}
1586
1587
1588# maps strings to callables.
1589# these callables must be of the form:
1590# def foo(*, ...)
1591# The callable may have any number of keyword-only parameters.
1592# The callable must return a CConverter object.
1593# The callable should not call builtins.print.
1594return_converters = {}
1595
Larry Hastings7726ac92014-01-31 22:03:12 -08001596clinic = None
Larry Hastings31826802013-10-19 00:09:25 -07001597class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001598
1599 presets_text = """
Larry Hastings7726ac92014-01-31 22:03:12 -08001600preset block
1601everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001602methoddef_ifndef buffer 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001603docstring_prototype suppress
1604parser_prototype suppress
1605cpp_if suppress
1606cpp_endif suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001607
Larry Hastingsbebf7352014-01-17 17:47:17 -08001608preset original
1609everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001610methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001611docstring_prototype suppress
1612parser_prototype suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001613cpp_if suppress
1614cpp_endif suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001615
1616preset file
1617everything file
Larry Hastings0759f842015-04-03 13:09:02 -07001618methoddef_ifndef file 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001619docstring_prototype suppress
1620parser_prototype suppress
1621impl_definition block
1622
1623preset buffer
1624everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001625methoddef_ifndef buffer 1
1626impl_definition block
Larry Hastingsbebf7352014-01-17 17:47:17 -08001627docstring_prototype suppress
1628impl_prototype suppress
1629parser_prototype suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001630
1631preset partial-buffer
1632everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001633methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001634docstring_prototype block
1635impl_prototype suppress
1636methoddef_define block
1637parser_prototype block
1638impl_definition block
1639
Larry Hastingsbebf7352014-01-17 17:47:17 -08001640"""
1641
Larry Hastings581ee362014-01-28 05:00:08 -08001642 def __init__(self, language, printer=None, *, force=False, verify=True, filename=None):
Larry Hastings31826802013-10-19 00:09:25 -07001643 # maps strings to Parser objects.
1644 # (instantiated from the "parsers" global.)
1645 self.parsers = {}
1646 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001647 if printer:
1648 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001649 self.printer = printer or BlockPrinter(language)
1650 self.verify = verify
Larry Hastings581ee362014-01-28 05:00:08 -08001651 self.force = force
Larry Hastings31826802013-10-19 00:09:25 -07001652 self.filename = filename
1653 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001654 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001655 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001656
Larry Hastingsbebf7352014-01-17 17:47:17 -08001657 self.line_prefix = self.line_suffix = ''
1658
1659 self.destinations = {}
1660 self.add_destination("block", "buffer")
1661 self.add_destination("suppress", "suppress")
1662 self.add_destination("buffer", "buffer")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001663 if filename:
Larry Hastingsc2047262014-01-25 20:43:29 -08001664 self.add_destination("file", "file", "{dirname}/clinic/{basename}.h")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001665
Larry Hastings0759f842015-04-03 13:09:02 -07001666 d = self.get_destination_buffer
1667 self.destination_buffers = collections.OrderedDict((
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001668 ('cpp_if', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001669 ('docstring_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001670 ('docstring_definition', d('file')),
1671 ('methoddef_define', d('file')),
1672 ('impl_prototype', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001673 ('parser_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001674 ('parser_definition', d('file')),
1675 ('cpp_endif', d('file')),
1676 ('methoddef_ifndef', d('file', 1)),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001677 ('impl_definition', d('block')),
1678 ))
1679
Larry Hastings0759f842015-04-03 13:09:02 -07001680 self.destination_buffers_stack = []
1681 self.ifndef_symbols = set()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001682
1683 self.presets = {}
1684 preset = None
1685 for line in self.presets_text.strip().split('\n'):
1686 line = line.strip()
1687 if not line:
1688 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001689 name, value, *options = line.split()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001690 if name == 'preset':
1691 self.presets[value] = preset = collections.OrderedDict()
1692 continue
1693
Larry Hastings0759f842015-04-03 13:09:02 -07001694 if len(options):
1695 index = int(options[0])
1696 else:
1697 index = 0
1698 buffer = self.get_destination_buffer(value, index)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001699
1700 if name == 'everything':
Larry Hastings0759f842015-04-03 13:09:02 -07001701 for name in self.destination_buffers:
1702 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001703 continue
1704
Larry Hastings0759f842015-04-03 13:09:02 -07001705 assert name in self.destination_buffers
1706 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001707
Larry Hastings31826802013-10-19 00:09:25 -07001708 global clinic
1709 clinic = self
1710
Larry Hastingsbebf7352014-01-17 17:47:17 -08001711 def add_destination(self, name, type, *args):
1712 if name in self.destinations:
1713 fail("Destination already exists: " + repr(name))
1714 self.destinations[name] = Destination(name, type, self, *args)
1715
Larry Hastings0759f842015-04-03 13:09:02 -07001716 def get_destination(self, name):
1717 d = self.destinations.get(name)
1718 if not d:
1719 fail("Destination does not exist: " + repr(name))
1720 return d
1721
1722 def get_destination_buffer(self, name, item=0):
1723 d = self.get_destination(name)
1724 return d.buffers[item]
1725
Larry Hastings31826802013-10-19 00:09:25 -07001726 def parse(self, input):
1727 printer = self.printer
1728 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1729 for block in self.block_parser:
1730 dsl_name = block.dsl_name
1731 if dsl_name:
1732 if dsl_name not in self.parsers:
1733 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1734 self.parsers[dsl_name] = parsers[dsl_name](self)
1735 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001736 try:
1737 parser.parse(block)
1738 except Exception:
1739 fail('Exception raised during parsing:\n' +
1740 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001741 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001742
1743 second_pass_replacements = {}
1744
Larry Hastings0759f842015-04-03 13:09:02 -07001745 # these are destinations not buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08001746 for name, destination in self.destinations.items():
1747 if destination.type == 'suppress':
1748 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001749 output = destination.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001750
1751 if output:
1752
1753 block = Block("", dsl_name="clinic", output=output)
1754
1755 if destination.type == 'buffer':
1756 block.input = "dump " + name + "\n"
1757 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1758 printer.write("\n")
1759 printer.print_block(block)
1760 continue
1761
1762 if destination.type == 'file':
1763 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08001764 dirname = os.path.dirname(destination.filename)
1765 try:
1766 os.makedirs(dirname)
1767 except FileExistsError:
1768 if not os.path.isdir(dirname):
1769 fail("Can't write to destination {}, "
1770 "can't make directory {}!".format(
1771 destination.filename, dirname))
Larry Hastings581ee362014-01-28 05:00:08 -08001772 if self.verify:
1773 with open(destination.filename, "rt") as f:
1774 parser_2 = BlockParser(f.read(), language=self.language)
1775 blocks = list(parser_2)
1776 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1777 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001778 except FileNotFoundError:
1779 pass
1780
1781 block.input = 'preserve\n'
1782 printer_2 = BlockPrinter(self.language)
1783 printer_2.print_block(block)
1784 with open(destination.filename, "wt") as f:
1785 f.write(printer_2.f.getvalue())
1786 continue
1787 text = printer.f.getvalue()
1788
1789 if second_pass_replacements:
1790 printer_2 = BlockPrinter(self.language)
1791 parser_2 = BlockParser(text, self.language)
1792 changed = False
1793 for block in parser_2:
1794 if block.dsl_name:
1795 for id, replacement in second_pass_replacements.items():
1796 if id in block.output:
1797 changed = True
1798 block.output = block.output.replace(id, replacement)
1799 printer_2.print_block(block)
1800 if changed:
1801 text = printer_2.f.getvalue()
1802
1803 return text
1804
Larry Hastings31826802013-10-19 00:09:25 -07001805
1806 def _module_and_class(self, fields):
1807 """
1808 fields should be an iterable of field names.
1809 returns a tuple of (module, class).
1810 the module object could actually be self (a clinic object).
1811 this function is only ever used to find the parent of where
1812 a new class/module should go.
1813 """
1814 in_classes = False
1815 parent = module = self
1816 cls = None
1817 so_far = []
1818
1819 for field in fields:
1820 so_far.append(field)
1821 if not in_classes:
1822 child = parent.modules.get(field)
1823 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001824 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001825 continue
1826 in_classes = True
1827 if not hasattr(parent, 'classes'):
1828 return module, cls
1829 child = parent.classes.get(field)
1830 if not child:
1831 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1832 cls = parent = child
1833
1834 return module, cls
1835
1836
Larry Hastings581ee362014-01-28 05:00:08 -08001837def parse_file(filename, *, force=False, verify=True, output=None, encoding='utf-8'):
Larry Hastings31826802013-10-19 00:09:25 -07001838 extension = os.path.splitext(filename)[1][1:]
1839 if not extension:
1840 fail("Can't extract file type for file " + repr(filename))
1841
1842 try:
Larry Hastings7726ac92014-01-31 22:03:12 -08001843 language = extensions[extension](filename)
Larry Hastings31826802013-10-19 00:09:25 -07001844 except KeyError:
1845 fail("Can't identify file type for file " + repr(filename))
1846
Larry Hastings31826802013-10-19 00:09:25 -07001847 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001848 raw = f.read()
1849
Larry Hastings2623c8c2014-02-08 22:15:29 -08001850 # exit quickly if there are no clinic markers in the file
1851 find_start_re = BlockParser("", language).find_start_re
1852 if not find_start_re.search(raw):
1853 return
1854
1855 clinic = Clinic(language, force=force, verify=verify, filename=filename)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001856 cooked = clinic.parse(raw)
Larry Hastings581ee362014-01-28 05:00:08 -08001857 if (cooked == raw) and not force:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001858 return
Larry Hastings31826802013-10-19 00:09:25 -07001859
1860 directory = os.path.dirname(filename) or '.'
1861
1862 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001863 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001864 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1865 with open(tmpfilename, "wb") as f:
1866 f.write(bytes)
1867 os.replace(tmpfilename, output or filename)
1868
1869
Larry Hastings581ee362014-01-28 05:00:08 -08001870def compute_checksum(input, length=None):
Larry Hastings31826802013-10-19 00:09:25 -07001871 input = input or ''
Larry Hastings581ee362014-01-28 05:00:08 -08001872 s = hashlib.sha1(input.encode('utf-8')).hexdigest()
1873 if length:
1874 s = s[:length]
1875 return s
Larry Hastings31826802013-10-19 00:09:25 -07001876
1877
1878
1879
1880class PythonParser:
1881 def __init__(self, clinic):
1882 pass
1883
1884 def parse(self, block):
1885 s = io.StringIO()
1886 with OverrideStdioWith(s):
1887 exec(block.input)
1888 block.output = s.getvalue()
1889
1890
1891class Module:
1892 def __init__(self, name, module=None):
1893 self.name = name
1894 self.module = self.parent = module
1895
1896 self.modules = collections.OrderedDict()
1897 self.classes = collections.OrderedDict()
1898 self.functions = []
1899
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001900 def __repr__(self):
1901 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1902
Larry Hastings31826802013-10-19 00:09:25 -07001903class Class:
Larry Hastingsc2047262014-01-25 20:43:29 -08001904 def __init__(self, name, module=None, cls=None, typedef=None, type_object=None):
Larry Hastings31826802013-10-19 00:09:25 -07001905 self.name = name
1906 self.module = module
1907 self.cls = cls
Larry Hastingsc2047262014-01-25 20:43:29 -08001908 self.typedef = typedef
1909 self.type_object = type_object
Larry Hastings31826802013-10-19 00:09:25 -07001910 self.parent = cls or module
1911
1912 self.classes = collections.OrderedDict()
1913 self.functions = []
1914
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001915 def __repr__(self):
1916 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1917
Larry Hastings8666e652014-01-12 14:12:59 -08001918unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001919
Larry Hastings8666e652014-01-12 14:12:59 -08001920__abs__
1921__add__
1922__and__
1923__bytes__
1924__call__
1925__complex__
1926__delitem__
1927__divmod__
1928__eq__
1929__float__
1930__floordiv__
1931__ge__
1932__getattr__
1933__getattribute__
1934__getitem__
1935__gt__
1936__hash__
1937__iadd__
1938__iand__
Larry Hastings8666e652014-01-12 14:12:59 -08001939__ifloordiv__
1940__ilshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001941__imatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001942__imod__
1943__imul__
1944__index__
1945__int__
1946__invert__
1947__ior__
1948__ipow__
1949__irshift__
1950__isub__
1951__iter__
1952__itruediv__
1953__ixor__
1954__le__
1955__len__
1956__lshift__
1957__lt__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001958__matmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001959__mod__
1960__mul__
1961__neg__
1962__new__
1963__next__
1964__or__
1965__pos__
1966__pow__
1967__radd__
1968__rand__
1969__rdivmod__
1970__repr__
1971__rfloordiv__
1972__rlshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001973__rmatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001974__rmod__
1975__rmul__
1976__ror__
1977__round__
1978__rpow__
1979__rrshift__
1980__rshift__
1981__rsub__
1982__rtruediv__
1983__rxor__
1984__setattr__
1985__setitem__
1986__str__
1987__sub__
1988__truediv__
1989__xor__
1990
1991""".strip().split())
1992
1993
Larry Hastings5c661892014-01-24 06:17:25 -08001994INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
1995INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
1996""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07001997
1998class Function:
1999 """
2000 Mutable duck type for inspect.Function.
2001
2002 docstring - a str containing
2003 * embedded line breaks
2004 * text outdented to the left margin
2005 * no trailing whitespace.
2006 It will always be true that
2007 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
2008 """
2009
2010 def __init__(self, parameters=None, *, name,
2011 module, cls=None, c_basename=None,
2012 full_name=None,
2013 return_converter, return_annotation=_empty,
Larry Hastings581ee362014-01-28 05:00:08 -08002014 docstring=None, kind=CALLABLE, coexist=False,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002015 docstring_only=False):
Larry Hastings31826802013-10-19 00:09:25 -07002016 self.parameters = parameters or collections.OrderedDict()
2017 self.return_annotation = return_annotation
2018 self.name = name
2019 self.full_name = full_name
2020 self.module = module
2021 self.cls = cls
2022 self.parent = cls or module
2023 self.c_basename = c_basename
2024 self.return_converter = return_converter
2025 self.docstring = docstring or ''
2026 self.kind = kind
2027 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08002028 self.self_converter = None
Larry Hastings2623c8c2014-02-08 22:15:29 -08002029 # docstring_only means "don't generate a machine-readable
2030 # signature, just a normal docstring". it's True for
2031 # functions with optional groups because we can't represent
2032 # those accurately with inspect.Signature in 3.4.
2033 self.docstring_only = docstring_only
Larry Hastingsebdcb502013-11-23 14:54:00 -08002034
Larry Hastings7726ac92014-01-31 22:03:12 -08002035 self.rendered_parameters = None
2036
2037 __render_parameters__ = None
2038 @property
2039 def render_parameters(self):
2040 if not self.__render_parameters__:
2041 self.__render_parameters__ = l = []
2042 for p in self.parameters.values():
2043 p = p.copy()
2044 p.converter.pre_render()
2045 l.append(p)
2046 return self.__render_parameters__
2047
Larry Hastingsebdcb502013-11-23 14:54:00 -08002048 @property
2049 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08002050 if self.kind in (METHOD_INIT, METHOD_NEW):
2051 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002052 flags = []
2053 if self.kind == CLASS_METHOD:
2054 flags.append('METH_CLASS')
2055 elif self.kind == STATIC_METHOD:
2056 flags.append('METH_STATIC')
2057 else:
2058 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
2059 if self.coexist:
2060 flags.append('METH_COEXIST')
2061 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07002062
2063 def __repr__(self):
2064 return '<clinic.Function ' + self.name + '>'
2065
Larry Hastings7726ac92014-01-31 22:03:12 -08002066 def copy(self, **overrides):
2067 kwargs = {
2068 'name': self.name, 'module': self.module, 'parameters': self.parameters,
2069 'cls': self.cls, 'c_basename': self.c_basename,
2070 'full_name': self.full_name,
2071 'return_converter': self.return_converter, 'return_annotation': self.return_annotation,
2072 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002073 'docstring_only': self.docstring_only,
Larry Hastings7726ac92014-01-31 22:03:12 -08002074 }
2075 kwargs.update(overrides)
2076 f = Function(**kwargs)
2077
2078 parameters = collections.OrderedDict()
2079 for name, value in f.parameters.items():
2080 value = value.copy(function=f)
2081 parameters[name] = value
2082 f.parameters = parameters
2083 return f
2084
Larry Hastings31826802013-10-19 00:09:25 -07002085
2086class Parameter:
2087 """
2088 Mutable duck type of inspect.Parameter.
2089 """
2090
2091 def __init__(self, name, kind, *, default=_empty,
2092 function, converter, annotation=_empty,
2093 docstring=None, group=0):
2094 self.name = name
2095 self.kind = kind
2096 self.default = default
2097 self.function = function
2098 self.converter = converter
2099 self.annotation = annotation
2100 self.docstring = docstring or ''
2101 self.group = group
2102
2103 def __repr__(self):
2104 return '<clinic.Parameter ' + self.name + '>'
2105
2106 def is_keyword_only(self):
2107 return self.kind == inspect.Parameter.KEYWORD_ONLY
2108
Larry Hastings2623c8c2014-02-08 22:15:29 -08002109 def is_positional_only(self):
2110 return self.kind == inspect.Parameter.POSITIONAL_ONLY
2111
Larry Hastings7726ac92014-01-31 22:03:12 -08002112 def copy(self, **overrides):
2113 kwargs = {
2114 'name': self.name, 'kind': self.kind, 'default':self.default,
2115 'function': self.function, 'converter': self.converter, 'annotation': self.annotation,
2116 'docstring': self.docstring, 'group': self.group,
2117 }
2118 kwargs.update(overrides)
2119 if 'converter' not in overrides:
2120 converter = copy.copy(self.converter)
2121 converter.function = kwargs['function']
2122 kwargs['converter'] = converter
2123 return Parameter(**kwargs)
2124
2125
2126
2127class LandMine:
2128 # try to access any
2129 def __init__(self, message):
2130 self.__message__ = message
2131
2132 def __repr__(self):
2133 return '<LandMine ' + repr(self.__message__) + ">"
2134
2135 def __getattribute__(self, name):
2136 if name in ('__repr__', '__message__'):
2137 return super().__getattribute__(name)
2138 # raise RuntimeError(repr(name))
2139 fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__)
Larry Hastings31826802013-10-19 00:09:25 -07002140
Larry Hastings31826802013-10-19 00:09:25 -07002141
2142def add_c_converter(f, name=None):
2143 if not name:
2144 name = f.__name__
2145 if not name.endswith('_converter'):
2146 return f
2147 name = name[:-len('_converter')]
2148 converters[name] = f
2149 return f
2150
2151def add_default_legacy_c_converter(cls):
2152 # automatically add converter for default format unit
2153 # (but without stomping on the existing one if it's already
2154 # set, in case you subclass)
Larry Hastingsf1503782014-06-11 04:31:29 -07002155 if ((cls.format_unit not in ('O&', '')) and
Larry Hastings31826802013-10-19 00:09:25 -07002156 (cls.format_unit not in legacy_converters)):
2157 legacy_converters[cls.format_unit] = cls
2158 return cls
2159
2160def add_legacy_c_converter(format_unit, **kwargs):
2161 """
2162 Adds a legacy converter.
2163 """
2164 def closure(f):
2165 if not kwargs:
2166 added_f = f
2167 else:
2168 added_f = functools.partial(f, **kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002169 if format_unit:
2170 legacy_converters[format_unit] = added_f
Larry Hastings31826802013-10-19 00:09:25 -07002171 return f
2172 return closure
2173
2174class CConverterAutoRegister(type):
2175 def __init__(cls, name, bases, classdict):
2176 add_c_converter(cls)
2177 add_default_legacy_c_converter(cls)
2178
2179class CConverter(metaclass=CConverterAutoRegister):
2180 """
2181 For the init function, self, name, function, and default
2182 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08002183 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07002184 """
2185
Larry Hastings7726ac92014-01-31 22:03:12 -08002186 # The C name to use for this variable.
2187 name = None
2188
2189 # The Python name to use for this variable.
2190 py_name = None
2191
Larry Hastings78cf85c2014-01-04 12:44:57 -08002192 # The C type to use for this variable.
2193 # 'type' should be a Python string specifying the type, e.g. "int".
2194 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002195 type = None
Larry Hastings31826802013-10-19 00:09:25 -07002196
2197 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08002198 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08002199 # Or the magic value "unknown" if this value is a cannot be evaluated
2200 # at Argument-Clinic-preprocessing time (but is presumed to be valid
2201 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07002202 default = unspecified
2203
Larry Hastings4a55fc52014-01-12 11:09:57 -08002204 # If not None, default must be isinstance() of this type.
2205 # (You can also specify a tuple of types.)
2206 default_type = None
2207
Larry Hastings31826802013-10-19 00:09:25 -07002208 # "default" converted into a C value, as a string.
2209 # Or None if there is no default.
2210 c_default = None
2211
Larry Hastings2a727912014-01-16 11:32:01 -08002212 # "default" converted into a Python value, as a string.
2213 # Or None if there is no default.
2214 py_default = None
2215
Larry Hastingsabc716b2013-11-20 09:13:52 -08002216 # The default value used to initialize the C variable when
2217 # there is no default, but not specifying a default may
2218 # result in an "uninitialized variable" warning. This can
2219 # easily happen when using option groups--although
2220 # properly-written code won't actually use the variable,
2221 # the variable does get passed in to the _impl. (Ah, if
2222 # only dataflow analysis could inline the static function!)
2223 #
2224 # This value is specified as a string.
2225 # Every non-abstract subclass should supply a valid value.
2226 c_ignored_default = 'NULL'
2227
Larry Hastings31826802013-10-19 00:09:25 -07002228 # The C converter *function* to be used, if any.
2229 # (If this is not None, format_unit must be 'O&'.)
2230 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002231
Larry Hastings78cf85c2014-01-04 12:44:57 -08002232 # Should Argument Clinic add a '&' before the name of
2233 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07002234 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08002235
2236 # Should Argument Clinic add a '&' before the name of
2237 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07002238 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08002239
2240 #############################################################
2241 #############################################################
2242 ## You shouldn't need to read anything below this point to ##
2243 ## write your own converter functions. ##
2244 #############################################################
2245 #############################################################
2246
2247 # The "format unit" to specify for this variable when
2248 # parsing arguments using PyArg_ParseTuple (AndKeywords).
2249 # Custom converters should always use the default value of 'O&'.
2250 format_unit = 'O&'
2251
2252 # What encoding do we want for this variable? Only used
2253 # by format units starting with 'e'.
2254 encoding = None
2255
Larry Hastings77561cc2014-01-07 12:13:13 -08002256 # Should this object be required to be a subclass of a specific type?
2257 # If not None, should be a string representing a pointer to a
2258 # PyTypeObject (e.g. "&PyUnicode_Type").
2259 # Only used by the 'O!' format unit (and the "object" converter).
2260 subclass_of = None
2261
Larry Hastings78cf85c2014-01-04 12:44:57 -08002262 # Do we want an adjacent '_length' variable for this variable?
2263 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07002264 length = False
2265
Larry Hastings5c661892014-01-24 06:17:25 -08002266 # Should we show this parameter in the generated
2267 # __text_signature__? This is *almost* always True.
Larry Hastingsc2047262014-01-25 20:43:29 -08002268 # (It's only False for __new__, __init__, and METH_STATIC functions.)
Larry Hastings5c661892014-01-24 06:17:25 -08002269 show_in_signature = True
2270
2271 # Overrides the name used in a text signature.
2272 # The name used for a "self" parameter must be one of
2273 # self, type, or module; however users can set their own.
2274 # This lets the self_converter overrule the user-settable
2275 # name, *just* for the text signature.
2276 # Only set by self_converter.
2277 signature_name = None
2278
2279 # keep in sync with self_converter.__init__!
Larry Hastings7726ac92014-01-31 22:03:12 -08002280 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 -07002281 self.name = name
Larry Hastings7726ac92014-01-31 22:03:12 -08002282 self.py_name = py_name
Larry Hastings31826802013-10-19 00:09:25 -07002283
2284 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08002285 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002286 if isinstance(self.default_type, type):
2287 types_str = self.default_type.__name__
2288 else:
2289 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2290 fail("{}: default value {!r} for field {} is not of type {}".format(
2291 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002292 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002293
Larry Hastingsb4705752014-01-18 21:54:15 -08002294 if c_default:
2295 self.c_default = c_default
2296 if py_default:
2297 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002298
Larry Hastings31826802013-10-19 00:09:25 -07002299 if annotation != unspecified:
2300 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings7726ac92014-01-31 22:03:12 -08002301
2302 # this is deliberate, to prevent you from caching information
2303 # about the function in the init.
2304 # (that breaks if we get cloned.)
2305 # so after this change we will noisily fail.
2306 self.function = LandMine("Don't access members of self.function inside converter_init!")
Larry Hastings31826802013-10-19 00:09:25 -07002307 self.converter_init(**kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002308 self.function = function
Larry Hastings31826802013-10-19 00:09:25 -07002309
2310 def converter_init(self):
2311 pass
2312
2313 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002314 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002315
Larry Hastings5c661892014-01-24 06:17:25 -08002316 def _render_self(self, parameter, data):
2317 self.parameter = parameter
2318 original_name = self.name
2319 name = ensure_legal_c_identifier(original_name)
2320
2321 # impl_arguments
2322 s = ("&" if self.impl_by_reference else "") + name
2323 data.impl_arguments.append(s)
2324 if self.length:
2325 data.impl_arguments.append(self.length_name())
2326
2327 # impl_parameters
2328 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2329 if self.length:
2330 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2331
2332 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002333 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002334 original_name = self.name
2335 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002336
2337 # declarations
2338 d = self.declaration()
2339 data.declarations.append(d)
2340
2341 # initializers
2342 initializers = self.initialize()
2343 if initializers:
2344 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2345
Larry Hastingsc2047262014-01-25 20:43:29 -08002346 # modifications
2347 modifications = self.modify()
2348 if modifications:
2349 data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2350
Larry Hastings31826802013-10-19 00:09:25 -07002351 # keywords
Larry Hastings7726ac92014-01-31 22:03:12 -08002352 data.keywords.append(parameter.name)
Larry Hastings31826802013-10-19 00:09:25 -07002353
2354 # format_units
2355 if self.is_optional() and '|' not in data.format_units:
2356 data.format_units.append('|')
2357 if parameter.is_keyword_only() and '$' not in data.format_units:
2358 data.format_units.append('$')
2359 data.format_units.append(self.format_unit)
2360
2361 # parse_arguments
2362 self.parse_argument(data.parse_arguments)
2363
Larry Hastings31826802013-10-19 00:09:25 -07002364 # cleanup
2365 cleanup = self.cleanup()
2366 if cleanup:
2367 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2368
Larry Hastings5c661892014-01-24 06:17:25 -08002369 def render(self, parameter, data):
2370 """
2371 parameter is a clinic.Parameter instance.
2372 data is a CRenderData instance.
2373 """
2374 self._render_self(parameter, data)
2375 self._render_non_self(parameter, data)
2376
Larry Hastingsebdcb502013-11-23 14:54:00 -08002377 def length_name(self):
2378 """Computes the name of the associated "length" variable."""
2379 if not self.length:
2380 return None
2381 return ensure_legal_c_identifier(self.name) + "_length"
2382
Larry Hastings31826802013-10-19 00:09:25 -07002383 # Why is this one broken out separately?
2384 # For "positional-only" function parsing,
2385 # which generates a bunch of PyArg_ParseTuple calls.
2386 def parse_argument(self, list):
2387 assert not (self.converter and self.encoding)
2388 if self.format_unit == 'O&':
2389 assert self.converter
2390 list.append(self.converter)
2391
2392 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002393 list.append(c_repr(self.encoding))
2394 elif self.subclass_of:
2395 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002396
Larry Hastingsebdcb502013-11-23 14:54:00 -08002397 legal_name = ensure_legal_c_identifier(self.name)
2398 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002399 list.append(s)
2400
Larry Hastingsebdcb502013-11-23 14:54:00 -08002401 if self.length:
2402 list.append("&" + self.length_name())
2403
Larry Hastings31826802013-10-19 00:09:25 -07002404 #
2405 # All the functions after here are intended as extension points.
2406 #
2407
2408 def simple_declaration(self, by_reference=False):
2409 """
2410 Computes the basic declaration of the variable.
2411 Used in computing the prototype declaration and the
2412 variable declaration.
2413 """
2414 prototype = [self.type]
2415 if by_reference or not self.type.endswith('*'):
2416 prototype.append(" ")
2417 if by_reference:
2418 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002419 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002420 return "".join(prototype)
2421
2422 def declaration(self):
2423 """
2424 The C statement to declare this variable.
2425 """
2426 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002427 default = self.c_default
2428 if not default and self.parameter.group:
2429 default = self.c_ignored_default
2430 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002431 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002432 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002433 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002434 if self.length:
2435 declaration.append('\nPy_ssize_clean_t ')
2436 declaration.append(self.length_name())
2437 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002438 s = "".join(declaration)
2439 # double up curly-braces, this string will be used
2440 # as part of a format_map() template later
2441 s = s.replace("{", "{{")
2442 s = s.replace("}", "}}")
2443 return s
Larry Hastings31826802013-10-19 00:09:25 -07002444
2445 def initialize(self):
2446 """
2447 The C statements required to set up this variable before parsing.
2448 Returns a string containing this code indented at column 0.
2449 If no initialization is necessary, returns an empty string.
2450 """
2451 return ""
2452
Larry Hastingsc2047262014-01-25 20:43:29 -08002453 def modify(self):
2454 """
2455 The C statements required to modify this variable after parsing.
2456 Returns a string containing this code indented at column 0.
2457 If no initialization is necessary, returns an empty string.
2458 """
2459 return ""
2460
Larry Hastings31826802013-10-19 00:09:25 -07002461 def cleanup(self):
2462 """
2463 The C statements required to clean up after this variable.
2464 Returns a string containing this code indented at column 0.
2465 If no cleanup is necessary, returns an empty string.
2466 """
2467 return ""
2468
Larry Hastings7726ac92014-01-31 22:03:12 -08002469 def pre_render(self):
2470 """
2471 A second initialization function, like converter_init,
2472 called just before rendering.
2473 You are permitted to examine self.function here.
2474 """
2475 pass
2476
Larry Hastings31826802013-10-19 00:09:25 -07002477
2478class bool_converter(CConverter):
2479 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002480 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002481 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002482 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002483
2484 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002485 if self.default is not unspecified:
2486 self.default = bool(self.default)
2487 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002488
2489class char_converter(CConverter):
2490 type = 'char'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002491 default_type = (bytes, bytearray)
Larry Hastings31826802013-10-19 00:09:25 -07002492 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002493 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002494
Larry Hastings4a55fc52014-01-12 11:09:57 -08002495 def converter_init(self):
Larry Hastings7f90cba2015-04-15 23:02:12 -04002496 if isinstance(self.default, self.default_type) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002497 fail("char_converter: illegal default value " + repr(self.default))
2498
2499
Larry Hastings31826802013-10-19 00:09:25 -07002500@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002501class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002502 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002503 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002504 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002505 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002506
2507 def converter_init(self, *, bitwise=False):
2508 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002509 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002510
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002511class byte_converter(unsigned_char_converter): pass
2512
Larry Hastings31826802013-10-19 00:09:25 -07002513class short_converter(CConverter):
2514 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002515 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002516 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002517 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002518
2519class unsigned_short_converter(CConverter):
2520 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002521 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002522 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002523 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002524
2525 def converter_init(self, *, bitwise=False):
2526 if not bitwise:
2527 fail("Unsigned shorts must be bitwise (for now).")
2528
Larry Hastings7f90cba2015-04-15 23:02:12 -04002529@add_legacy_c_converter('C', types={'str'})
Larry Hastings31826802013-10-19 00:09:25 -07002530class int_converter(CConverter):
2531 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002532 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002533 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002534 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002535
Larry Hastings7f90cba2015-04-15 23:02:12 -04002536 def converter_init(self, *, types={'int'}, type=None):
2537 if types == {'str'}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002538 self.format_unit = 'C'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002539 elif types != {'int'}:
2540 fail("int_converter: illegal 'types' argument " + repr(types))
Larry Hastingsdfbeb162014-10-13 10:39:41 +01002541 if type != None:
2542 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002543
2544class unsigned_int_converter(CConverter):
2545 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002546 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002547 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002548 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002549
2550 def converter_init(self, *, bitwise=False):
2551 if not bitwise:
2552 fail("Unsigned ints must be bitwise (for now).")
2553
2554class long_converter(CConverter):
2555 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002556 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002557 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002558 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002559
2560class unsigned_long_converter(CConverter):
2561 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002562 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002563 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002564 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002565
2566 def converter_init(self, *, bitwise=False):
2567 if not bitwise:
2568 fail("Unsigned longs must be bitwise (for now).")
2569
2570class PY_LONG_LONG_converter(CConverter):
2571 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002572 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002573 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002574 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002575
2576class unsigned_PY_LONG_LONG_converter(CConverter):
2577 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002578 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002579 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002580 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002581
2582 def converter_init(self, *, bitwise=False):
2583 if not bitwise:
2584 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2585
2586class Py_ssize_t_converter(CConverter):
2587 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002588 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002589 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002590 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002591
2592
2593class float_converter(CConverter):
2594 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002595 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002596 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002597 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002598
2599class double_converter(CConverter):
2600 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002601 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002602 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002603 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002604
2605
2606class Py_complex_converter(CConverter):
2607 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002608 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002609 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002610 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002611
2612
2613class object_converter(CConverter):
2614 type = 'PyObject *'
2615 format_unit = 'O'
2616
Larry Hastings4a55fc52014-01-12 11:09:57 -08002617 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2618 if converter:
2619 if subclass_of:
2620 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2621 self.format_unit = 'O&'
2622 self.converter = converter
2623 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002624 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002625 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002626
Larry Hastings77561cc2014-01-07 12:13:13 -08002627 if type is not None:
2628 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002629
2630
Larry Hastings7f90cba2015-04-15 23:02:12 -04002631#
2632# We define three string conventions for buffer types in the 'types' argument:
2633# 'buffer' : any object supporting the buffer interface
2634# 'rwbuffer': any object supporting the buffer interface, but must be writeable
2635# 'robuffer': any object supporting the buffer interface, but must not be writeable
2636#
2637
2638@add_legacy_c_converter('s#', types={"str", "robuffer"}, length=True)
2639@add_legacy_c_converter('y', types={"robuffer"})
2640@add_legacy_c_converter('y#', types={"robuffer"}, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002641@add_legacy_c_converter('z', nullable=True)
Larry Hastings7f90cba2015-04-15 23:02:12 -04002642@add_legacy_c_converter('z#', types={"str", "robuffer"}, nullable=True, length=True)
2643# add_legacy_c_converter not supported for es, es#, et, et#
2644# because of their extra encoding argument
Larry Hastings31826802013-10-19 00:09:25 -07002645class str_converter(CConverter):
2646 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002647 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002648 format_unit = 's'
2649
Larry Hastings7f90cba2015-04-15 23:02:12 -04002650 def converter_init(self, *, encoding=None, types={"str"},
Larry Hastingsebdcb502013-11-23 14:54:00 -08002651 length=False, nullable=False, zeroes=False):
2652
Larry Hastingsebdcb502013-11-23 14:54:00 -08002653 self.length = bool(length)
Larry Hastings7f90cba2015-04-15 23:02:12 -04002654
2655 is_b_or_ba = types == {"bytes", "bytearray"}
2656 is_str = types == {"str"}
2657 is_robuffer = types == {"robuffer"}
2658 is_str_or_robuffer = types == {"str", "robuffer"}
2659
Larry Hastingsebdcb502013-11-23 14:54:00 -08002660 format_unit = None
2661
2662 if encoding:
2663 self.encoding = encoding
2664
Larry Hastings7f90cba2015-04-15 23:02:12 -04002665 if is_str and not length and not zeroes and not nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002666 format_unit = 'es'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002667 elif is_str and length and zeroes and nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002668 format_unit = 'es#'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002669 elif is_b_or_ba and not length and not zeroes and not nullable:
2670 format_unit = 'et'
2671 elif is_b_or_ba and length and zeroes and nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002672 format_unit = 'et#'
2673
Larry Hastingsebdcb502013-11-23 14:54:00 -08002674 else:
2675 if zeroes:
2676 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
2677
Larry Hastings7f90cba2015-04-15 23:02:12 -04002678 if is_str and not length and not nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002679 format_unit = 's'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002680 elif is_str and not length and nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002681 format_unit = 'z'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002682 elif is_robuffer and not length and not nullable:
2683 format_unit = 'y'
2684 elif is_robuffer and length and not nullable:
2685 format_unit = 'y#'
2686 elif is_str_or_robuffer and length and not nullable:
2687 format_unit = 's#'
2688 elif is_str_or_robuffer and length and nullable:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002689 format_unit = 'z#'
2690
2691 if not format_unit:
2692 fail("str_converter: illegal combination of arguments")
2693 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002694
2695
2696class PyBytesObject_converter(CConverter):
2697 type = 'PyBytesObject *'
2698 format_unit = 'S'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002699 # types = {'bytes'}
Larry Hastings31826802013-10-19 00:09:25 -07002700
2701class PyByteArrayObject_converter(CConverter):
2702 type = 'PyByteArrayObject *'
2703 format_unit = 'Y'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002704 # types = {'bytearray'}
Larry Hastings31826802013-10-19 00:09:25 -07002705
2706class unicode_converter(CConverter):
2707 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002708 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002709 format_unit = 'U'
2710
Larry Hastingsebdcb502013-11-23 14:54:00 -08002711@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002712@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002713@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002714class Py_UNICODE_converter(CConverter):
2715 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002716 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002717 format_unit = 'u'
2718
Larry Hastingsebdcb502013-11-23 14:54:00 -08002719 def converter_init(self, *, nullable=False, length=False):
2720 format_unit = 'Z' if nullable else 'u'
2721 if length:
2722 format_unit += '#'
2723 self.length = True
2724 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002725
Larry Hastings7f90cba2015-04-15 23:02:12 -04002726@add_legacy_c_converter('s*', types={'str', 'buffer'})
2727@add_legacy_c_converter('z*', types={'str', 'buffer'}, nullable=True)
2728@add_legacy_c_converter('w*', types={'rwbuffer'})
Larry Hastings31826802013-10-19 00:09:25 -07002729class Py_buffer_converter(CConverter):
2730 type = 'Py_buffer'
2731 format_unit = 'y*'
2732 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002733 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002734
Larry Hastings7f90cba2015-04-15 23:02:12 -04002735 def converter_init(self, *, types={'buffer'}, nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002736 if self.default not in (unspecified, None):
2737 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08002738 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002739
2740 format_unit = None
Larry Hastings7f90cba2015-04-15 23:02:12 -04002741 if types == {'str', 'buffer'}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002742 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07002743 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002744 if nullable:
2745 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
Larry Hastings7f90cba2015-04-15 23:02:12 -04002746 elif types == {'buffer'}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002747 format_unit = 'y*'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002748 elif types == {'rwbuffer'}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002749 format_unit = 'w*'
2750 if not format_unit:
2751 fail("Py_buffer_converter: illegal combination of arguments")
2752
2753 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002754
2755 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002756 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002757 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002758
2759
Larry Hastings5c661892014-01-24 06:17:25 -08002760def correct_name_for_self(f):
2761 if f.kind in (CALLABLE, METHOD_INIT):
2762 if f.cls:
2763 return "PyObject *", "self"
2764 return "PyModuleDef *", "module"
2765 if f.kind == STATIC_METHOD:
2766 return "void *", "null"
2767 if f.kind in (CLASS_METHOD, METHOD_NEW):
2768 return "PyTypeObject *", "type"
2769 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2770
Larry Hastingsc2047262014-01-25 20:43:29 -08002771def required_type_for_self_for_parser(f):
2772 type, _ = correct_name_for_self(f)
2773 if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2774 return type
2775 return None
2776
Larry Hastings5c661892014-01-24 06:17:25 -08002777
Larry Hastingsebdcb502013-11-23 14:54:00 -08002778class self_converter(CConverter):
2779 """
2780 A special-case converter:
2781 this is the default converter used for "self".
2782 """
Larry Hastings5c661892014-01-24 06:17:25 -08002783 type = None
2784 format_unit = ''
2785
Larry Hastings78cf85c2014-01-04 12:44:57 -08002786 def converter_init(self, *, type=None):
Larry Hastings7726ac92014-01-31 22:03:12 -08002787 self.specified_type = type
2788
2789 def pre_render(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002790 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002791 default_type, default_name = correct_name_for_self(f)
2792 self.signature_name = default_name
Larry Hastings7726ac92014-01-31 22:03:12 -08002793 self.type = self.specified_type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002794
Larry Hastings5c661892014-01-24 06:17:25 -08002795 kind = self.function.kind
2796 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2797
2798 if (kind == STATIC_METHOD) or new_or_init:
2799 self.show_in_signature = False
2800
2801 # tp_new (METHOD_NEW) functions are of type newfunc:
2802 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2803 # PyTypeObject is a typedef for struct _typeobject.
2804 #
2805 # tp_init (METHOD_INIT) functions are of type initproc:
2806 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2807 #
2808 # All other functions generated by Argument Clinic are stored in
2809 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2810 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2811 # However! We habitually cast these functions to PyCFunction,
2812 # since functions that accept keyword arguments don't fit this signature
2813 # but are stored there anyway. So strict type equality isn't important
2814 # for these functions.
2815 #
2816 # So:
2817 #
2818 # * The name of the first parameter to the impl and the parsing function will always
2819 # be self.name.
2820 #
2821 # * The type of the first parameter to the impl will always be of self.type.
2822 #
2823 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2824 # * The type of the first parameter to the parsing function is also self.type.
2825 # This means that if you step into the parsing function, your "self" parameter
2826 # is of the correct type, which may make debugging more pleasant.
2827 #
2828 # * Else if the function is tp_new (METHOD_NEW):
2829 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2830 # so the type signature of the function call is an exact match.
2831 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2832 # in the impl call.
2833 #
2834 # * Else if the function is tp_init (METHOD_INIT):
2835 # * The type of the first parameter to the parsing function is "PyObject *",
2836 # so the type signature of the function call is an exact match.
2837 # * If self.type != "PyObject *", we cast the first parameter to self.type
2838 # in the impl call.
2839
2840 @property
2841 def parser_type(self):
Larry Hastingsc2047262014-01-25 20:43:29 -08002842 return required_type_for_self_for_parser(self.function) or self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002843
Larry Hastingsebdcb502013-11-23 14:54:00 -08002844 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002845 """
2846 parameter is a clinic.Parameter instance.
2847 data is a CRenderData instance.
2848 """
2849 if self.function.kind == STATIC_METHOD:
2850 return
2851
2852 self._render_self(parameter, data)
2853
2854 if self.type != self.parser_type:
2855 # insert cast to impl_argument[0], aka self.
2856 # we know we're in the first slot in all the CRenderData lists,
2857 # because we render parameters in order, and self is always first.
2858 assert len(data.impl_arguments) == 1
2859 assert data.impl_arguments[0] == self.name
2860 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2861
2862 def set_template_dict(self, template_dict):
2863 template_dict['self_name'] = self.name
2864 template_dict['self_type'] = self.parser_type
Larry Hastingsf0537e82014-01-25 22:01:12 -08002865 kind = self.function.kind
2866 cls = self.function.cls
2867
2868 if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef):
2869 if kind == METHOD_NEW:
2870 passed_in_type = self.name
2871 else:
2872 passed_in_type = 'Py_TYPE({})'.format(self.name)
2873
2874 line = '({passed_in_type} == {type_object}) &&\n '
2875 d = {
2876 'type_object': self.function.cls.type_object,
2877 'passed_in_type': passed_in_type
2878 }
2879 template_dict['self_type_check'] = line.format_map(d)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002880
Larry Hastings31826802013-10-19 00:09:25 -07002881
2882
2883def add_c_return_converter(f, name=None):
2884 if not name:
2885 name = f.__name__
2886 if not name.endswith('_return_converter'):
2887 return f
2888 name = name[:-len('_return_converter')]
2889 return_converters[name] = f
2890 return f
2891
2892
2893class CReturnConverterAutoRegister(type):
2894 def __init__(cls, name, bases, classdict):
2895 add_c_return_converter(cls)
2896
2897class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2898
Larry Hastings78cf85c2014-01-04 12:44:57 -08002899 # The C type to use for this variable.
2900 # 'type' should be a Python string specifying the type, e.g. "int".
2901 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002902 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002903
2904 # The Python default value for this parameter, as a Python value.
2905 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002906 default = None
2907
Larry Hastings2a727912014-01-16 11:32:01 -08002908 def __init__(self, *, py_default=None, **kwargs):
2909 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002910 try:
2911 self.return_converter_init(**kwargs)
2912 except TypeError as e:
2913 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2914 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2915
2916 def return_converter_init(self):
2917 pass
2918
2919 def declare(self, data, name="_return_value"):
2920 line = []
2921 add = line.append
2922 add(self.type)
2923 if not self.type.endswith('*'):
2924 add(' ')
2925 add(name + ';')
2926 data.declarations.append(''.join(line))
2927 data.return_value = name
2928
2929 def err_occurred_if(self, expr, data):
2930 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2931
2932 def err_occurred_if_null_pointer(self, variable, data):
2933 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2934
2935 def render(self, function, data):
2936 """
2937 function is a clinic.Function instance.
2938 data is a CRenderData instance.
2939 """
2940 pass
2941
2942add_c_return_converter(CReturnConverter, 'object')
2943
Larry Hastings78cf85c2014-01-04 12:44:57 -08002944class NoneType_return_converter(CReturnConverter):
2945 def render(self, function, data):
2946 self.declare(data)
2947 data.return_conversion.append('''
2948if (_return_value != Py_None)
2949 goto exit;
2950return_value = Py_None;
2951Py_INCREF(Py_None);
2952'''.strip())
2953
Larry Hastings4a55fc52014-01-12 11:09:57 -08002954class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002955 type = 'int'
2956
2957 def render(self, function, data):
2958 self.declare(data)
2959 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002960 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002961
2962class long_return_converter(CReturnConverter):
2963 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002964 conversion_fn = 'PyLong_FromLong'
2965 cast = ''
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002966 unsigned_cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002967
2968 def render(self, function, data):
2969 self.declare(data)
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002970 self.err_occurred_if("_return_value == {}-1".format(self.unsigned_cast), data)
Larry Hastings31826802013-10-19 00:09:25 -07002971 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002972 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002973
Larry Hastings4a55fc52014-01-12 11:09:57 -08002974class int_return_converter(long_return_converter):
2975 type = 'int'
2976 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002977
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002978class init_return_converter(long_return_converter):
2979 """
2980 Special return converter for __init__ functions.
2981 """
2982 type = 'int'
2983 cast = '(long)'
2984
2985 def render(self, function, data):
2986 pass
2987
Larry Hastings4a55fc52014-01-12 11:09:57 -08002988class unsigned_long_return_converter(long_return_converter):
2989 type = 'unsigned long'
2990 conversion_fn = 'PyLong_FromUnsignedLong'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002991 unsigned_cast = '(unsigned long)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002992
2993class unsigned_int_return_converter(unsigned_long_return_converter):
2994 type = 'unsigned int'
2995 cast = '(unsigned long)'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002996 unsigned_cast = '(unsigned int)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002997
2998class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07002999 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003000 conversion_fn = 'PyLong_FromSsize_t'
3001
3002class size_t_return_converter(long_return_converter):
3003 type = 'size_t'
3004 conversion_fn = 'PyLong_FromSize_t'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003005 unsigned_cast = '(size_t)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003006
3007
3008class double_return_converter(CReturnConverter):
3009 type = 'double'
3010 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07003011
3012 def render(self, function, data):
3013 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08003014 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07003015 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08003016 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
3017
3018class float_return_converter(double_return_converter):
3019 type = 'float'
3020 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07003021
3022
3023class DecodeFSDefault_return_converter(CReturnConverter):
3024 type = 'char *'
3025
3026 def render(self, function, data):
3027 self.declare(data)
3028 self.err_occurred_if_null_pointer("_return_value", data)
3029 data.return_conversion.append(
3030 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
3031
3032
3033class IndentStack:
3034 def __init__(self):
3035 self.indents = []
3036 self.margin = None
3037
3038 def _ensure(self):
3039 if not self.indents:
3040 fail('IndentStack expected indents, but none are defined.')
3041
3042 def measure(self, line):
3043 """
3044 Returns the length of the line's margin.
3045 """
3046 if '\t' in line:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003047 fail('Tab characters are illegal in the Argument Clinic DSL.')
Larry Hastings31826802013-10-19 00:09:25 -07003048 stripped = line.lstrip()
3049 if not len(stripped):
3050 # we can't tell anything from an empty line
3051 # so just pretend it's indented like our current indent
3052 self._ensure()
3053 return self.indents[-1]
3054 return len(line) - len(stripped)
3055
3056 def infer(self, line):
3057 """
3058 Infer what is now the current margin based on this line.
3059 Returns:
3060 1 if we have indented (or this is the first margin)
3061 0 if the margin has not changed
3062 -N if we have dedented N times
3063 """
3064 indent = self.measure(line)
3065 margin = ' ' * indent
3066 if not self.indents:
3067 self.indents.append(indent)
3068 self.margin = margin
3069 return 1
3070 current = self.indents[-1]
3071 if indent == current:
3072 return 0
3073 if indent > current:
3074 self.indents.append(indent)
3075 self.margin = margin
3076 return 1
3077 # indent < current
3078 if indent not in self.indents:
3079 fail("Illegal outdent.")
3080 outdent_count = 0
3081 while indent != current:
3082 self.indents.pop()
3083 current = self.indents[-1]
3084 outdent_count -= 1
3085 self.margin = margin
3086 return outdent_count
3087
3088 @property
3089 def depth(self):
3090 """
3091 Returns how many margins are currently defined.
3092 """
3093 return len(self.indents)
3094
3095 def indent(self, line):
3096 """
3097 Indents a line by the currently defined margin.
3098 """
3099 return self.margin + line
3100
3101 def dedent(self, line):
3102 """
3103 Dedents a line by the currently defined margin.
3104 (The inverse of 'indent'.)
3105 """
3106 margin = self.margin
3107 indent = self.indents[-1]
3108 if not line.startswith(margin):
3109 fail('Cannot dedent, line does not start with the previous margin:')
3110 return line[indent:]
3111
3112
3113class DSLParser:
3114 def __init__(self, clinic):
3115 self.clinic = clinic
3116
3117 self.directives = {}
3118 for name in dir(self):
3119 # functions that start with directive_ are added to directives
3120 _, s, key = name.partition("directive_")
3121 if s:
3122 self.directives[key] = getattr(self, name)
3123
3124 # functions that start with at_ are too, with an @ in front
3125 _, s, key = name.partition("at_")
3126 if s:
3127 self.directives['@' + key] = getattr(self, name)
3128
3129 self.reset()
3130
3131 def reset(self):
3132 self.function = None
3133 self.state = self.state_dsl_start
3134 self.parameter_indent = None
3135 self.keyword_only = False
3136 self.group = 0
3137 self.parameter_state = self.ps_start
Larry Hastingsc2047262014-01-25 20:43:29 -08003138 self.seen_positional_with_default = False
Larry Hastings31826802013-10-19 00:09:25 -07003139 self.indent = IndentStack()
3140 self.kind = CALLABLE
3141 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08003142 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08003143 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07003144
Larry Hastingsebdcb502013-11-23 14:54:00 -08003145 def directive_version(self, required):
3146 global version
3147 if version_comparitor(version, required) < 0:
3148 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
3149
Larry Hastings31826802013-10-19 00:09:25 -07003150 def directive_module(self, name):
3151 fields = name.split('.')
3152 new = fields.pop()
3153 module, cls = self.clinic._module_and_class(fields)
3154 if cls:
3155 fail("Can't nest a module inside a class!")
Larry Hastingsc2047262014-01-25 20:43:29 -08003156
3157 if name in module.classes:
3158 fail("Already defined module " + repr(name) + "!")
3159
Larry Hastings31826802013-10-19 00:09:25 -07003160 m = Module(name, module)
3161 module.modules[name] = m
3162 self.block.signatures.append(m)
3163
Larry Hastingsc2047262014-01-25 20:43:29 -08003164 def directive_class(self, name, typedef, type_object):
Larry Hastings31826802013-10-19 00:09:25 -07003165 fields = name.split('.')
3166 in_classes = False
3167 parent = self
3168 name = fields.pop()
3169 so_far = []
3170 module, cls = self.clinic._module_and_class(fields)
3171
Larry Hastingsc2047262014-01-25 20:43:29 -08003172 parent = cls or module
3173 if name in parent.classes:
3174 fail("Already defined class " + repr(name) + "!")
3175
3176 c = Class(name, module, cls, typedef, type_object)
3177 parent.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07003178 self.block.signatures.append(c)
3179
Larry Hastingsbebf7352014-01-17 17:47:17 -08003180 def directive_set(self, name, value):
3181 if name not in ("line_prefix", "line_suffix"):
3182 fail("unknown variable", repr(name))
3183
3184 value = value.format_map({
3185 'block comment start': '/*',
3186 'block comment end': '*/',
3187 })
3188
3189 self.clinic.__dict__[name] = value
3190
3191 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06003192 if command == 'new':
3193 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003194 return
3195
Zachary Ware071baa62014-01-21 23:07:12 -06003196 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08003197 self.clinic.get_destination(name).clear()
3198 fail("unknown destination command", repr(command))
3199
3200
Larry Hastings0759f842015-04-03 13:09:02 -07003201 def directive_output(self, command_or_name, destination=''):
3202 fd = self.clinic.destination_buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08003203
Larry Hastings0759f842015-04-03 13:09:02 -07003204 if command_or_name == "preset":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003205 preset = self.clinic.presets.get(destination)
3206 if not preset:
3207 fail("Unknown preset " + repr(destination) + "!")
3208 fd.update(preset)
3209 return
3210
Larry Hastings0759f842015-04-03 13:09:02 -07003211 if command_or_name == "push":
3212 self.clinic.destination_buffers_stack.append(fd.copy())
Larry Hastingsbebf7352014-01-17 17:47:17 -08003213 return
3214
Larry Hastings0759f842015-04-03 13:09:02 -07003215 if command_or_name == "pop":
3216 if not self.clinic.destination_buffers_stack:
Larry Hastingsbebf7352014-01-17 17:47:17 -08003217 fail("Can't 'output pop', stack is empty!")
Larry Hastings0759f842015-04-03 13:09:02 -07003218 previous_fd = self.clinic.destination_buffers_stack.pop()
Larry Hastingsbebf7352014-01-17 17:47:17 -08003219 fd.update(previous_fd)
3220 return
3221
3222 # secret command for debugging!
Larry Hastings0759f842015-04-03 13:09:02 -07003223 if command_or_name == "print":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003224 self.block.output.append(pprint.pformat(fd))
3225 self.block.output.append('\n')
3226 return
3227
3228 d = self.clinic.get_destination(destination)
3229
Larry Hastings0759f842015-04-03 13:09:02 -07003230 if command_or_name == "everything":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003231 for name in list(fd):
3232 fd[name] = d
3233 return
3234
Larry Hastings0759f842015-04-03 13:09:02 -07003235 if command_or_name not in fd:
3236 fail("Invalid command / destination name " + repr(command_or_name) + ", must be one of:\n preset push pop print everything " + " ".join(fd))
3237 fd[command_or_name] = d
Larry Hastingsbebf7352014-01-17 17:47:17 -08003238
3239 def directive_dump(self, name):
3240 self.block.output.append(self.clinic.get_destination(name).dump())
3241
3242 def directive_print(self, *args):
3243 self.block.output.append(' '.join(args))
3244 self.block.output.append('\n')
3245
3246 def directive_preserve(self):
3247 if self.preserve_output:
3248 fail("Can't have preserve twice in one block!")
3249 self.preserve_output = True
3250
Larry Hastings31826802013-10-19 00:09:25 -07003251 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003252 if self.kind is not CALLABLE:
3253 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003254 self.kind = CLASS_METHOD
3255
3256 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003257 if self.kind is not CALLABLE:
3258 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003259 self.kind = STATIC_METHOD
3260
3261 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003262 if self.coexist:
3263 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07003264 self.coexist = True
3265
3266 def parse(self, block):
3267 self.reset()
3268 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08003269 self.saved_output = self.block.output
3270 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07003271 block_start = self.clinic.block_parser.line_number
3272 lines = block.input.split('\n')
3273 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
3274 if '\t' in line:
3275 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
3276 self.state(line)
3277
3278 self.next(self.state_terminal)
3279 self.state(None)
3280
Larry Hastingsbebf7352014-01-17 17:47:17 -08003281 block.output.extend(self.clinic.language.render(clinic, block.signatures))
3282
3283 if self.preserve_output:
3284 if block.output:
3285 fail("'preserve' only works for blocks that don't produce any output!")
3286 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07003287
3288 @staticmethod
3289 def ignore_line(line):
3290 # ignore comment-only lines
3291 if line.lstrip().startswith('#'):
3292 return True
3293
3294 # Ignore empty lines too
3295 # (but not in docstring sections!)
3296 if not line.strip():
3297 return True
3298
3299 return False
3300
3301 @staticmethod
3302 def calculate_indent(line):
3303 return len(line) - len(line.strip())
3304
3305 def next(self, state, line=None):
3306 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3307 self.state = state
3308 if line is not None:
3309 self.state(line)
3310
3311 def state_dsl_start(self, line):
3312 # self.block = self.ClinicOutputBlock(self)
3313 if self.ignore_line(line):
3314 return
Larry Hastings7726ac92014-01-31 22:03:12 -08003315
3316 # is it a directive?
3317 fields = shlex.split(line)
3318 directive_name = fields[0]
3319 directive = self.directives.get(directive_name, None)
3320 if directive:
3321 try:
3322 directive(*fields[1:])
3323 except TypeError as e:
3324 fail(str(e))
3325 return
3326
Larry Hastings31826802013-10-19 00:09:25 -07003327 self.next(self.state_modulename_name, line)
3328
3329 def state_modulename_name(self, line):
3330 # looking for declaration, which establishes the leftmost column
3331 # line should be
3332 # modulename.fnname [as c_basename] [-> return annotation]
3333 # square brackets denote optional syntax.
3334 #
Larry Hastings4a714d42014-01-14 22:22:41 -08003335 # alternatively:
3336 # modulename.fnname [as c_basename] = modulename.existing_fn_name
3337 # clones the parameters and return converter from that
3338 # function. you can't modify them. you must enter a
3339 # new docstring.
3340 #
Larry Hastings31826802013-10-19 00:09:25 -07003341 # (but we might find a directive first!)
3342 #
3343 # this line is permitted to start with whitespace.
3344 # we'll call this number of spaces F (for "function").
3345
3346 if not line.strip():
3347 return
3348
3349 self.indent.infer(line)
3350
Larry Hastings4a714d42014-01-14 22:22:41 -08003351 # are we cloning?
3352 before, equals, existing = line.rpartition('=')
3353 if equals:
3354 full_name, _, c_basename = before.partition(' as ')
3355 full_name = full_name.strip()
3356 c_basename = c_basename.strip()
3357 existing = existing.strip()
3358 if (is_legal_py_identifier(full_name) and
3359 (not c_basename or is_legal_c_identifier(c_basename)) and
3360 is_legal_py_identifier(existing)):
3361 # we're cloning!
3362 fields = [x.strip() for x in existing.split('.')]
3363 function_name = fields.pop()
3364 module, cls = self.clinic._module_and_class(fields)
3365
3366 for existing_function in (cls or module).functions:
3367 if existing_function.name == function_name:
3368 break
3369 else:
3370 existing_function = None
3371 if not existing_function:
Larry Hastings7726ac92014-01-31 22:03:12 -08003372 print("class", cls, "module", module, "existing", existing)
Larry Hastingsc2047262014-01-25 20:43:29 -08003373 print("cls. functions", cls.functions)
Larry Hastings4a714d42014-01-14 22:22:41 -08003374 fail("Couldn't find existing function " + repr(existing) + "!")
3375
3376 fields = [x.strip() for x in full_name.split('.')]
3377 function_name = fields.pop()
3378 module, cls = self.clinic._module_and_class(fields)
3379
3380 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3381 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
Larry Hastings7726ac92014-01-31 22:03:12 -08003382 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 -08003383
3384 self.block.signatures.append(self.function)
3385 (cls or module).functions.append(self.function)
3386 self.next(self.state_function_docstring)
3387 return
3388
Larry Hastings31826802013-10-19 00:09:25 -07003389 line, _, returns = line.partition('->')
3390
3391 full_name, _, c_basename = line.partition(' as ')
3392 full_name = full_name.strip()
3393 c_basename = c_basename.strip() or None
3394
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003395 if not is_legal_py_identifier(full_name):
3396 fail("Illegal function name: {}".format(full_name))
3397 if c_basename and not is_legal_c_identifier(c_basename):
3398 fail("Illegal C basename: {}".format(c_basename))
3399
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003400 return_converter = None
3401 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003402 ast_input = "def x() -> {}: pass".format(returns)
3403 module = None
3404 try:
3405 module = ast.parse(ast_input)
3406 except SyntaxError:
3407 pass
3408 if not module:
3409 fail("Badly-formed annotation for " + full_name + ": " + returns)
3410 try:
3411 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003412 if legacy:
3413 fail("Legacy converter {!r} not allowed as a return converter"
3414 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003415 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003416 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003417 return_converter = return_converters[name](**kwargs)
3418 except ValueError:
3419 fail("Badly-formed annotation for " + full_name + ": " + returns)
3420
3421 fields = [x.strip() for x in full_name.split('.')]
3422 function_name = fields.pop()
3423 module, cls = self.clinic._module_and_class(fields)
3424
Larry Hastings8666e652014-01-12 14:12:59 -08003425 fields = full_name.split('.')
3426 if fields[-1] == '__new__':
3427 if (self.kind != CLASS_METHOD) or (not cls):
3428 fail("__new__ must be a class method!")
3429 self.kind = METHOD_NEW
3430 elif fields[-1] == '__init__':
3431 if (self.kind != CALLABLE) or (not cls):
3432 fail("__init__ must be a normal method, not a class or static method!")
3433 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003434 if not return_converter:
3435 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003436 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003437 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003438
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003439 if not return_converter:
3440 return_converter = CReturnConverter()
3441
Larry Hastings31826802013-10-19 00:09:25 -07003442 if not module:
3443 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3444 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3445 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3446 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003447
3448 # insert a self converter automatically
Larry Hastingsc2047262014-01-25 20:43:29 -08003449 type, name = correct_name_for_self(self.function)
3450 kwargs = {}
3451 if cls and type == "PyObject *":
3452 kwargs['type'] = cls.typedef
Larry Hastings7726ac92014-01-31 22:03:12 -08003453 sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs)
Larry Hastings5c661892014-01-24 06:17:25 -08003454 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3455 self.function.parameters[sc.name] = p_self
3456
Larry Hastings4a714d42014-01-14 22:22:41 -08003457 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003458 self.next(self.state_parameters_start)
3459
3460 # Now entering the parameters section. The rules, formally stated:
3461 #
3462 # * All lines must be indented with spaces only.
3463 # * The first line must be a parameter declaration.
3464 # * The first line must be indented.
3465 # * This first line establishes the indent for parameters.
3466 # * We'll call this number of spaces P (for "parameter").
3467 # * Thenceforth:
3468 # * Lines indented with P spaces specify a parameter.
3469 # * Lines indented with > P spaces are docstrings for the previous
3470 # parameter.
3471 # * We'll call this number of spaces D (for "docstring").
3472 # * All subsequent lines indented with >= D spaces are stored as
3473 # part of the per-parameter docstring.
3474 # * All lines will have the first D spaces of the indent stripped
3475 # before they are stored.
3476 # * It's illegal to have a line starting with a number of spaces X
3477 # such that P < X < D.
3478 # * A line with < P spaces is the first line of the function
3479 # docstring, which ends processing for parameters and per-parameter
3480 # docstrings.
3481 # * The first line of the function docstring must be at the same
3482 # indent as the function declaration.
3483 # * It's illegal to have any line in the parameters section starting
3484 # with X spaces such that F < X < P. (As before, F is the indent
3485 # of the function declaration.)
3486 #
Larry Hastings31826802013-10-19 00:09:25 -07003487 # Also, currently Argument Clinic places the following restrictions on groups:
3488 # * Each group must contain at least one parameter.
3489 # * Each group may contain at most one group, which must be the furthest
3490 # thing in the group from the required parameters. (The nested group
3491 # must be the first in the group when it's before the required
3492 # parameters, and the last thing in the group when after the required
3493 # parameters.)
3494 # * There may be at most one (top-level) group to the left or right of
3495 # the required parameters.
3496 # * You must specify a slash, and it must be after all parameters.
3497 # (In other words: either all parameters are positional-only,
3498 # or none are.)
3499 #
3500 # Said another way:
3501 # * Each group must contain at least one parameter.
3502 # * All left square brackets before the required parameters must be
3503 # consecutive. (You can't have a left square bracket followed
3504 # by a parameter, then another left square bracket. You can't
3505 # have a left square bracket, a parameter, a right square bracket,
3506 # and then a left square bracket.)
3507 # * All right square brackets after the required parameters must be
3508 # consecutive.
3509 #
3510 # These rules are enforced with a single state variable:
3511 # "parameter_state". (Previously the code was a miasma of ifs and
3512 # separate boolean state variables.) The states are:
3513 #
Larry Hastingsc2047262014-01-25 20:43:29 -08003514 # [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ] / <- line
3515 # 01 2 3 4 5 6 7 <- state transitions
Larry Hastings31826802013-10-19 00:09:25 -07003516 #
3517 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3518 # 1: ps_left_square_before. left square brackets before required parameters.
3519 # 2: ps_group_before. in a group, before required parameters.
Larry Hastingsc2047262014-01-25 20:43:29 -08003520 # 3: ps_required. required parameters, positional-or-keyword or positional-only
3521 # (we don't know yet). (renumber left groups!)
3522 # 4: ps_optional. positional-or-keyword or positional-only parameters that
3523 # now must have default values.
3524 # 5: ps_group_after. in a group, after required parameters.
3525 # 6: ps_right_square_after. right square brackets after required parameters.
3526 # 7: ps_seen_slash. seen slash.
Larry Hastings31826802013-10-19 00:09:25 -07003527 ps_start, ps_left_square_before, ps_group_before, ps_required, \
Larry Hastingsc2047262014-01-25 20:43:29 -08003528 ps_optional, ps_group_after, ps_right_square_after, ps_seen_slash = range(8)
Larry Hastings31826802013-10-19 00:09:25 -07003529
3530 def state_parameters_start(self, line):
3531 if self.ignore_line(line):
3532 return
3533
3534 # if this line is not indented, we have no parameters
3535 if not self.indent.infer(line):
3536 return self.next(self.state_function_docstring, line)
3537
Larry Hastings2a727912014-01-16 11:32:01 -08003538 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003539 return self.next(self.state_parameter, line)
3540
3541
3542 def to_required(self):
3543 """
3544 Transition to the "required" parameter state.
3545 """
3546 if self.parameter_state != self.ps_required:
3547 self.parameter_state = self.ps_required
3548 for p in self.function.parameters.values():
3549 p.group = -p.group
3550
3551 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003552 if self.parameter_continuation:
3553 line = self.parameter_continuation + ' ' + line.lstrip()
3554 self.parameter_continuation = ''
3555
Larry Hastings31826802013-10-19 00:09:25 -07003556 if self.ignore_line(line):
3557 return
3558
3559 assert self.indent.depth == 2
3560 indent = self.indent.infer(line)
3561 if indent == -1:
3562 # we outdented, must be to definition column
3563 return self.next(self.state_function_docstring, line)
3564
3565 if indent == 1:
3566 # we indented, must be to new parameter docstring column
3567 return self.next(self.state_parameter_docstring_start, line)
3568
Larry Hastings2a727912014-01-16 11:32:01 -08003569 line = line.rstrip()
3570 if line.endswith('\\'):
3571 self.parameter_continuation = line[:-1]
3572 return
3573
Larry Hastings31826802013-10-19 00:09:25 -07003574 line = line.lstrip()
3575
3576 if line in ('*', '/', '[', ']'):
3577 self.parse_special_symbol(line)
3578 return
3579
3580 if self.parameter_state in (self.ps_start, self.ps_required):
3581 self.to_required()
3582 elif self.parameter_state == self.ps_left_square_before:
3583 self.parameter_state = self.ps_group_before
3584 elif self.parameter_state == self.ps_group_before:
3585 if not self.group:
3586 self.to_required()
Larry Hastingsc2047262014-01-25 20:43:29 -08003587 elif self.parameter_state in (self.ps_group_after, self.ps_optional):
Larry Hastings31826802013-10-19 00:09:25 -07003588 pass
3589 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003590 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
Larry Hastings31826802013-10-19 00:09:25 -07003591
Larry Hastings7726ac92014-01-31 22:03:12 -08003592 # handle "as" for parameters too
3593 c_name = None
3594 name, have_as_token, trailing = line.partition(' as ')
3595 if have_as_token:
3596 name = name.strip()
3597 if ' ' not in name:
3598 fields = trailing.strip().split(' ')
3599 if not fields:
3600 fail("Invalid 'as' clause!")
3601 c_name = fields[0]
3602 if c_name.endswith(':'):
3603 name += ':'
3604 c_name = c_name[:-1]
3605 fields[0] = name
3606 line = ' '.join(fields)
3607
Larry Hastings2a727912014-01-16 11:32:01 -08003608 base, equals, default = line.rpartition('=')
3609 if not equals:
3610 base = default
3611 default = None
Larry Hastingsc2047262014-01-25 20:43:29 -08003612
Larry Hastings31826802013-10-19 00:09:25 -07003613 module = None
3614 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003615 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003616 module = ast.parse(ast_input)
3617 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003618 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08003619 # the last = was probably inside a function call, like
3620 # i: int(nullable=True)
3621 # so assume there was no actual default value.
Larry Hastings2a727912014-01-16 11:32:01 -08003622 default = None
3623 ast_input = "def x({}): pass".format(line)
3624 module = ast.parse(ast_input)
3625 except SyntaxError:
3626 pass
Larry Hastings31826802013-10-19 00:09:25 -07003627 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003628 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003629
3630 function_args = module.body[0].args
3631 parameter = function_args.args[0]
3632
Larry Hastings16c51912014-01-07 11:53:01 -08003633 parameter_name = parameter.arg
3634 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3635
Larry Hastings2a727912014-01-16 11:32:01 -08003636 if not default:
Larry Hastingsc2047262014-01-25 20:43:29 -08003637 if self.parameter_state == self.ps_optional:
3638 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 -08003639 value = unspecified
3640 if 'py_default' in kwargs:
3641 fail("You can't specify py_default without specifying a default value!")
3642 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003643 if self.parameter_state == self.ps_required:
3644 self.parameter_state = self.ps_optional
Larry Hastings2a727912014-01-16 11:32:01 -08003645 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003646 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003647 ast_input = "x = {}".format(default)
Larry Hastingsc2047262014-01-25 20:43:29 -08003648 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003649 try:
3650 module = ast.parse(ast_input)
3651
Larry Hastings5c661892014-01-24 06:17:25 -08003652 if 'c_default' not in kwargs:
3653 # we can only represent very simple data values in C.
3654 # detect whether default is okay, via a blacklist
3655 # of disallowed ast nodes.
3656 class DetectBadNodes(ast.NodeVisitor):
3657 bad = False
3658 def bad_node(self, node):
3659 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003660
Larry Hastings5c661892014-01-24 06:17:25 -08003661 # inline function call
3662 visit_Call = bad_node
3663 # inline if statement ("x = 3 if y else z")
3664 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003665
Larry Hastings5c661892014-01-24 06:17:25 -08003666 # comprehensions and generator expressions
3667 visit_ListComp = visit_SetComp = bad_node
3668 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003669
Larry Hastings5c661892014-01-24 06:17:25 -08003670 # literals for advanced types
3671 visit_Dict = visit_Set = bad_node
3672 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003673
Larry Hastings5c661892014-01-24 06:17:25 -08003674 # "starred": "a = [1, 2, 3]; *a"
3675 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003676
Larry Hastings5c661892014-01-24 06:17:25 -08003677 # allow ellipsis, for now
3678 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003679
Larry Hastings5c661892014-01-24 06:17:25 -08003680 blacklist = DetectBadNodes()
3681 blacklist.visit(module)
3682 bad = blacklist.bad
3683 else:
3684 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003685 # but at least make an attempt at ensuring it's a valid expression.
3686 try:
3687 value = eval(default)
3688 if value == unspecified:
3689 fail("'unspecified' is not a legal default value!")
3690 except NameError:
3691 pass # probably a named constant
3692 except Exception as e:
3693 fail("Malformed expression given as default value\n"
3694 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003695 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003696 fail("Unsupported expression as default value: " + repr(default))
3697
3698 expr = module.body[0].value
3699 # mild hack: explicitly support NULL as a default value
3700 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3701 value = NULL
3702 py_default = 'None'
3703 c_default = "NULL"
3704 elif (isinstance(expr, ast.BinOp) or
3705 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3706 c_default = kwargs.get("c_default")
3707 if not (isinstance(c_default, str) and c_default):
3708 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3709 py_default = default
3710 value = unknown
3711 elif isinstance(expr, ast.Attribute):
3712 a = []
3713 n = expr
3714 while isinstance(n, ast.Attribute):
3715 a.append(n.attr)
3716 n = n.value
3717 if not isinstance(n, ast.Name):
3718 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3719 a.append(n.id)
3720 py_default = ".".join(reversed(a))
3721
3722 c_default = kwargs.get("c_default")
3723 if not (isinstance(c_default, str) and c_default):
3724 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3725
3726 try:
3727 value = eval(py_default)
3728 except NameError:
3729 value = unknown
3730 else:
3731 value = ast.literal_eval(expr)
3732 py_default = repr(value)
3733 if isinstance(value, (bool, None.__class__)):
3734 c_default = "Py_" + py_default
3735 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003736 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003737 else:
3738 c_default = py_default
3739
3740 except SyntaxError as e:
3741 fail("Syntax error: " + repr(e.text))
3742 except (ValueError, AttributeError):
3743 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003744 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003745 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003746 if not (isinstance(c_default, str) and c_default):
3747 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3748
Larry Hastings2a727912014-01-16 11:32:01 -08003749 kwargs.setdefault('c_default', c_default)
3750 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003751
Larry Hastings31826802013-10-19 00:09:25 -07003752 dict = legacy_converters if legacy else converters
3753 legacy_str = "legacy " if legacy else ""
3754 if name not in dict:
3755 fail('{} is not a valid {}converter'.format(name, legacy_str))
Larry Hastings7726ac92014-01-31 22:03:12 -08003756 # if you use a c_name for the parameter, we just give that name to the converter
3757 # but the parameter object gets the python name
3758 converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
Larry Hastings31826802013-10-19 00:09:25 -07003759
3760 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003761
3762 if isinstance(converter, self_converter):
3763 if len(self.function.parameters) == 1:
3764 if (self.parameter_state != self.ps_required):
3765 fail("A 'self' parameter cannot be marked optional.")
3766 if value is not unspecified:
3767 fail("A 'self' parameter cannot have a default value.")
3768 if self.group:
3769 fail("A 'self' parameter cannot be in an optional group.")
3770 kind = inspect.Parameter.POSITIONAL_ONLY
3771 self.parameter_state = self.ps_start
3772 self.function.parameters.clear()
3773 else:
3774 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3775
Larry Hastings31826802013-10-19 00:09:25 -07003776 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003777
3778 if parameter_name in self.function.parameters:
3779 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003780 self.function.parameters[parameter_name] = p
3781
3782 def parse_converter(self, annotation):
3783 if isinstance(annotation, ast.Str):
3784 return annotation.s, True, {}
3785
3786 if isinstance(annotation, ast.Name):
3787 return annotation.id, False, {}
3788
Larry Hastings4a55fc52014-01-12 11:09:57 -08003789 if not isinstance(annotation, ast.Call):
3790 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003791
3792 name = annotation.func.id
3793 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
3794 return name, False, kwargs
3795
3796 def parse_special_symbol(self, symbol):
3797 if self.parameter_state == self.ps_seen_slash:
3798 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3799
3800 if symbol == '*':
3801 if self.keyword_only:
3802 fail("Function " + self.function.name + " uses '*' more than once.")
3803 self.keyword_only = True
3804 elif symbol == '[':
3805 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3806 self.parameter_state = self.ps_left_square_before
3807 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3808 self.parameter_state = self.ps_group_after
3809 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003810 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
Larry Hastings31826802013-10-19 00:09:25 -07003811 self.group += 1
Larry Hastings2623c8c2014-02-08 22:15:29 -08003812 self.function.docstring_only = True
Larry Hastings31826802013-10-19 00:09:25 -07003813 elif symbol == ']':
3814 if not self.group:
3815 fail("Function " + self.function.name + " has a ] without a matching [.")
3816 if not any(p.group == self.group for p in self.function.parameters.values()):
3817 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3818 self.group -= 1
3819 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3820 self.parameter_state = self.ps_group_before
3821 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3822 self.parameter_state = self.ps_right_square_after
3823 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003824 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
Larry Hastings31826802013-10-19 00:09:25 -07003825 elif symbol == '/':
Larry Hastingsc2047262014-01-25 20:43:29 -08003826 # ps_required and ps_optional are allowed here, that allows positional-only without option groups
Larry Hastings31826802013-10-19 00:09:25 -07003827 # to work (and have default values!)
Larry Hastingsc2047262014-01-25 20:43:29 -08003828 if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
3829 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
Larry Hastings31826802013-10-19 00:09:25 -07003830 if self.keyword_only:
3831 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3832 self.parameter_state = self.ps_seen_slash
Berker Peksagf23530f2014-10-19 18:04:38 +03003833 # fixup preceding parameters
Larry Hastings31826802013-10-19 00:09:25 -07003834 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003835 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003836 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3837 p.kind = inspect.Parameter.POSITIONAL_ONLY
3838
3839 def state_parameter_docstring_start(self, line):
3840 self.parameter_docstring_indent = len(self.indent.margin)
3841 assert self.indent.depth == 3
3842 return self.next(self.state_parameter_docstring, line)
3843
3844 # every line of the docstring must start with at least F spaces,
3845 # where F > P.
3846 # these F spaces will be stripped.
3847 def state_parameter_docstring(self, line):
3848 stripped = line.strip()
3849 if stripped.startswith('#'):
3850 return
3851
3852 indent = self.indent.measure(line)
3853 if indent < self.parameter_docstring_indent:
3854 self.indent.infer(line)
3855 assert self.indent.depth < 3
3856 if self.indent.depth == 2:
3857 # back to a parameter
3858 return self.next(self.state_parameter, line)
3859 assert self.indent.depth == 1
3860 return self.next(self.state_function_docstring, line)
3861
3862 assert self.function.parameters
3863 last_parameter = next(reversed(list(self.function.parameters.values())))
3864
3865 new_docstring = last_parameter.docstring
3866
3867 if new_docstring:
3868 new_docstring += '\n'
3869 if stripped:
3870 new_docstring += self.indent.dedent(line)
3871
3872 last_parameter.docstring = new_docstring
3873
3874 # the final stanza of the DSL is the docstring.
3875 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003876 if self.group:
3877 fail("Function " + self.function.name + " has a ] without a matching [.")
3878
3879 stripped = line.strip()
3880 if stripped.startswith('#'):
3881 return
3882
3883 new_docstring = self.function.docstring
3884 if new_docstring:
3885 new_docstring += "\n"
3886 if stripped:
3887 line = self.indent.dedent(line).rstrip()
3888 else:
3889 line = ''
3890 new_docstring += line
3891 self.function.docstring = new_docstring
3892
3893 def format_docstring(self):
3894 f = self.function
3895
Larry Hastings5c661892014-01-24 06:17:25 -08003896 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3897 if new_or_init and not f.docstring:
3898 # don't render a docstring at all, no signature, nothing.
3899 return f.docstring
3900
Larry Hastings2623c8c2014-02-08 22:15:29 -08003901 text, add, output = _text_accumulator()
Larry Hastings7726ac92014-01-31 22:03:12 -08003902 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07003903
3904 ##
3905 ## docstring first line
3906 ##
3907
Larry Hastings2623c8c2014-02-08 22:15:29 -08003908 if new_or_init:
3909 # classes get *just* the name of the class
3910 # not __new__, not __init__, and not module.classname
3911 assert f.cls
3912 add(f.cls.name)
Larry Hastings46258262014-01-22 03:05:49 -08003913 else:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003914 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003915 add('(')
3916
3917 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003918 assert parameters, "We should always have a self parameter. " + repr(f)
3919 assert isinstance(parameters[0].converter, self_converter)
3920 parameters[0].right_bracket_count = 0
3921 parameters_after_self = parameters[1:]
3922 if parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003923 # for now, the only way Clinic supports positional-only parameters
Larry Hastings5c661892014-01-24 06:17:25 -08003924 # is if all of them are positional-only...
3925 #
3926 # ... except for self! self is always positional-only.
3927
3928 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters_after_self]
3929 if parameters_after_self[0].kind == inspect.Parameter.POSITIONAL_ONLY:
Larry Hastings31826802013-10-19 00:09:25 -07003930 assert all(positional_only_parameters)
3931 for p in parameters:
3932 p.right_bracket_count = abs(p.group)
3933 else:
3934 # don't put any right brackets around non-positional-only parameters, ever.
Larry Hastings5c661892014-01-24 06:17:25 -08003935 for p in parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003936 p.right_bracket_count = 0
3937
3938 right_bracket_count = 0
3939
3940 def fix_right_bracket_count(desired):
3941 nonlocal right_bracket_count
3942 s = ''
3943 while right_bracket_count < desired:
3944 s += '['
3945 right_bracket_count += 1
3946 while right_bracket_count > desired:
3947 s += ']'
3948 right_bracket_count -= 1
3949 return s
3950
Larry Hastings2623c8c2014-02-08 22:15:29 -08003951 need_slash = False
3952 added_slash = False
3953 need_a_trailing_slash = False
3954
3955 # we only need a trailing slash:
3956 # * if this is not a "docstring_only" signature
3957 # * and if the last *shown* parameter is
3958 # positional only
3959 if not f.docstring_only:
3960 for p in reversed(parameters):
3961 if not p.converter.show_in_signature:
3962 continue
3963 if p.is_positional_only():
3964 need_a_trailing_slash = True
3965 break
3966
3967
Larry Hastings31826802013-10-19 00:09:25 -07003968 added_star = False
Larry Hastings2623c8c2014-02-08 22:15:29 -08003969
3970 first_parameter = True
3971 last_p = parameters[-1]
3972 line_length = len(''.join(text))
3973 indent = " " * line_length
3974 def add_parameter(text):
3975 nonlocal line_length
3976 nonlocal first_parameter
3977 if first_parameter:
3978 s = text
3979 first_parameter = False
3980 else:
3981 s = ' ' + text
3982 if line_length + len(s) >= 72:
3983 add('\n')
3984 add(indent)
3985 line_length = len(indent)
3986 s = text
3987 line_length += len(s)
3988 add(s)
Larry Hastings31826802013-10-19 00:09:25 -07003989
3990 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08003991 if not p.converter.show_in_signature:
3992 continue
Larry Hastings31826802013-10-19 00:09:25 -07003993 assert p.name
3994
Larry Hastings2623c8c2014-02-08 22:15:29 -08003995 is_self = isinstance(p.converter, self_converter)
3996 if is_self and f.docstring_only:
3997 # this isn't a real machine-parsable signature,
3998 # so let's not print the "self" parameter
3999 continue
4000
4001 if p.is_positional_only():
4002 need_slash = not f.docstring_only
4003 elif need_slash and not (added_slash or p.is_positional_only()):
4004 added_slash = True
4005 add_parameter('/,')
4006
Larry Hastings31826802013-10-19 00:09:25 -07004007 if p.is_keyword_only() and not added_star:
4008 added_star = True
Larry Hastings2623c8c2014-02-08 22:15:29 -08004009 add_parameter('*,')
4010
4011 p_add, p_output = text_accumulator()
4012 p_add(fix_right_bracket_count(p.right_bracket_count))
4013
4014 if isinstance(p.converter, self_converter):
4015 # annotate first parameter as being a "self".
4016 #
4017 # if inspect.Signature gets this function,
4018 # and it's already bound, the self parameter
4019 # will be stripped off.
4020 #
4021 # if it's not bound, it should be marked
4022 # as positional-only.
4023 #
4024 # note: we don't print "self" for __init__,
4025 # because this isn't actually the signature
4026 # for __init__. (it can't be, __init__ doesn't
4027 # have a docstring.) if this is an __init__
4028 # (or __new__), then this signature is for
Berker Peksagf23530f2014-10-19 18:04:38 +03004029 # calling the class to construct a new instance.
Larry Hastings2623c8c2014-02-08 22:15:29 -08004030 p_add('$')
Larry Hastings31826802013-10-19 00:09:25 -07004031
Larry Hastings5c661892014-01-24 06:17:25 -08004032 name = p.converter.signature_name or p.name
Larry Hastings2623c8c2014-02-08 22:15:29 -08004033 p_add(name)
Larry Hastings581ee362014-01-28 05:00:08 -08004034
Larry Hastings31826802013-10-19 00:09:25 -07004035 if p.converter.is_optional():
Larry Hastings2623c8c2014-02-08 22:15:29 -08004036 p_add('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08004037 value = p.converter.py_default
4038 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08004039 value = repr(p.converter.default)
Larry Hastings2623c8c2014-02-08 22:15:29 -08004040 p_add(value)
4041
4042 if (p != last_p) or need_a_trailing_slash:
4043 p_add(',')
4044
4045 add_parameter(p_output())
Larry Hastings31826802013-10-19 00:09:25 -07004046
4047 add(fix_right_bracket_count(0))
Larry Hastings2623c8c2014-02-08 22:15:29 -08004048 if need_a_trailing_slash:
4049 add_parameter('/')
Larry Hastings31826802013-10-19 00:09:25 -07004050 add(')')
4051
Larry Hastings2a727912014-01-16 11:32:01 -08004052 # PEP 8 says:
4053 #
4054 # The Python standard library will not use function annotations
4055 # as that would result in a premature commitment to a particular
4056 # annotation style. Instead, the annotations are left for users
4057 # to discover and experiment with useful annotation styles.
4058 #
4059 # therefore this is commented out:
4060 #
4061 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004062 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08004063 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07004064
Larry Hastings2623c8c2014-02-08 22:15:29 -08004065 if not f.docstring_only:
Zachary Ware8ef887c2015-04-13 18:22:35 -05004066 add("\n" + sig_end_marker + "\n")
Larry Hastings2623c8c2014-02-08 22:15:29 -08004067
Larry Hastings31826802013-10-19 00:09:25 -07004068 docstring_first_line = output()
4069
4070 # now fix up the places where the brackets look wrong
4071 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
4072
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004073 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07004074 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004075 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07004076 for p in parameters:
4077 if not p.docstring.strip():
4078 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004079 if spacer_line:
4080 add('\n')
4081 else:
4082 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07004083 add(" ")
4084 add(p.name)
4085 add('\n')
4086 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004087 parameters = output()
4088 if parameters:
4089 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07004090
4091 ##
4092 ## docstring body
4093 ##
4094
4095 docstring = f.docstring.rstrip()
4096 lines = [line.rstrip() for line in docstring.split('\n')]
4097
4098 # Enforce the summary line!
4099 # The first line of a docstring should be a summary of the function.
4100 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
4101 # by itself.
4102 #
4103 # Argument Clinic enforces the following rule:
4104 # * either the docstring is empty,
4105 # * or it must have a summary line.
4106 #
4107 # Guido said Clinic should enforce this:
4108 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
4109
4110 if len(lines) >= 2:
4111 if lines[1]:
4112 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
4113 "Every non-blank function docstring must start with\n" +
4114 "a single line summary followed by an empty line.")
4115 elif len(lines) == 1:
4116 # the docstring is only one line right now--the summary line.
4117 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004118 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07004119 lines.append('')
4120
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004121 parameters_marker_count = len(docstring.split('{parameters}')) - 1
4122 if parameters_marker_count > 1:
4123 fail('You may not specify {parameters} more than once in a docstring!')
4124
4125 if not parameters_marker_count:
4126 # insert after summary line
4127 lines.insert(2, '{parameters}')
4128
4129 # insert at front of docstring
4130 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07004131
4132 docstring = "\n".join(lines)
4133
4134 add(docstring)
4135 docstring = output()
4136
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004137 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07004138 docstring = docstring.rstrip()
4139
4140 return docstring
4141
4142 def state_terminal(self, line):
4143 """
4144 Called when processing the block is done.
4145 """
4146 assert not line
4147
4148 if not self.function:
4149 return
4150
4151 if self.keyword_only:
4152 values = self.function.parameters.values()
4153 if not values:
4154 no_parameter_after_star = True
4155 else:
4156 last_parameter = next(reversed(list(values)))
4157 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
4158 if no_parameter_after_star:
4159 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
4160
4161 # remove trailing whitespace from all parameter docstrings
4162 for name, value in self.function.parameters.items():
4163 if not value:
4164 continue
4165 value.docstring = value.docstring.rstrip()
4166
4167 self.function.docstring = self.format_docstring()
4168
4169
Larry Hastings5c661892014-01-24 06:17:25 -08004170
4171
Larry Hastings31826802013-10-19 00:09:25 -07004172# maps strings to callables.
4173# the callable should return an object
4174# that implements the clinic parser
4175# interface (__init__ and parse).
4176#
4177# example parsers:
4178# "clinic", handles the Clinic DSL
4179# "python", handles running Python code
4180#
4181parsers = {'clinic' : DSLParser, 'python': PythonParser}
4182
4183
4184clinic = None
4185
4186
4187def main(argv):
4188 import sys
4189
4190 if sys.version_info.major < 3 or sys.version_info.minor < 3:
4191 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
4192
4193 import argparse
4194 cmdline = argparse.ArgumentParser()
4195 cmdline.add_argument("-f", "--force", action='store_true')
4196 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08004197 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004198 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004199 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004200 cmdline.add_argument("filename", type=str, nargs="*")
4201 ns = cmdline.parse_args(argv)
4202
4203 if ns.converters:
4204 if ns.filename:
4205 print("Usage error: can't specify --converters and a filename at the same time.")
4206 print()
4207 cmdline.print_usage()
4208 sys.exit(-1)
4209 converters = []
4210 return_converters = []
4211 ignored = set("""
4212 add_c_converter
4213 add_c_return_converter
4214 add_default_legacy_c_converter
4215 add_legacy_c_converter
4216 """.strip().split())
4217 module = globals()
4218 for name in module:
4219 for suffix, ids in (
4220 ("_return_converter", return_converters),
4221 ("_converter", converters),
4222 ):
4223 if name in ignored:
4224 continue
4225 if name.endswith(suffix):
4226 ids.append((name, name[:-len(suffix)]))
4227 break
4228 print()
4229
4230 print("Legacy converters:")
4231 legacy = sorted(legacy_converters)
4232 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
4233 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
4234 print()
4235
4236 for title, attribute, ids in (
4237 ("Converters", 'converter_init', converters),
4238 ("Return converters", 'return_converter_init', return_converters),
4239 ):
4240 print(title + ":")
4241 longest = -1
4242 for name, short_name in ids:
4243 longest = max(longest, len(short_name))
4244 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
4245 cls = module[name]
4246 callable = getattr(cls, attribute, None)
4247 if not callable:
4248 continue
4249 signature = inspect.signature(callable)
4250 parameters = []
4251 for parameter_name, parameter in signature.parameters.items():
4252 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
4253 if parameter.default != inspect.Parameter.empty:
4254 s = '{}={!r}'.format(parameter_name, parameter.default)
4255 else:
4256 s = parameter_name
4257 parameters.append(s)
4258 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07004259 print()
Larry Hastings2a727912014-01-16 11:32:01 -08004260 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
4261 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07004262 sys.exit(0)
4263
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004264 if ns.make:
4265 if ns.output or ns.filename:
4266 print("Usage error: can't use -o or filenames with --make.")
4267 print()
4268 cmdline.print_usage()
4269 sys.exit(-1)
4270 for root, dirs, files in os.walk('.'):
Zachary Warebbbbe7e2015-04-13 18:33:41 -05004271 for rcs_dir in ('.svn', '.git', '.hg', 'build', 'externals'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004272 if rcs_dir in dirs:
4273 dirs.remove(rcs_dir)
4274 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08004275 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004276 continue
4277 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08004278 if ns.verbose:
4279 print(path)
Larry Hastings581ee362014-01-28 05:00:08 -08004280 parse_file(path, force=ns.force, verify=not ns.force)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004281 return
4282
Larry Hastings31826802013-10-19 00:09:25 -07004283 if not ns.filename:
4284 cmdline.print_usage()
4285 sys.exit(-1)
4286
4287 if ns.output and len(ns.filename) > 1:
4288 print("Usage error: can't use -o with multiple filenames.")
4289 print()
4290 cmdline.print_usage()
4291 sys.exit(-1)
4292
4293 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08004294 if ns.verbose:
4295 print(filename)
Larry Hastings581ee362014-01-28 05:00:08 -08004296 parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
Larry Hastings31826802013-10-19 00:09:25 -07004297
4298
4299if __name__ == "__main__":
4300 sys.exit(main(sys.argv[1:]))