blob: 1adabb95cc96a8575e8130c523756cb58fb7e87f [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
Larry Hastings31826802013-10-19 00:09:25 -070010import collections
11import contextlib
Larry Hastings7726ac92014-01-31 22:03:12 -080012import copy
13import cpp
Larry Hastings31826802013-10-19 00:09:25 -070014import functools
15import hashlib
16import inspect
17import io
18import itertools
19import os
Larry Hastingsbebf7352014-01-17 17:47:17 -080020import pprint
Larry Hastings31826802013-10-19 00:09:25 -070021import re
22import shlex
Larry Hastings581ee362014-01-28 05:00:08 -080023import string
Larry Hastings31826802013-10-19 00:09:25 -070024import sys
25import tempfile
26import textwrap
Georg Brandlaabebde2014-01-16 06:53:54 +010027import traceback
Larry Hastingsdbfdc382015-05-04 06:59:46 -070028import types
Larry Hastings31826802013-10-19 00:09:25 -070029
Larry Hastingsdbfdc382015-05-04 06:59:46 -070030from types import *
31NoneType = type(None)
32
Larry Hastings31826802013-10-19 00:09:25 -070033# TODO:
Larry Hastings31826802013-10-19 00:09:25 -070034#
35# soon:
36#
37# * allow mixing any two of {positional-only, positional-or-keyword,
38# keyword-only}
39# * dict constructor uses positional-only and keyword-only
40# * max and min use positional only with an optional group
41# and keyword-only
42#
Larry Hastings31826802013-10-19 00:09:25 -070043
Larry Hastingsebdcb502013-11-23 14:54:00 -080044version = '1'
45
Larry Hastings31826802013-10-19 00:09:25 -070046_empty = inspect._empty
47_void = inspect._void
48
Larry Hastings4a55fc52014-01-12 11:09:57 -080049NoneType = type(None)
Larry Hastings31826802013-10-19 00:09:25 -070050
51class Unspecified:
52 def __repr__(self):
53 return '<Unspecified>'
54
55unspecified = Unspecified()
56
57
58class Null:
59 def __repr__(self):
60 return '<Null>'
61
62NULL = Null()
63
64
Larry Hastings2a727912014-01-16 11:32:01 -080065class Unknown:
66 def __repr__(self):
67 return '<Unknown>'
68
69unknown = Unknown()
70
Zachary Ware8ef887c2015-04-13 18:22:35 -050071sig_end_marker = '--'
72
Larry Hastings2a727912014-01-16 11:32:01 -080073
Larry Hastings0759f842015-04-03 13:09:02 -070074_text_accumulator_nt = collections.namedtuple("_text_accumulator", "text append output")
75
Larry Hastings31826802013-10-19 00:09:25 -070076def _text_accumulator():
77 text = []
78 def output():
79 s = ''.join(text)
80 text.clear()
81 return s
Larry Hastings0759f842015-04-03 13:09:02 -070082 return _text_accumulator_nt(text, text.append, output)
Larry Hastings31826802013-10-19 00:09:25 -070083
84
Larry Hastings0759f842015-04-03 13:09:02 -070085text_accumulator_nt = collections.namedtuple("text_accumulator", "text append")
86
Larry Hastings31826802013-10-19 00:09:25 -070087def text_accumulator():
88 """
89 Creates a simple text accumulator / joiner.
90
91 Returns a pair of callables:
92 append, output
93 "append" appends a string to the accumulator.
94 "output" returns the contents of the accumulator
95 joined together (''.join(accumulator)) and
96 empties the accumulator.
97 """
98 text, append, output = _text_accumulator()
Larry Hastings0759f842015-04-03 13:09:02 -070099 return text_accumulator_nt(append, output)
Larry Hastings31826802013-10-19 00:09:25 -0700100
101
Larry Hastingsbebf7352014-01-17 17:47:17 -0800102def warn_or_fail(fail=False, *args, filename=None, line_number=None):
Larry Hastings31826802013-10-19 00:09:25 -0700103 joined = " ".join([str(a) for a in args])
104 add, output = text_accumulator()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800105 if fail:
106 add("Error")
107 else:
108 add("Warning")
Larry Hastings31826802013-10-19 00:09:25 -0700109 if clinic:
110 if filename is None:
111 filename = clinic.filename
Larry Hastings581ee362014-01-28 05:00:08 -0800112 if getattr(clinic, 'block_parser', None) and (line_number is None):
Larry Hastings31826802013-10-19 00:09:25 -0700113 line_number = clinic.block_parser.line_number
114 if filename is not None:
115 add(' in file "' + filename + '"')
116 if line_number is not None:
117 add(" on line " + str(line_number))
118 add(':\n')
119 add(joined)
120 print(output())
Larry Hastingsbebf7352014-01-17 17:47:17 -0800121 if fail:
122 sys.exit(-1)
Larry Hastings31826802013-10-19 00:09:25 -0700123
124
Larry Hastingsbebf7352014-01-17 17:47:17 -0800125def warn(*args, filename=None, line_number=None):
126 return warn_or_fail(False, *args, filename=filename, line_number=line_number)
127
128def fail(*args, filename=None, line_number=None):
129 return warn_or_fail(True, *args, filename=filename, line_number=line_number)
130
Larry Hastings31826802013-10-19 00:09:25 -0700131
132def quoted_for_c_string(s):
133 for old, new in (
Zachary Ware9d7849f2014-01-25 03:26:20 -0600134 ('\\', '\\\\'), # must be first!
Larry Hastings31826802013-10-19 00:09:25 -0700135 ('"', '\\"'),
136 ("'", "\\'"),
137 ):
138 s = s.replace(old, new)
139 return s
140
Larry Hastings4903e002014-01-18 00:26:16 -0800141def c_repr(s):
142 return '"' + s + '"'
143
144
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700145is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
146
147def is_legal_py_identifier(s):
148 return all(is_legal_c_identifier(field) for field in s.split('.'))
149
Larry Hastingsbebf7352014-01-17 17:47:17 -0800150# identifiers that are okay in Python but aren't a good idea in C.
151# so if they're used Argument Clinic will add "_value" to the end
152# of the name in C.
Larry Hastings31826802013-10-19 00:09:25 -0700153c_keywords = set("""
Larry Hastings5c661892014-01-24 06:17:25 -0800154asm auto break case char const continue default do double
155else enum extern float for goto if inline int long
156register return short signed sizeof static struct switch
Larry Hastingsbebf7352014-01-17 17:47:17 -0800157typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700158""".strip().split())
159
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700160def ensure_legal_c_identifier(s):
161 # for now, just complain if what we're given isn't legal
162 if not is_legal_c_identifier(s):
163 fail("Illegal C identifier: {}".format(s))
164 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700165 if s in c_keywords:
166 return s + "_value"
167 return s
168
169def rstrip_lines(s):
170 text, add, output = _text_accumulator()
171 for line in s.split('\n'):
172 add(line.rstrip())
173 add('\n')
174 text.pop()
175 return output()
176
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +0300177def format_escape(s):
178 # double up curly-braces, this string will be used
179 # as part of a format_map() template later
180 s = s.replace('{', '{{')
181 s = s.replace('}', '}}')
182 return s
183
Larry Hastings31826802013-10-19 00:09:25 -0700184def linear_format(s, **kwargs):
185 """
186 Perform str.format-like substitution, except:
187 * The strings substituted must be on lines by
188 themselves. (This line is the "source line".)
189 * If the substitution text is empty, the source line
190 is removed in the output.
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800191 * If the field is not recognized, the original line
192 is passed unmodified through to the output.
Larry Hastings31826802013-10-19 00:09:25 -0700193 * If the substitution text is not empty:
194 * Each line of the substituted text is indented
195 by the indent of the source line.
196 * A newline will be added to the end.
197 """
198
199 add, output = text_accumulator()
200 for line in s.split('\n'):
201 indent, curly, trailing = line.partition('{')
202 if not curly:
203 add(line)
204 add('\n')
205 continue
206
Martin Panter4177e7c2016-02-14 03:23:13 +0000207 name, curly, trailing = trailing.partition('}')
Larry Hastings31826802013-10-19 00:09:25 -0700208 if not curly or name not in kwargs:
209 add(line)
210 add('\n')
211 continue
212
213 if trailing:
214 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
215 if indent.strip():
216 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
217
218 value = kwargs[name]
219 if not value:
220 continue
221
222 value = textwrap.indent(rstrip_lines(value), indent)
223 add(value)
224 add('\n')
225
226 return output()[:-1]
227
Larry Hastingsbebf7352014-01-17 17:47:17 -0800228def indent_all_lines(s, prefix):
229 """
230 Returns 's', with 'prefix' prepended to all lines.
231
232 If the last line is empty, prefix is not prepended
233 to it. (If s is blank, returns s unchanged.)
234
235 (textwrap.indent only adds to non-blank lines.)
236 """
237 split = s.split('\n')
238 last = split.pop()
239 final = []
240 for line in split:
241 final.append(prefix)
242 final.append(line)
243 final.append('\n')
244 if last:
245 final.append(prefix)
246 final.append(last)
247 return ''.join(final)
248
249def suffix_all_lines(s, suffix):
250 """
251 Returns 's', with 'suffix' appended to all lines.
252
253 If the last line is empty, suffix is not appended
254 to it. (If s is blank, returns s unchanged.)
255 """
256 split = s.split('\n')
257 last = split.pop()
258 final = []
259 for line in split:
260 final.append(line)
261 final.append(suffix)
262 final.append('\n')
263 if last:
264 final.append(last)
265 final.append(suffix)
266 return ''.join(final)
267
268
Larry Hastingsebdcb502013-11-23 14:54:00 -0800269def version_splitter(s):
270 """Splits a version string into a tuple of integers.
271
272 The following ASCII characters are allowed, and employ
273 the following conversions:
274 a -> -3
275 b -> -2
276 c -> -1
277 (This permits Python-style version strings such as "1.4b3".)
278 """
279 version = []
280 accumulator = []
281 def flush():
282 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800283 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800284 version.append(int(''.join(accumulator)))
285 accumulator.clear()
286
287 for c in s:
288 if c.isdigit():
289 accumulator.append(c)
290 elif c == '.':
291 flush()
292 elif c in 'abc':
293 flush()
294 version.append('abc'.index(c) - 3)
295 else:
296 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
297 flush()
298 return tuple(version)
299
300def version_comparitor(version1, version2):
301 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
302 for i, (a, b) in enumerate(iterator):
303 if a < b:
304 return -1
305 if a > b:
306 return 1
307 return 0
308
Larry Hastings31826802013-10-19 00:09:25 -0700309
310class CRenderData:
311 def __init__(self):
312
313 # The C statements to declare variables.
314 # Should be full lines with \n eol characters.
315 self.declarations = []
316
317 # The C statements required to initialize the variables before the parse call.
318 # Should be full lines with \n eol characters.
319 self.initializers = []
320
Larry Hastingsc2047262014-01-25 20:43:29 -0800321 # The C statements needed to dynamically modify the values
322 # parsed by the parse call, before calling the impl.
323 self.modifications = []
324
Larry Hastings31826802013-10-19 00:09:25 -0700325 # The entries for the "keywords" array for PyArg_ParseTuple.
326 # Should be individual strings representing the names.
327 self.keywords = []
328
329 # The "format units" for PyArg_ParseTuple.
330 # Should be individual strings that will get
331 self.format_units = []
332
333 # The varargs arguments for PyArg_ParseTuple.
334 self.parse_arguments = []
335
336 # The parameter declarations for the impl function.
337 self.impl_parameters = []
338
339 # The arguments to the impl function at the time it's called.
340 self.impl_arguments = []
341
342 # For return converters: the name of the variable that
343 # should receive the value returned by the impl.
344 self.return_value = "return_value"
345
346 # For return converters: the code to convert the return
347 # value from the parse function. This is also where
348 # you should check the _return_value for errors, and
349 # "goto exit" if there are any.
350 self.return_conversion = []
351
352 # The C statements required to clean up after the impl call.
353 self.cleanup = []
354
355
Larry Hastings581ee362014-01-28 05:00:08 -0800356class FormatCounterFormatter(string.Formatter):
357 """
358 This counts how many instances of each formatter
359 "replacement string" appear in the format string.
360
361 e.g. after evaluating "string {a}, {b}, {c}, {a}"
362 the counts dict would now look like
363 {'a': 2, 'b': 1, 'c': 1}
364 """
365 def __init__(self):
366 self.counts = collections.Counter()
367
368 def get_value(self, key, args, kwargs):
369 self.counts[key] += 1
370 return ''
371
Larry Hastings31826802013-10-19 00:09:25 -0700372class Language(metaclass=abc.ABCMeta):
373
374 start_line = ""
375 body_prefix = ""
376 stop_line = ""
377 checksum_line = ""
378
Larry Hastings7726ac92014-01-31 22:03:12 -0800379 def __init__(self, filename):
380 pass
381
Larry Hastings31826802013-10-19 00:09:25 -0700382 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800383 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700384 pass
385
Larry Hastings7726ac92014-01-31 22:03:12 -0800386 def parse_line(self, line):
387 pass
388
Larry Hastings31826802013-10-19 00:09:25 -0700389 def validate(self):
Larry Hastings581ee362014-01-28 05:00:08 -0800390 def assert_only_one(attr, *additional_fields):
391 """
392 Ensures that the string found at getattr(self, attr)
393 contains exactly one formatter replacement string for
394 each valid field. The list of valid fields is
395 ['dsl_name'] extended by additional_fields.
396
397 e.g.
398 self.fmt = "{dsl_name} {a} {b}"
399
400 # this passes
401 self.assert_only_one('fmt', 'a', 'b')
402
403 # this fails, the format string has a {b} in it
404 self.assert_only_one('fmt', 'a')
405
406 # this fails, the format string doesn't have a {c} in it
407 self.assert_only_one('fmt', 'a', 'b', 'c')
408
409 # this fails, the format string has two {a}s in it,
410 # it must contain exactly one
411 self.fmt2 = '{dsl_name} {a} {a}'
412 self.assert_only_one('fmt2', 'a')
413
414 """
415 fields = ['dsl_name']
416 fields.extend(additional_fields)
417 line = getattr(self, attr)
418 fcf = FormatCounterFormatter()
419 fcf.format(line)
420 def local_fail(should_be_there_but_isnt):
421 if should_be_there_but_isnt:
422 fail("{} {} must contain {{{}}} exactly once!".format(
423 self.__class__.__name__, attr, name))
424 else:
425 fail("{} {} must not contain {{{}}}!".format(
426 self.__class__.__name__, attr, name))
427
428 for name, count in fcf.counts.items():
429 if name in fields:
430 if count > 1:
431 local_fail(True)
432 else:
433 local_fail(False)
434 for name in fields:
435 if fcf.counts.get(name) != 1:
436 local_fail(True)
437
Larry Hastings31826802013-10-19 00:09:25 -0700438 assert_only_one('start_line')
439 assert_only_one('stop_line')
Larry Hastings31826802013-10-19 00:09:25 -0700440
Larry Hastings581ee362014-01-28 05:00:08 -0800441 field = "arguments" if "{arguments}" in self.checksum_line else "checksum"
442 assert_only_one('checksum_line', field)
Larry Hastings31826802013-10-19 00:09:25 -0700443
444
445
446class PythonLanguage(Language):
447
448 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800449 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700450 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800451 stop_line = "#[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800452 checksum_line = "#/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700453
454
455def permute_left_option_groups(l):
456 """
457 Given [1, 2, 3], should yield:
458 ()
459 (3,)
460 (2, 3)
461 (1, 2, 3)
462 """
463 yield tuple()
464 accumulator = []
465 for group in reversed(l):
466 accumulator = list(group) + accumulator
467 yield tuple(accumulator)
468
469
470def permute_right_option_groups(l):
471 """
472 Given [1, 2, 3], should yield:
473 ()
474 (1,)
475 (1, 2)
476 (1, 2, 3)
477 """
478 yield tuple()
479 accumulator = []
480 for group in l:
481 accumulator.extend(group)
482 yield tuple(accumulator)
483
484
485def permute_optional_groups(left, required, right):
486 """
487 Generator function that computes the set of acceptable
488 argument lists for the provided iterables of
489 argument groups. (Actually it generates a tuple of tuples.)
490
491 Algorithm: prefer left options over right options.
492
493 If required is empty, left must also be empty.
494 """
495 required = tuple(required)
496 result = []
497
498 if not required:
499 assert not left
500
501 accumulator = []
502 counts = set()
503 for r in permute_right_option_groups(right):
504 for l in permute_left_option_groups(left):
505 t = l + required + r
506 if len(t) in counts:
507 continue
508 counts.add(len(t))
509 accumulator.append(t)
510
511 accumulator.sort(key=len)
512 return tuple(accumulator)
513
514
Larry Hastings7726ac92014-01-31 22:03:12 -0800515def strip_leading_and_trailing_blank_lines(s):
516 lines = s.rstrip().split('\n')
517 while lines:
518 line = lines[0]
519 if line.strip():
520 break
521 del lines[0]
522 return '\n'.join(lines)
523
524@functools.lru_cache()
525def normalize_snippet(s, *, indent=0):
526 """
527 Reformats s:
528 * removes leading and trailing blank lines
529 * ensures that it does not end with a newline
530 * dedents so the first nonwhite character on any line is at column "indent"
531 """
532 s = strip_leading_and_trailing_blank_lines(s)
533 s = textwrap.dedent(s)
534 if indent:
535 s = textwrap.indent(s, ' ' * indent)
536 return s
537
538
Larry Hastings89964c42015-04-14 18:07:59 -0400539def wrap_declarations(text, length=78):
540 """
541 A simple-minded text wrapper for C function declarations.
542
543 It views a declaration line as looking like this:
544 xxxxxxxx(xxxxxxxxx,xxxxxxxxx)
545 If called with length=30, it would wrap that line into
546 xxxxxxxx(xxxxxxxxx,
547 xxxxxxxxx)
548 (If the declaration has zero or one parameters, this
549 function won't wrap it.)
550
551 If this doesn't work properly, it's probably better to
552 start from scratch with a more sophisticated algorithm,
553 rather than try and improve/debug this dumb little function.
554 """
555 lines = []
556 for line in text.split('\n'):
557 prefix, _, after_l_paren = line.partition('(')
558 if not after_l_paren:
559 lines.append(line)
560 continue
561 parameters, _, after_r_paren = after_l_paren.partition(')')
562 if not _:
563 lines.append(line)
564 continue
565 if ',' not in parameters:
566 lines.append(line)
567 continue
568 parameters = [x.strip() + ", " for x in parameters.split(',')]
569 prefix += "("
570 if len(prefix) < length:
571 spaces = " " * len(prefix)
572 else:
573 spaces = " " * 4
574
575 while parameters:
576 line = prefix
577 first = True
578 while parameters:
579 if (not first and
580 (len(line) + len(parameters[0]) > length)):
581 break
582 line += parameters.pop(0)
583 first = False
584 if not parameters:
585 line = line.rstrip(", ") + ")" + after_r_paren
586 lines.append(line.rstrip())
587 prefix = spaces
588 return "\n".join(lines)
589
590
Larry Hastings31826802013-10-19 00:09:25 -0700591class CLanguage(Language):
592
Larry Hastings61272b72014-01-07 12:41:53 -0800593 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700594 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800595 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700596 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800597 stop_line = "[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800598 checksum_line = "/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700599
Larry Hastings7726ac92014-01-31 22:03:12 -0800600 def __init__(self, filename):
601 super().__init__(filename)
602 self.cpp = cpp.Monitor(filename)
603 self.cpp.fail = fail
604
605 def parse_line(self, line):
606 self.cpp.writeline(line)
607
Larry Hastingsbebf7352014-01-17 17:47:17 -0800608 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700609 function = None
610 for o in signatures:
611 if isinstance(o, Function):
612 if function:
613 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
614 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800615 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700616
617 def docstring_for_c_string(self, f):
618 text, add, output = _text_accumulator()
619 # turn docstring into a properly quoted C string
620 for line in f.docstring.split('\n'):
621 add('"')
622 add(quoted_for_c_string(line))
623 add('\\n"\n')
624
Zachary Ware8ef887c2015-04-13 18:22:35 -0500625 if text[-2] == sig_end_marker:
626 # If we only have a signature, add the blank line that the
627 # __text_signature__ getter expects to be there.
628 add('"\\n"')
629 else:
630 text.pop()
631 add('"')
Larry Hastings31826802013-10-19 00:09:25 -0700632 return ''.join(text)
633
Larry Hastingsbebf7352014-01-17 17:47:17 -0800634 def output_templates(self, f):
635 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800636 assert parameters
637 assert isinstance(parameters[0].converter, self_converter)
638 del parameters[0]
Larry Hastingsbebf7352014-01-17 17:47:17 -0800639 converters = [p.converter for p in parameters]
640
641 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
642 default_return_converter = (not f.return_converter or
643 f.return_converter.type == 'PyObject *')
644
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300645 positional = parameters and parameters[-1].is_positional_only()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800646 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
647 first_optional = len(parameters)
648 for i, p in enumerate(parameters):
649 c = p.converter
650 if type(c) != object_converter:
651 break
652 if c.format_unit != 'O':
653 break
654 if p.default is not unspecified:
655 first_optional = min(first_optional, i)
656 else:
657 all_boring_objects = True
658
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800659 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
660
Larry Hastingsbebf7352014-01-17 17:47:17 -0800661 meth_o = (len(parameters) == 1 and
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300662 parameters[0].is_positional_only() and
Larry Hastingsbebf7352014-01-17 17:47:17 -0800663 not converters[0].is_optional() and
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800664 not new_or_init)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800665
Larry Hastings7726ac92014-01-31 22:03:12 -0800666 # we have to set these things before we're done:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800667 #
668 # docstring_prototype
669 # docstring_definition
670 # impl_prototype
671 # methoddef_define
672 # parser_prototype
673 # parser_definition
674 # impl_definition
Larry Hastings7726ac92014-01-31 22:03:12 -0800675 # cpp_if
676 # cpp_endif
677 # methoddef_ifndef
Larry Hastingsbebf7352014-01-17 17:47:17 -0800678
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800679 return_value_declaration = "PyObject *return_value = NULL;"
Larry Hastings31826802013-10-19 00:09:25 -0700680
Larry Hastings7726ac92014-01-31 22:03:12 -0800681 methoddef_define = normalize_snippet("""
682 #define {methoddef_name} \\
Serhiy Storchaka4a934d42018-11-27 11:27:36 +0200683 {{"{name}", {methoddef_cast}{c_basename}, {methoddef_flags}, {c_basename}__doc__}},
Larry Hastings7726ac92014-01-31 22:03:12 -0800684 """)
Larry Hastings5c661892014-01-24 06:17:25 -0800685 if new_or_init and not f.docstring:
686 docstring_prototype = docstring_definition = ''
687 else:
Larry Hastings7726ac92014-01-31 22:03:12 -0800688 docstring_prototype = normalize_snippet("""
689 PyDoc_VAR({c_basename}__doc__);
690 """)
691 docstring_definition = normalize_snippet("""
692 PyDoc_STRVAR({c_basename}__doc__,
693 {docstring});
694 """)
695 impl_definition = normalize_snippet("""
696 static {impl_return_type}
697 {c_basename}_impl({impl_parameters})
698 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800699 impl_prototype = parser_prototype = parser_definition = None
700
Larry Hastings7726ac92014-01-31 22:03:12 -0800701 parser_prototype_keyword = normalize_snippet("""
702 static PyObject *
703 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
704 """)
705
706 parser_prototype_varargs = normalize_snippet("""
707 static PyObject *
708 {c_basename}({self_type}{self_name}, PyObject *args)
709 """)
710
Victor Stinner0c8c3892017-01-17 01:42:54 +0100711 parser_prototype_fastcall = normalize_snippet("""
712 static PyObject *
Serhiy Storchakaa5552f02017-12-15 13:11:11 +0200713 {c_basename}({self_type}{self_name}, PyObject *const *args, Py_ssize_t nargs)
Serhiy Storchaka6969eaf2017-07-03 21:20:15 +0300714 """)
715
716 parser_prototype_fastcall_keywords = normalize_snippet("""
717 static PyObject *
Serhiy Storchakaa5552f02017-12-15 13:11:11 +0200718 {c_basename}({self_type}{self_name}, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
Victor Stinner0c8c3892017-01-17 01:42:54 +0100719 """)
720
Larry Hastings7726ac92014-01-31 22:03:12 -0800721 # parser_body_fields remembers the fields passed in to the
722 # previous call to parser_body. this is used for an awful hack.
Larry Hastingsc2047262014-01-25 20:43:29 -0800723 parser_body_fields = ()
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800724 def parser_body(prototype, *fields):
725 nonlocal parser_body_fields
726 add, output = text_accumulator()
727 add(prototype)
728 parser_body_fields = fields
Larry Hastings7726ac92014-01-31 22:03:12 -0800729
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800730 fields = list(fields)
Larry Hastings7726ac92014-01-31 22:03:12 -0800731 fields.insert(0, normalize_snippet("""
732 {{
733 {return_value_declaration}
734 {declarations}
735 {initializers}
736 """) + "\n")
737 # just imagine--your code is here in the middle
738 fields.append(normalize_snippet("""
739 {modifications}
740 {return_value} = {c_basename}_impl({impl_arguments});
741 {return_conversion}
742
743 {exit_label}
744 {cleanup}
745 return return_value;
746 }}
747 """))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800748 for field in fields:
749 add('\n')
Larry Hastings7726ac92014-01-31 22:03:12 -0800750 add(field)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800751 return output()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800752
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800753 def insert_keywords(s):
Serhiy Storchaka9171a8b2016-08-14 10:52:18 +0300754 return linear_format(s, declarations=
755 'static const char * const _keywords[] = {{{keywords}, NULL}};\n'
756 'static _PyArg_Parser _parser = {{"{format_units}:{name}", _keywords, 0}};\n'
757 '{declarations}')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800758
759 if not parameters:
760 # no parameters, METH_NOARGS
761
762 flags = "METH_NOARGS"
763
Larry Hastings7726ac92014-01-31 22:03:12 -0800764 parser_prototype = normalize_snippet("""
765 static PyObject *
766 {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
767 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800768 parser_definition = parser_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800769
770 if default_return_converter:
Larry Hastings7726ac92014-01-31 22:03:12 -0800771 parser_definition = parser_prototype + '\n' + normalize_snippet("""
772 {{
773 return {c_basename}_impl({impl_arguments});
774 }}
775 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800776 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800777 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700778
Larry Hastingsbebf7352014-01-17 17:47:17 -0800779 elif meth_o:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800780 flags = "METH_O"
Larry Hastings7726ac92014-01-31 22:03:12 -0800781
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300782 if (isinstance(converters[0], object_converter) and
783 converters[0].format_unit == 'O'):
784 meth_o_prototype = normalize_snippet("""
785 static PyObject *
786 {c_basename}({impl_parameters})
787 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800788
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300789 if default_return_converter:
790 # maps perfectly to METH_O, doesn't need a return converter.
791 # so we skip making a parse function
792 # and call directly into the impl function.
793 impl_prototype = parser_prototype = parser_definition = ''
794 impl_definition = meth_o_prototype
795 else:
796 # SLIGHT HACK
797 # use impl_parameters for the parser here!
798 parser_prototype = meth_o_prototype
799 parser_definition = parser_body(parser_prototype)
800
Larry Hastingsbebf7352014-01-17 17:47:17 -0800801 else:
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300802 argname = 'arg'
803 if parameters[0].name == argname:
804 argname += '_'
805 parser_prototype = normalize_snippet("""
806 static PyObject *
807 {c_basename}({self_type}{self_name}, PyObject *%s)
808 """ % argname)
809
810 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300811 if (!PyArg_Parse(%s, "{format_units}:{name}", {parse_arguments})) {{
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300812 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300813 }}
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300814 """ % argname, indent=4))
Larry Hastings31826802013-10-19 00:09:25 -0700815
Larry Hastingsbebf7352014-01-17 17:47:17 -0800816 elif has_option_groups:
817 # positional parameters with option groups
818 # (we have to generate lots of PyArg_ParseTuple calls
819 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700820
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800821 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800822 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700823
Larry Hastings7726ac92014-01-31 22:03:12 -0800824 parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')
Larry Hastings31826802013-10-19 00:09:25 -0700825
Larry Hastingsbebf7352014-01-17 17:47:17 -0800826 elif positional and all_boring_objects:
827 # positional-only, but no option groups,
828 # and nothing but normal objects:
829 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700830
Victor Stinner093119e2017-01-17 02:35:41 +0100831 if not new_or_init:
832 flags = "METH_FASTCALL"
833 parser_prototype = parser_prototype_fastcall
Larry Hastings31826802013-10-19 00:09:25 -0700834
Victor Stinner093119e2017-01-17 02:35:41 +0100835 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Sylvain74453812017-06-10 06:51:48 +0200836 if (!_PyArg_UnpackStack(args, nargs, "{name}",
837 {unpack_min}, {unpack_max},
838 {parse_arguments})) {{
Victor Stinner093119e2017-01-17 02:35:41 +0100839 goto exit;
840 }}
841 """, indent=4))
842 else:
843 flags = "METH_VARARGS"
844 parser_prototype = parser_prototype_varargs
845
846 parser_definition = parser_body(parser_prototype, normalize_snippet("""
847 if (!PyArg_UnpackTuple(args, "{name}",
848 {unpack_min}, {unpack_max},
849 {parse_arguments})) {{
850 goto exit;
851 }}
852 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800853
854 elif positional:
Victor Stinner0c8c3892017-01-17 01:42:54 +0100855 if not new_or_init:
856 # positional-only, but no option groups
857 # we only need one call to _PyArg_ParseStack
Larry Hastingsbebf7352014-01-17 17:47:17 -0800858
Victor Stinner0c8c3892017-01-17 01:42:54 +0100859 flags = "METH_FASTCALL"
860 parser_prototype = parser_prototype_fastcall
Larry Hastingsbebf7352014-01-17 17:47:17 -0800861
Victor Stinner0c8c3892017-01-17 01:42:54 +0100862 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Sylvain74453812017-06-10 06:51:48 +0200863 if (!_PyArg_ParseStack(args, nargs, "{format_units}:{name}",
864 {parse_arguments})) {{
Victor Stinner0c8c3892017-01-17 01:42:54 +0100865 goto exit;
866 }}
867 """, indent=4))
868 else:
869 # positional-only, but no option groups
870 # we only need one call to PyArg_ParseTuple
871
872 flags = "METH_VARARGS"
873 parser_prototype = parser_prototype_varargs
874
875 parser_definition = parser_body(parser_prototype, normalize_snippet("""
876 if (!PyArg_ParseTuple(args, "{format_units}:{name}",
877 {parse_arguments})) {{
878 goto exit;
879 }}
880 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800881
Victor Stinnerf0ccbbb2016-09-09 17:40:38 -0700882 elif not new_or_init:
Serhiy Storchaka6969eaf2017-07-03 21:20:15 +0300883 flags = "METH_FASTCALL|METH_KEYWORDS"
Victor Stinnerf0ccbbb2016-09-09 17:40:38 -0700884
Serhiy Storchaka6969eaf2017-07-03 21:20:15 +0300885 parser_prototype = parser_prototype_fastcall_keywords
Victor Stinnerf0ccbbb2016-09-09 17:40:38 -0700886
887 body = normalize_snippet("""
Victor Stinner3e1fad62017-01-17 01:29:01 +0100888 if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
Victor Stinnerf0ccbbb2016-09-09 17:40:38 -0700889 {parse_arguments})) {{
890 goto exit;
891 }}
892 """, indent=4)
893 parser_definition = parser_body(parser_prototype, body)
894 parser_definition = insert_keywords(parser_definition)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800895 else:
896 # positional-or-keyword arguments
897 flags = "METH_VARARGS|METH_KEYWORDS"
898
Larry Hastings7726ac92014-01-31 22:03:12 -0800899 parser_prototype = parser_prototype_keyword
Larry Hastingsbebf7352014-01-17 17:47:17 -0800900
Larry Hastings7726ac92014-01-31 22:03:12 -0800901 body = normalize_snippet("""
Serhiy Storchaka9171a8b2016-08-14 10:52:18 +0300902 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300903 {parse_arguments})) {{
Larry Hastings7726ac92014-01-31 22:03:12 -0800904 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300905 }}
906 """, indent=4)
Serhiy Storchaka9171a8b2016-08-14 10:52:18 +0300907 parser_definition = parser_body(parser_prototype, body)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800908 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700909
Larry Hastings31826802013-10-19 00:09:25 -0700910
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800911 if new_or_init:
912 methoddef_define = ''
913
914 if f.kind == METHOD_NEW:
Larry Hastings7726ac92014-01-31 22:03:12 -0800915 parser_prototype = parser_prototype_keyword
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800916 else:
917 return_value_declaration = "int return_value = -1;"
Larry Hastings7726ac92014-01-31 22:03:12 -0800918 parser_prototype = normalize_snippet("""
919 static int
920 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
921 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800922
923 fields = list(parser_body_fields)
924 parses_positional = 'METH_NOARGS' not in flags
925 parses_keywords = 'METH_KEYWORDS' in flags
926 if parses_keywords:
927 assert parses_positional
928
929 if not parses_keywords:
Larry Hastings7726ac92014-01-31 22:03:12 -0800930 fields.insert(0, normalize_snippet("""
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300931 if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) {{
Larry Hastings7726ac92014-01-31 22:03:12 -0800932 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300933 }}
Larry Hastings7726ac92014-01-31 22:03:12 -0800934 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800935 if not parses_positional:
Larry Hastings7726ac92014-01-31 22:03:12 -0800936 fields.insert(0, normalize_snippet("""
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300937 if ({self_type_check}!_PyArg_NoPositional("{name}", args)) {{
Larry Hastings7726ac92014-01-31 22:03:12 -0800938 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300939 }}
Larry Hastings7726ac92014-01-31 22:03:12 -0800940 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800941
942 parser_definition = parser_body(parser_prototype, *fields)
943 if parses_keywords:
944 parser_definition = insert_keywords(parser_definition)
945
Larry Hastings31826802013-10-19 00:09:25 -0700946
Serhiy Storchaka4a934d42018-11-27 11:27:36 +0200947 if flags in ('METH_NOARGS', 'METH_O', 'METH_VARARGS'):
948 methoddef_cast = "(PyCFunction)"
949 else:
950 methoddef_cast = "(PyCFunction)(void(*)(void))"
951
Larry Hastingsbebf7352014-01-17 17:47:17 -0800952 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800953 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700954
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800955 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Serhiy Storchaka4a934d42018-11-27 11:27:36 +0200956 methoddef_define = methoddef_define.replace('{methoddef_cast}', methoddef_cast)
Larry Hastings31826802013-10-19 00:09:25 -0700957
Larry Hastings7726ac92014-01-31 22:03:12 -0800958 methoddef_ifndef = ''
959 conditional = self.cpp.condition()
960 if not conditional:
961 cpp_if = cpp_endif = ''
962 else:
963 cpp_if = "#if " + conditional
964 cpp_endif = "#endif /* " + conditional + " */"
965
Tal Einat4f574092017-11-03 11:09:00 +0200966 if methoddef_define and f.full_name not in clinic.ifndef_symbols:
967 clinic.ifndef_symbols.add(f.full_name)
Larry Hastings7726ac92014-01-31 22:03:12 -0800968 methoddef_ifndef = normalize_snippet("""
969 #ifndef {methoddef_name}
970 #define {methoddef_name}
971 #endif /* !defined({methoddef_name}) */
972 """)
973
974
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800975 # add ';' to the end of parser_prototype and impl_prototype
976 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800977 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800978 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800979 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800980 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700981
Larry Hastingsbebf7352014-01-17 17:47:17 -0800982 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800983 impl_prototype = impl_definition
984 if impl_prototype:
985 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700986
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800987 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800988
989 d = {
990 "docstring_prototype" : docstring_prototype,
991 "docstring_definition" : docstring_definition,
992 "impl_prototype" : impl_prototype,
993 "methoddef_define" : methoddef_define,
994 "parser_prototype" : parser_prototype,
995 "parser_definition" : parser_definition,
996 "impl_definition" : impl_definition,
Larry Hastings7726ac92014-01-31 22:03:12 -0800997 "cpp_if" : cpp_if,
998 "cpp_endif" : cpp_endif,
999 "methoddef_ifndef" : methoddef_ifndef,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001000 }
1001
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001002 # make sure we didn't forget to assign something,
1003 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -08001004 d2 = {}
1005 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001006 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001007 if value:
1008 value = '\n' + value + '\n'
1009 d2[name] = value
1010 return d2
Larry Hastings31826802013-10-19 00:09:25 -07001011
1012 @staticmethod
1013 def group_to_variable_name(group):
1014 adjective = "left_" if group < 0 else "right_"
1015 return "group_" + adjective + str(abs(group))
1016
1017 def render_option_group_parsing(self, f, template_dict):
1018 # positional only, grouped, optional arguments!
1019 # can be optional on the left or right.
1020 # here's an example:
1021 #
1022 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
1023 #
1024 # Here group D are required, and all other groups are optional.
1025 # (Group D's "group" is actually None.)
1026 # We can figure out which sets of arguments we have based on
1027 # how many arguments are in the tuple.
1028 #
1029 # Note that you need to count up on both sides. For example,
1030 # you could have groups C+D, or C+D+E, or C+D+E+F.
1031 #
1032 # What if the number of arguments leads us to an ambiguous result?
1033 # Clinic prefers groups on the left. So in the above example,
1034 # five arguments would map to B+C, not C+D.
1035
1036 add, output = text_accumulator()
1037 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -08001038 if isinstance(parameters[0].converter, self_converter):
1039 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -07001040
1041 groups = []
1042 group = None
1043 left = []
1044 right = []
1045 required = []
1046 last = unspecified
1047
1048 for p in parameters:
1049 group_id = p.group
1050 if group_id != last:
1051 last = group_id
1052 group = []
1053 if group_id < 0:
1054 left.append(group)
1055 elif group_id == 0:
1056 group = required
1057 else:
1058 right.append(group)
1059 group.append(p)
1060
1061 count_min = sys.maxsize
1062 count_max = -1
1063
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03001064 add("switch (PyTuple_GET_SIZE(args)) {\n")
Larry Hastings31826802013-10-19 00:09:25 -07001065 for subset in permute_optional_groups(left, required, right):
1066 count = len(subset)
1067 count_min = min(count_min, count)
1068 count_max = max(count_max, count)
1069
Larry Hastings583baa82014-01-12 08:49:30 -08001070 if count == 0:
1071 add(""" case 0:
1072 break;
1073""")
1074 continue
1075
Larry Hastings31826802013-10-19 00:09:25 -07001076 group_ids = {p.group for p in subset} # eliminate duplicates
1077 d = {}
1078 d['count'] = count
1079 d['name'] = f.name
Larry Hastings31826802013-10-19 00:09:25 -07001080 d['format_units'] = "".join(p.converter.format_unit for p in subset)
1081
1082 parse_arguments = []
1083 for p in subset:
1084 p.converter.parse_argument(parse_arguments)
1085 d['parse_arguments'] = ", ".join(parse_arguments)
1086
1087 group_ids.discard(0)
1088 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
1089 lines = "\n".join(lines)
1090
1091 s = """
1092 case {count}:
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03001093 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments})) {{
Larry Hastings46258262014-01-22 03:05:49 -08001094 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03001095 }}
Larry Hastings31826802013-10-19 00:09:25 -07001096 {group_booleans}
1097 break;
1098"""[1:]
1099 s = linear_format(s, group_booleans=lines)
1100 s = s.format_map(d)
1101 add(s)
1102
1103 add(" default:\n")
1104 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
1105 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -08001106 add(' goto exit;\n')
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03001107 add("}")
1108 template_dict['option_group_parsing'] = format_escape(output())
Larry Hastings31826802013-10-19 00:09:25 -07001109
Larry Hastingsbebf7352014-01-17 17:47:17 -08001110 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -07001111 if not f:
1112 return ""
1113
1114 add, output = text_accumulator()
1115 data = CRenderData()
1116
Larry Hastings7726ac92014-01-31 22:03:12 -08001117 assert f.parameters, "We should always have a 'self' at this point!"
1118 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07001119 converters = [p.converter for p in parameters]
1120
Larry Hastings5c661892014-01-24 06:17:25 -08001121 templates = self.output_templates(f)
1122
1123 f_self = parameters[0]
1124 selfless = parameters[1:]
1125 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
1126
1127 last_group = 0
1128 first_optional = len(selfless)
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03001129 positional = selfless and selfless[-1].is_positional_only()
Larry Hastings5c661892014-01-24 06:17:25 -08001130 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
1131 default_return_converter = (not f.return_converter or
1132 f.return_converter.type == 'PyObject *')
1133 has_option_groups = False
1134
1135 # offset i by -1 because first_optional needs to ignore self
1136 for i, p in enumerate(parameters, -1):
1137 c = p.converter
1138
1139 if (i != -1) and (p.default is not unspecified):
1140 first_optional = min(first_optional, i)
1141
1142 # insert group variable
1143 group = p.group
1144 if last_group != group:
1145 last_group = group
1146 if group:
1147 group_name = self.group_to_variable_name(group)
1148 data.impl_arguments.append(group_name)
1149 data.declarations.append("int " + group_name + " = 0;")
1150 data.impl_parameters.append("int " + group_name)
1151 has_option_groups = True
1152
1153 c.render(p, data)
1154
1155 if has_option_groups and (not positional):
1156 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
1157
1158 # HACK
1159 # when we're METH_O, but have a custom return converter,
1160 # we use "impl_parameters" for the parsing function
1161 # because that works better. but that means we must
Berker Peksagf23530f2014-10-19 18:04:38 +03001162 # suppress actually declaring the impl's parameters
Larry Hastings5c661892014-01-24 06:17:25 -08001163 # as variables in the parsing function. but since it's
1164 # METH_O, we have exactly one anyway, so we know exactly
1165 # where it is.
1166 if ("METH_O" in templates['methoddef_define'] and
Serhiy Storchaka92e8af62015-04-04 00:12:11 +03001167 '{impl_parameters}' in templates['parser_prototype']):
Larry Hastings5c661892014-01-24 06:17:25 -08001168 data.declarations.pop(0)
1169
Larry Hastings31826802013-10-19 00:09:25 -07001170 template_dict = {}
1171
1172 full_name = f.full_name
1173 template_dict['full_name'] = full_name
1174
Larry Hastings5c661892014-01-24 06:17:25 -08001175 if new_or_init:
1176 name = f.cls.name
1177 else:
1178 name = f.name
1179
Larry Hastings31826802013-10-19 00:09:25 -07001180 template_dict['name'] = name
1181
Larry Hastings8666e652014-01-12 14:12:59 -08001182 if f.c_basename:
1183 c_basename = f.c_basename
1184 else:
1185 fields = full_name.split(".")
1186 if fields[-1] == '__new__':
1187 fields.pop()
1188 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001189
Larry Hastings31826802013-10-19 00:09:25 -07001190 template_dict['c_basename'] = c_basename
1191
1192 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1193 template_dict['methoddef_name'] = methoddef_name
1194
1195 template_dict['docstring'] = self.docstring_for_c_string(f)
1196
Larry Hastingsc2047262014-01-25 20:43:29 -08001197 template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
Larry Hastings5c661892014-01-24 06:17:25 -08001198 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001199
Larry Hastings31826802013-10-19 00:09:25 -07001200 f.return_converter.render(f, data)
1201 template_dict['impl_return_type'] = f.return_converter.type
1202
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03001203 template_dict['declarations'] = format_escape("\n".join(data.declarations))
Larry Hastings31826802013-10-19 00:09:25 -07001204 template_dict['initializers'] = "\n\n".join(data.initializers)
Larry Hastingsc2047262014-01-25 20:43:29 -08001205 template_dict['modifications'] = '\n\n'.join(data.modifications)
Larry Hastings31826802013-10-19 00:09:25 -07001206 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1207 template_dict['format_units'] = ''.join(data.format_units)
1208 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1209 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1210 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03001211 template_dict['return_conversion'] = format_escape("".join(data.return_conversion).rstrip())
1212 template_dict['cleanup'] = format_escape("".join(data.cleanup))
Larry Hastings31826802013-10-19 00:09:25 -07001213 template_dict['return_value'] = data.return_value
1214
Larry Hastings5c661892014-01-24 06:17:25 -08001215 # used by unpack tuple code generator
1216 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1217 unpack_min = first_optional
1218 unpack_max = len(selfless)
1219 template_dict['unpack_min'] = str(unpack_min)
1220 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001221
Larry Hastingsbebf7352014-01-17 17:47:17 -08001222 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001223 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001224
Larry Hastings0759f842015-04-03 13:09:02 -07001225 # buffers, not destination
1226 for name, destination in clinic.destination_buffers.items():
Larry Hastingsbebf7352014-01-17 17:47:17 -08001227 template = templates[name]
1228 if has_option_groups:
1229 template = linear_format(template,
1230 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001231 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001232 declarations=template_dict['declarations'],
1233 return_conversion=template_dict['return_conversion'],
1234 initializers=template_dict['initializers'],
Larry Hastingsc2047262014-01-25 20:43:29 -08001235 modifications=template_dict['modifications'],
Larry Hastingsbebf7352014-01-17 17:47:17 -08001236 cleanup=template_dict['cleanup'],
1237 )
Larry Hastings31826802013-10-19 00:09:25 -07001238
Larry Hastingsbebf7352014-01-17 17:47:17 -08001239 # Only generate the "exit:" label
1240 # if we have any gotos
1241 need_exit_label = "goto exit;" in template
1242 template = linear_format(template,
1243 exit_label="exit:" if need_exit_label else ''
1244 )
Larry Hastings31826802013-10-19 00:09:25 -07001245
Larry Hastingsbebf7352014-01-17 17:47:17 -08001246 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001247
Larry Hastings89964c42015-04-14 18:07:59 -04001248 # mild hack:
1249 # reflow long impl declarations
1250 if name in {"impl_prototype", "impl_definition"}:
1251 s = wrap_declarations(s)
1252
Larry Hastingsbebf7352014-01-17 17:47:17 -08001253 if clinic.line_prefix:
1254 s = indent_all_lines(s, clinic.line_prefix)
1255 if clinic.line_suffix:
1256 s = suffix_all_lines(s, clinic.line_suffix)
1257
1258 destination.append(s)
1259
1260 return clinic.get_destination('block').dump()
1261
Larry Hastings31826802013-10-19 00:09:25 -07001262
1263
Larry Hastings5c661892014-01-24 06:17:25 -08001264
Larry Hastings31826802013-10-19 00:09:25 -07001265@contextlib.contextmanager
1266def OverrideStdioWith(stdout):
1267 saved_stdout = sys.stdout
1268 sys.stdout = stdout
1269 try:
1270 yield
1271 finally:
1272 assert sys.stdout is stdout
1273 sys.stdout = saved_stdout
1274
1275
Larry Hastings2623c8c2014-02-08 22:15:29 -08001276def create_regex(before, after, word=True, whole_line=True):
Larry Hastings31826802013-10-19 00:09:25 -07001277 """Create an re object for matching marker lines."""
R David Murray44b548d2016-09-08 13:59:53 -04001278 group_re = r"\w+" if word else ".+"
Larry Hastings2623c8c2014-02-08 22:15:29 -08001279 pattern = r'{}({}){}'
1280 if whole_line:
1281 pattern = '^' + pattern + '$'
Larry Hastings581ee362014-01-28 05:00:08 -08001282 pattern = pattern.format(re.escape(before), group_re, re.escape(after))
1283 return re.compile(pattern)
Larry Hastings31826802013-10-19 00:09:25 -07001284
1285
1286class Block:
1287 r"""
1288 Represents a single block of text embedded in
1289 another file. If dsl_name is None, the block represents
1290 verbatim text, raw original text from the file, in
1291 which case "input" will be the only non-false member.
1292 If dsl_name is not None, the block represents a Clinic
1293 block.
1294
1295 input is always str, with embedded \n characters.
1296 input represents the original text from the file;
1297 if it's a Clinic block, it is the original text with
1298 the body_prefix and redundant leading whitespace removed.
1299
1300 dsl_name is either str or None. If str, it's the text
1301 found on the start line of the block between the square
1302 brackets.
1303
1304 signatures is either list or None. If it's a list,
1305 it may only contain clinic.Module, clinic.Class, and
1306 clinic.Function objects. At the moment it should
1307 contain at most one of each.
1308
1309 output is either str or None. If str, it's the output
1310 from this block, with embedded '\n' characters.
1311
1312 indent is either str or None. It's the leading whitespace
1313 that was found on every line of input. (If body_prefix is
1314 not empty, this is the indent *after* removing the
1315 body_prefix.)
1316
1317 preindent is either str or None. It's the whitespace that
1318 was found in front of every line of input *before* the
1319 "body_prefix" (see the Language object). If body_prefix
1320 is empty, preindent must always be empty too.
1321
1322 To illustrate indent and preindent: Assume that '_'
1323 represents whitespace. If the block processed was in a
1324 Python file, and looked like this:
1325 ____#/*[python]
1326 ____#__for a in range(20):
1327 ____#____print(a)
1328 ____#[python]*/
1329 "preindent" would be "____" and "indent" would be "__".
1330
1331 """
1332 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1333 assert isinstance(input, str)
1334 self.input = input
1335 self.dsl_name = dsl_name
1336 self.signatures = signatures or []
1337 self.output = output
1338 self.indent = indent
1339 self.preindent = preindent
1340
Larry Hastings581ee362014-01-28 05:00:08 -08001341 def __repr__(self):
1342 dsl_name = self.dsl_name or "text"
1343 def summarize(s):
1344 s = repr(s)
1345 if len(s) > 30:
1346 return s[:26] + "..." + s[0]
1347 return s
1348 return "".join((
1349 "<Block ", dsl_name, " input=", summarize(self.input), " output=", summarize(self.output), ">"))
1350
Larry Hastings31826802013-10-19 00:09:25 -07001351
1352class BlockParser:
1353 """
1354 Block-oriented parser for Argument Clinic.
1355 Iterator, yields Block objects.
1356 """
1357
1358 def __init__(self, input, language, *, verify=True):
1359 """
1360 "input" should be a str object
1361 with embedded \n characters.
1362
1363 "language" should be a Language object.
1364 """
1365 language.validate()
1366
1367 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1368 self.block_start_line_number = self.line_number = 0
1369
1370 self.language = language
1371 before, _, after = language.start_line.partition('{dsl_name}')
1372 assert _ == '{dsl_name}'
Larry Hastings2623c8c2014-02-08 22:15:29 -08001373 self.find_start_re = create_regex(before, after, whole_line=False)
Larry Hastings31826802013-10-19 00:09:25 -07001374 self.start_re = create_regex(before, after)
1375 self.verify = verify
1376 self.last_checksum_re = None
1377 self.last_dsl_name = None
1378 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001379 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001380
1381 def __iter__(self):
1382 return self
1383
1384 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001385 while True:
1386 if not self.input:
1387 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001388
Larry Hastingsbebf7352014-01-17 17:47:17 -08001389 if self.dsl_name:
1390 return_value = self.parse_clinic_block(self.dsl_name)
1391 self.dsl_name = None
1392 self.first_block = False
1393 return return_value
1394 block = self.parse_verbatim_block()
1395 if self.first_block and not block.input:
1396 continue
1397 self.first_block = False
1398 return block
1399
Larry Hastings31826802013-10-19 00:09:25 -07001400
1401 def is_start_line(self, line):
1402 match = self.start_re.match(line.lstrip())
1403 return match.group(1) if match else None
1404
Larry Hastingse1b82532014-07-27 16:22:20 +02001405 def _line(self, lookahead=False):
Larry Hastings31826802013-10-19 00:09:25 -07001406 self.line_number += 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001407 line = self.input.pop()
Larry Hastingse1b82532014-07-27 16:22:20 +02001408 if not lookahead:
1409 self.language.parse_line(line)
Larry Hastings7726ac92014-01-31 22:03:12 -08001410 return line
Larry Hastings31826802013-10-19 00:09:25 -07001411
1412 def parse_verbatim_block(self):
1413 add, output = text_accumulator()
1414 self.block_start_line_number = self.line_number
1415
1416 while self.input:
1417 line = self._line()
1418 dsl_name = self.is_start_line(line)
1419 if dsl_name:
1420 self.dsl_name = dsl_name
1421 break
1422 add(line)
1423
1424 return Block(output())
1425
1426 def parse_clinic_block(self, dsl_name):
1427 input_add, input_output = text_accumulator()
1428 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001429 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001430 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1431
Larry Hastings90261132014-01-07 12:21:08 -08001432 def is_stop_line(line):
1433 # make sure to recognize stop line even if it
1434 # doesn't end with EOL (it could be the very end of the file)
1435 if not line.startswith(stop_line):
1436 return False
1437 remainder = line[len(stop_line):]
1438 return (not remainder) or remainder.isspace()
1439
Larry Hastings31826802013-10-19 00:09:25 -07001440 # consume body of program
1441 while self.input:
1442 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001443 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001444 break
1445 if body_prefix:
1446 line = line.lstrip()
1447 assert line.startswith(body_prefix)
1448 line = line[len(body_prefix):]
1449 input_add(line)
1450
1451 # consume output and checksum line, if present.
1452 if self.last_dsl_name == dsl_name:
1453 checksum_re = self.last_checksum_re
1454 else:
Larry Hastings581ee362014-01-28 05:00:08 -08001455 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, arguments='{arguments}').partition('{arguments}')
1456 assert _ == '{arguments}'
1457 checksum_re = create_regex(before, after, word=False)
Larry Hastings31826802013-10-19 00:09:25 -07001458 self.last_dsl_name = dsl_name
1459 self.last_checksum_re = checksum_re
1460
1461 # scan forward for checksum line
1462 output_add, output_output = text_accumulator()
Larry Hastings581ee362014-01-28 05:00:08 -08001463 arguments = None
Larry Hastings31826802013-10-19 00:09:25 -07001464 while self.input:
Larry Hastingse1b82532014-07-27 16:22:20 +02001465 line = self._line(lookahead=True)
Larry Hastings31826802013-10-19 00:09:25 -07001466 match = checksum_re.match(line.lstrip())
Larry Hastings581ee362014-01-28 05:00:08 -08001467 arguments = match.group(1) if match else None
1468 if arguments:
Larry Hastings31826802013-10-19 00:09:25 -07001469 break
1470 output_add(line)
1471 if self.is_start_line(line):
1472 break
1473
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001474 output = output_output()
Larry Hastings581ee362014-01-28 05:00:08 -08001475 if arguments:
1476 d = {}
1477 for field in shlex.split(arguments):
1478 name, equals, value = field.partition('=')
1479 if not equals:
1480 fail("Mangled Argument Clinic marker line: {!r}".format(line))
1481 d[name.strip()] = value.strip()
1482
Larry Hastings31826802013-10-19 00:09:25 -07001483 if self.verify:
Larry Hastings581ee362014-01-28 05:00:08 -08001484 if 'input' in d:
1485 checksum = d['output']
1486 input_checksum = d['input']
1487 else:
1488 checksum = d['checksum']
1489 input_checksum = None
1490
1491 computed = compute_checksum(output, len(checksum))
Larry Hastings31826802013-10-19 00:09:25 -07001492 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001493 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1494 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001495 "the end marker,\n"
1496 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001497 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001498 else:
1499 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001500 output_lines = output.splitlines(keepends=True)
1501 self.line_number -= len(output_lines)
1502 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001503 output = None
1504
1505 return Block(input_output(), dsl_name, output=output)
1506
1507
1508class BlockPrinter:
1509
1510 def __init__(self, language, f=None):
1511 self.language = language
1512 self.f = f or io.StringIO()
1513
1514 def print_block(self, block):
1515 input = block.input
1516 output = block.output
1517 dsl_name = block.dsl_name
1518 write = self.f.write
1519
Larry Hastings31826802013-10-19 00:09:25 -07001520 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1521
1522 if not dsl_name:
1523 write(input)
1524 return
1525
1526 write(self.language.start_line.format(dsl_name=dsl_name))
1527 write("\n")
1528
1529 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1530 if not body_prefix:
1531 write(input)
1532 else:
1533 for line in input.split('\n'):
1534 write(body_prefix)
1535 write(line)
1536 write("\n")
1537
1538 write(self.language.stop_line.format(dsl_name=dsl_name))
1539 write("\n")
1540
Larry Hastings581ee362014-01-28 05:00:08 -08001541 input = ''.join(block.input)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001542 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001543 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001544 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001545 output += '\n'
1546 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001547
Larry Hastings581ee362014-01-28 05:00:08 -08001548 arguments="output={} input={}".format(compute_checksum(output, 16), compute_checksum(input, 16))
1549 write(self.language.checksum_line.format(dsl_name=dsl_name, arguments=arguments))
Larry Hastings31826802013-10-19 00:09:25 -07001550 write("\n")
1551
Larry Hastingsbebf7352014-01-17 17:47:17 -08001552 def write(self, text):
1553 self.f.write(text)
1554
1555
Larry Hastings0759f842015-04-03 13:09:02 -07001556class BufferSeries:
1557 """
1558 Behaves like a "defaultlist".
1559 When you ask for an index that doesn't exist yet,
1560 the object grows the list until that item exists.
1561 So o[n] will always work.
1562
1563 Supports negative indices for actual items.
1564 e.g. o[-1] is an element immediately preceding o[0].
1565 """
1566
1567 def __init__(self):
1568 self._start = 0
1569 self._array = []
1570 self._constructor = _text_accumulator
1571
1572 def __getitem__(self, i):
1573 i -= self._start
1574 if i < 0:
1575 self._start += i
1576 prefix = [self._constructor() for x in range(-i)]
1577 self._array = prefix + self._array
1578 i = 0
1579 while i >= len(self._array):
1580 self._array.append(self._constructor())
1581 return self._array[i]
1582
1583 def clear(self):
1584 for ta in self._array:
1585 ta._text.clear()
1586
1587 def dump(self):
1588 texts = [ta.output() for ta in self._array]
1589 return "".join(texts)
1590
1591
Larry Hastingsbebf7352014-01-17 17:47:17 -08001592class Destination:
1593 def __init__(self, name, type, clinic, *args):
1594 self.name = name
1595 self.type = type
1596 self.clinic = clinic
Larry Hastings0759f842015-04-03 13:09:02 -07001597 valid_types = ('buffer', 'file', 'suppress')
Larry Hastingsbebf7352014-01-17 17:47:17 -08001598 if type not in valid_types:
1599 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1600 extra_arguments = 1 if type == "file" else 0
1601 if len(args) < extra_arguments:
1602 fail("Not enough arguments for destination " + name + " new " + type)
1603 if len(args) > extra_arguments:
1604 fail("Too many arguments for destination " + name + " new " + type)
1605 if type =='file':
1606 d = {}
Larry Hastingsc2047262014-01-25 20:43:29 -08001607 filename = clinic.filename
1608 d['path'] = filename
1609 dirname, basename = os.path.split(filename)
1610 if not dirname:
1611 dirname = '.'
1612 d['dirname'] = dirname
1613 d['basename'] = basename
1614 d['basename_root'], d['basename_extension'] = os.path.splitext(filename)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001615 self.filename = args[0].format_map(d)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001616
Larry Hastings0759f842015-04-03 13:09:02 -07001617 self.buffers = BufferSeries()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001618
1619 def __repr__(self):
1620 if self.type == 'file':
1621 file_repr = " " + repr(self.filename)
1622 else:
1623 file_repr = ''
1624 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1625
1626 def clear(self):
1627 if self.type != 'buffer':
1628 fail("Can't clear destination" + self.name + " , it's not of type buffer")
Larry Hastings0759f842015-04-03 13:09:02 -07001629 self.buffers.clear()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001630
1631 def dump(self):
Larry Hastings0759f842015-04-03 13:09:02 -07001632 return self.buffers.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001633
Larry Hastings31826802013-10-19 00:09:25 -07001634
1635# maps strings to Language objects.
1636# "languages" maps the name of the language ("C", "Python").
1637# "extensions" maps the file extension ("c", "py").
1638languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001639extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1640extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001641
1642
1643# maps strings to callables.
1644# these callables must be of the form:
1645# def foo(name, default, *, ...)
1646# The callable may have any number of keyword-only parameters.
1647# The callable must return a CConverter object.
1648# The callable should not call builtins.print.
1649converters = {}
1650
1651# maps strings to callables.
1652# these callables follow the same rules as those for "converters" above.
1653# note however that they will never be called with keyword-only parameters.
1654legacy_converters = {}
1655
1656
1657# maps strings to callables.
1658# these callables must be of the form:
1659# def foo(*, ...)
1660# The callable may have any number of keyword-only parameters.
1661# The callable must return a CConverter object.
1662# The callable should not call builtins.print.
1663return_converters = {}
1664
Larry Hastings7726ac92014-01-31 22:03:12 -08001665clinic = None
Larry Hastings31826802013-10-19 00:09:25 -07001666class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001667
1668 presets_text = """
Larry Hastings7726ac92014-01-31 22:03:12 -08001669preset block
1670everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001671methoddef_ifndef buffer 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001672docstring_prototype suppress
1673parser_prototype suppress
1674cpp_if suppress
1675cpp_endif suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001676
Larry Hastingsbebf7352014-01-17 17:47:17 -08001677preset original
1678everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001679methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001680docstring_prototype suppress
1681parser_prototype suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001682cpp_if suppress
1683cpp_endif suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001684
1685preset file
1686everything file
Larry Hastings0759f842015-04-03 13:09:02 -07001687methoddef_ifndef file 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001688docstring_prototype suppress
1689parser_prototype suppress
1690impl_definition block
1691
1692preset buffer
1693everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001694methoddef_ifndef buffer 1
1695impl_definition block
Larry Hastingsbebf7352014-01-17 17:47:17 -08001696docstring_prototype suppress
1697impl_prototype suppress
1698parser_prototype suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001699
1700preset partial-buffer
1701everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001702methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001703docstring_prototype block
1704impl_prototype suppress
1705methoddef_define block
1706parser_prototype block
1707impl_definition block
1708
Larry Hastingsbebf7352014-01-17 17:47:17 -08001709"""
1710
Larry Hastings581ee362014-01-28 05:00:08 -08001711 def __init__(self, language, printer=None, *, force=False, verify=True, filename=None):
Larry Hastings31826802013-10-19 00:09:25 -07001712 # maps strings to Parser objects.
1713 # (instantiated from the "parsers" global.)
1714 self.parsers = {}
1715 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001716 if printer:
1717 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001718 self.printer = printer or BlockPrinter(language)
1719 self.verify = verify
Larry Hastings581ee362014-01-28 05:00:08 -08001720 self.force = force
Larry Hastings31826802013-10-19 00:09:25 -07001721 self.filename = filename
1722 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001723 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001724 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001725
Larry Hastingsbebf7352014-01-17 17:47:17 -08001726 self.line_prefix = self.line_suffix = ''
1727
1728 self.destinations = {}
1729 self.add_destination("block", "buffer")
1730 self.add_destination("suppress", "suppress")
1731 self.add_destination("buffer", "buffer")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001732 if filename:
Larry Hastingsc2047262014-01-25 20:43:29 -08001733 self.add_destination("file", "file", "{dirname}/clinic/{basename}.h")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001734
Larry Hastings0759f842015-04-03 13:09:02 -07001735 d = self.get_destination_buffer
1736 self.destination_buffers = collections.OrderedDict((
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001737 ('cpp_if', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001738 ('docstring_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001739 ('docstring_definition', d('file')),
1740 ('methoddef_define', d('file')),
1741 ('impl_prototype', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001742 ('parser_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001743 ('parser_definition', d('file')),
1744 ('cpp_endif', d('file')),
1745 ('methoddef_ifndef', d('file', 1)),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001746 ('impl_definition', d('block')),
1747 ))
1748
Larry Hastings0759f842015-04-03 13:09:02 -07001749 self.destination_buffers_stack = []
1750 self.ifndef_symbols = set()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001751
1752 self.presets = {}
1753 preset = None
1754 for line in self.presets_text.strip().split('\n'):
1755 line = line.strip()
1756 if not line:
1757 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001758 name, value, *options = line.split()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001759 if name == 'preset':
1760 self.presets[value] = preset = collections.OrderedDict()
1761 continue
1762
Larry Hastings0759f842015-04-03 13:09:02 -07001763 if len(options):
1764 index = int(options[0])
1765 else:
1766 index = 0
1767 buffer = self.get_destination_buffer(value, index)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001768
1769 if name == 'everything':
Larry Hastings0759f842015-04-03 13:09:02 -07001770 for name in self.destination_buffers:
1771 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001772 continue
1773
Larry Hastings0759f842015-04-03 13:09:02 -07001774 assert name in self.destination_buffers
1775 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001776
Larry Hastings31826802013-10-19 00:09:25 -07001777 global clinic
1778 clinic = self
1779
Larry Hastingsbebf7352014-01-17 17:47:17 -08001780 def add_destination(self, name, type, *args):
1781 if name in self.destinations:
1782 fail("Destination already exists: " + repr(name))
1783 self.destinations[name] = Destination(name, type, self, *args)
1784
Larry Hastings0759f842015-04-03 13:09:02 -07001785 def get_destination(self, name):
1786 d = self.destinations.get(name)
1787 if not d:
1788 fail("Destination does not exist: " + repr(name))
1789 return d
1790
1791 def get_destination_buffer(self, name, item=0):
1792 d = self.get_destination(name)
1793 return d.buffers[item]
1794
Larry Hastings31826802013-10-19 00:09:25 -07001795 def parse(self, input):
1796 printer = self.printer
1797 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1798 for block in self.block_parser:
1799 dsl_name = block.dsl_name
1800 if dsl_name:
1801 if dsl_name not in self.parsers:
1802 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1803 self.parsers[dsl_name] = parsers[dsl_name](self)
1804 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001805 try:
1806 parser.parse(block)
1807 except Exception:
1808 fail('Exception raised during parsing:\n' +
1809 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001810 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001811
1812 second_pass_replacements = {}
1813
Larry Hastings0759f842015-04-03 13:09:02 -07001814 # these are destinations not buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08001815 for name, destination in self.destinations.items():
1816 if destination.type == 'suppress':
1817 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001818 output = destination.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001819
1820 if output:
1821
1822 block = Block("", dsl_name="clinic", output=output)
1823
1824 if destination.type == 'buffer':
1825 block.input = "dump " + name + "\n"
1826 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1827 printer.write("\n")
1828 printer.print_block(block)
1829 continue
1830
1831 if destination.type == 'file':
1832 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08001833 dirname = os.path.dirname(destination.filename)
1834 try:
1835 os.makedirs(dirname)
1836 except FileExistsError:
1837 if not os.path.isdir(dirname):
1838 fail("Can't write to destination {}, "
1839 "can't make directory {}!".format(
1840 destination.filename, dirname))
Larry Hastings581ee362014-01-28 05:00:08 -08001841 if self.verify:
1842 with open(destination.filename, "rt") as f:
1843 parser_2 = BlockParser(f.read(), language=self.language)
1844 blocks = list(parser_2)
1845 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1846 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001847 except FileNotFoundError:
1848 pass
1849
1850 block.input = 'preserve\n'
1851 printer_2 = BlockPrinter(self.language)
1852 printer_2.print_block(block)
1853 with open(destination.filename, "wt") as f:
1854 f.write(printer_2.f.getvalue())
1855 continue
1856 text = printer.f.getvalue()
1857
1858 if second_pass_replacements:
1859 printer_2 = BlockPrinter(self.language)
1860 parser_2 = BlockParser(text, self.language)
1861 changed = False
1862 for block in parser_2:
1863 if block.dsl_name:
1864 for id, replacement in second_pass_replacements.items():
1865 if id in block.output:
1866 changed = True
1867 block.output = block.output.replace(id, replacement)
1868 printer_2.print_block(block)
1869 if changed:
1870 text = printer_2.f.getvalue()
1871
1872 return text
1873
Larry Hastings31826802013-10-19 00:09:25 -07001874
1875 def _module_and_class(self, fields):
1876 """
1877 fields should be an iterable of field names.
1878 returns a tuple of (module, class).
1879 the module object could actually be self (a clinic object).
1880 this function is only ever used to find the parent of where
1881 a new class/module should go.
1882 """
1883 in_classes = False
1884 parent = module = self
1885 cls = None
1886 so_far = []
1887
1888 for field in fields:
1889 so_far.append(field)
1890 if not in_classes:
1891 child = parent.modules.get(field)
1892 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001893 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001894 continue
1895 in_classes = True
1896 if not hasattr(parent, 'classes'):
1897 return module, cls
1898 child = parent.classes.get(field)
1899 if not child:
1900 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1901 cls = parent = child
1902
1903 return module, cls
1904
1905
Larry Hastings581ee362014-01-28 05:00:08 -08001906def parse_file(filename, *, force=False, verify=True, output=None, encoding='utf-8'):
Larry Hastings31826802013-10-19 00:09:25 -07001907 extension = os.path.splitext(filename)[1][1:]
1908 if not extension:
1909 fail("Can't extract file type for file " + repr(filename))
1910
1911 try:
Larry Hastings7726ac92014-01-31 22:03:12 -08001912 language = extensions[extension](filename)
Larry Hastings31826802013-10-19 00:09:25 -07001913 except KeyError:
1914 fail("Can't identify file type for file " + repr(filename))
1915
Larry Hastings31826802013-10-19 00:09:25 -07001916 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001917 raw = f.read()
1918
Larry Hastings2623c8c2014-02-08 22:15:29 -08001919 # exit quickly if there are no clinic markers in the file
1920 find_start_re = BlockParser("", language).find_start_re
1921 if not find_start_re.search(raw):
1922 return
1923
1924 clinic = Clinic(language, force=force, verify=verify, filename=filename)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001925 cooked = clinic.parse(raw)
Larry Hastings581ee362014-01-28 05:00:08 -08001926 if (cooked == raw) and not force:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001927 return
Larry Hastings31826802013-10-19 00:09:25 -07001928
1929 directory = os.path.dirname(filename) or '.'
1930
1931 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001932 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001933 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1934 with open(tmpfilename, "wb") as f:
1935 f.write(bytes)
1936 os.replace(tmpfilename, output or filename)
1937
1938
Larry Hastings581ee362014-01-28 05:00:08 -08001939def compute_checksum(input, length=None):
Larry Hastings31826802013-10-19 00:09:25 -07001940 input = input or ''
Larry Hastings581ee362014-01-28 05:00:08 -08001941 s = hashlib.sha1(input.encode('utf-8')).hexdigest()
1942 if length:
1943 s = s[:length]
1944 return s
Larry Hastings31826802013-10-19 00:09:25 -07001945
1946
1947
1948
1949class PythonParser:
1950 def __init__(self, clinic):
1951 pass
1952
1953 def parse(self, block):
1954 s = io.StringIO()
1955 with OverrideStdioWith(s):
1956 exec(block.input)
1957 block.output = s.getvalue()
1958
1959
1960class Module:
1961 def __init__(self, name, module=None):
1962 self.name = name
1963 self.module = self.parent = module
1964
1965 self.modules = collections.OrderedDict()
1966 self.classes = collections.OrderedDict()
1967 self.functions = []
1968
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001969 def __repr__(self):
1970 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1971
Larry Hastings31826802013-10-19 00:09:25 -07001972class Class:
Larry Hastingsc2047262014-01-25 20:43:29 -08001973 def __init__(self, name, module=None, cls=None, typedef=None, type_object=None):
Larry Hastings31826802013-10-19 00:09:25 -07001974 self.name = name
1975 self.module = module
1976 self.cls = cls
Larry Hastingsc2047262014-01-25 20:43:29 -08001977 self.typedef = typedef
1978 self.type_object = type_object
Larry Hastings31826802013-10-19 00:09:25 -07001979 self.parent = cls or module
1980
1981 self.classes = collections.OrderedDict()
1982 self.functions = []
1983
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001984 def __repr__(self):
1985 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1986
Larry Hastings8666e652014-01-12 14:12:59 -08001987unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001988
Larry Hastings8666e652014-01-12 14:12:59 -08001989__abs__
1990__add__
1991__and__
1992__bytes__
1993__call__
1994__complex__
1995__delitem__
1996__divmod__
1997__eq__
1998__float__
1999__floordiv__
2000__ge__
2001__getattr__
2002__getattribute__
2003__getitem__
2004__gt__
2005__hash__
2006__iadd__
2007__iand__
Larry Hastings8666e652014-01-12 14:12:59 -08002008__ifloordiv__
2009__ilshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02002010__imatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08002011__imod__
2012__imul__
2013__index__
2014__int__
2015__invert__
2016__ior__
2017__ipow__
2018__irshift__
2019__isub__
2020__iter__
2021__itruediv__
2022__ixor__
2023__le__
2024__len__
2025__lshift__
2026__lt__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02002027__matmul__
Larry Hastings8666e652014-01-12 14:12:59 -08002028__mod__
2029__mul__
2030__neg__
2031__new__
2032__next__
2033__or__
2034__pos__
2035__pow__
2036__radd__
2037__rand__
2038__rdivmod__
2039__repr__
2040__rfloordiv__
2041__rlshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02002042__rmatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08002043__rmod__
2044__rmul__
2045__ror__
Larry Hastings8666e652014-01-12 14:12:59 -08002046__rpow__
2047__rrshift__
2048__rshift__
2049__rsub__
2050__rtruediv__
2051__rxor__
2052__setattr__
2053__setitem__
2054__str__
2055__sub__
2056__truediv__
2057__xor__
2058
2059""".strip().split())
2060
2061
Larry Hastings5c661892014-01-24 06:17:25 -08002062INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
2063INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
2064""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07002065
2066class Function:
2067 """
2068 Mutable duck type for inspect.Function.
2069
2070 docstring - a str containing
2071 * embedded line breaks
2072 * text outdented to the left margin
2073 * no trailing whitespace.
2074 It will always be true that
2075 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
2076 """
2077
2078 def __init__(self, parameters=None, *, name,
2079 module, cls=None, c_basename=None,
2080 full_name=None,
2081 return_converter, return_annotation=_empty,
Larry Hastings581ee362014-01-28 05:00:08 -08002082 docstring=None, kind=CALLABLE, coexist=False,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002083 docstring_only=False):
Larry Hastings31826802013-10-19 00:09:25 -07002084 self.parameters = parameters or collections.OrderedDict()
2085 self.return_annotation = return_annotation
2086 self.name = name
2087 self.full_name = full_name
2088 self.module = module
2089 self.cls = cls
2090 self.parent = cls or module
2091 self.c_basename = c_basename
2092 self.return_converter = return_converter
2093 self.docstring = docstring or ''
2094 self.kind = kind
2095 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08002096 self.self_converter = None
Larry Hastings2623c8c2014-02-08 22:15:29 -08002097 # docstring_only means "don't generate a machine-readable
2098 # signature, just a normal docstring". it's True for
2099 # functions with optional groups because we can't represent
2100 # those accurately with inspect.Signature in 3.4.
2101 self.docstring_only = docstring_only
Larry Hastingsebdcb502013-11-23 14:54:00 -08002102
Larry Hastings7726ac92014-01-31 22:03:12 -08002103 self.rendered_parameters = None
2104
2105 __render_parameters__ = None
2106 @property
2107 def render_parameters(self):
2108 if not self.__render_parameters__:
2109 self.__render_parameters__ = l = []
2110 for p in self.parameters.values():
2111 p = p.copy()
2112 p.converter.pre_render()
2113 l.append(p)
2114 return self.__render_parameters__
2115
Larry Hastingsebdcb502013-11-23 14:54:00 -08002116 @property
2117 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08002118 if self.kind in (METHOD_INIT, METHOD_NEW):
2119 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002120 flags = []
2121 if self.kind == CLASS_METHOD:
2122 flags.append('METH_CLASS')
2123 elif self.kind == STATIC_METHOD:
2124 flags.append('METH_STATIC')
2125 else:
2126 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
2127 if self.coexist:
2128 flags.append('METH_COEXIST')
2129 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07002130
2131 def __repr__(self):
2132 return '<clinic.Function ' + self.name + '>'
2133
Larry Hastings7726ac92014-01-31 22:03:12 -08002134 def copy(self, **overrides):
2135 kwargs = {
2136 'name': self.name, 'module': self.module, 'parameters': self.parameters,
2137 'cls': self.cls, 'c_basename': self.c_basename,
2138 'full_name': self.full_name,
2139 'return_converter': self.return_converter, 'return_annotation': self.return_annotation,
2140 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002141 'docstring_only': self.docstring_only,
Larry Hastings7726ac92014-01-31 22:03:12 -08002142 }
2143 kwargs.update(overrides)
2144 f = Function(**kwargs)
2145
2146 parameters = collections.OrderedDict()
2147 for name, value in f.parameters.items():
2148 value = value.copy(function=f)
2149 parameters[name] = value
2150 f.parameters = parameters
2151 return f
2152
Larry Hastings31826802013-10-19 00:09:25 -07002153
2154class Parameter:
2155 """
2156 Mutable duck type of inspect.Parameter.
2157 """
2158
2159 def __init__(self, name, kind, *, default=_empty,
2160 function, converter, annotation=_empty,
2161 docstring=None, group=0):
2162 self.name = name
2163 self.kind = kind
2164 self.default = default
2165 self.function = function
2166 self.converter = converter
2167 self.annotation = annotation
2168 self.docstring = docstring or ''
2169 self.group = group
2170
2171 def __repr__(self):
2172 return '<clinic.Parameter ' + self.name + '>'
2173
2174 def is_keyword_only(self):
2175 return self.kind == inspect.Parameter.KEYWORD_ONLY
2176
Larry Hastings2623c8c2014-02-08 22:15:29 -08002177 def is_positional_only(self):
2178 return self.kind == inspect.Parameter.POSITIONAL_ONLY
2179
Larry Hastings7726ac92014-01-31 22:03:12 -08002180 def copy(self, **overrides):
2181 kwargs = {
2182 'name': self.name, 'kind': self.kind, 'default':self.default,
2183 'function': self.function, 'converter': self.converter, 'annotation': self.annotation,
2184 'docstring': self.docstring, 'group': self.group,
2185 }
2186 kwargs.update(overrides)
2187 if 'converter' not in overrides:
2188 converter = copy.copy(self.converter)
2189 converter.function = kwargs['function']
2190 kwargs['converter'] = converter
2191 return Parameter(**kwargs)
2192
2193
2194
2195class LandMine:
2196 # try to access any
2197 def __init__(self, message):
2198 self.__message__ = message
2199
2200 def __repr__(self):
2201 return '<LandMine ' + repr(self.__message__) + ">"
2202
2203 def __getattribute__(self, name):
2204 if name in ('__repr__', '__message__'):
2205 return super().__getattribute__(name)
2206 # raise RuntimeError(repr(name))
2207 fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__)
Larry Hastings31826802013-10-19 00:09:25 -07002208
Larry Hastings31826802013-10-19 00:09:25 -07002209
2210def add_c_converter(f, name=None):
2211 if not name:
2212 name = f.__name__
2213 if not name.endswith('_converter'):
2214 return f
2215 name = name[:-len('_converter')]
2216 converters[name] = f
2217 return f
2218
2219def add_default_legacy_c_converter(cls):
2220 # automatically add converter for default format unit
2221 # (but without stomping on the existing one if it's already
2222 # set, in case you subclass)
Larry Hastingsf1503782014-06-11 04:31:29 -07002223 if ((cls.format_unit not in ('O&', '')) and
Larry Hastings31826802013-10-19 00:09:25 -07002224 (cls.format_unit not in legacy_converters)):
2225 legacy_converters[cls.format_unit] = cls
2226 return cls
2227
2228def add_legacy_c_converter(format_unit, **kwargs):
2229 """
2230 Adds a legacy converter.
2231 """
2232 def closure(f):
2233 if not kwargs:
2234 added_f = f
2235 else:
2236 added_f = functools.partial(f, **kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002237 if format_unit:
2238 legacy_converters[format_unit] = added_f
Larry Hastings31826802013-10-19 00:09:25 -07002239 return f
2240 return closure
2241
2242class CConverterAutoRegister(type):
2243 def __init__(cls, name, bases, classdict):
2244 add_c_converter(cls)
2245 add_default_legacy_c_converter(cls)
2246
2247class CConverter(metaclass=CConverterAutoRegister):
2248 """
2249 For the init function, self, name, function, and default
2250 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08002251 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07002252 """
2253
Larry Hastings7726ac92014-01-31 22:03:12 -08002254 # The C name to use for this variable.
2255 name = None
2256
2257 # The Python name to use for this variable.
2258 py_name = None
2259
Larry Hastings78cf85c2014-01-04 12:44:57 -08002260 # The C type to use for this variable.
2261 # 'type' should be a Python string specifying the type, e.g. "int".
2262 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002263 type = None
Larry Hastings31826802013-10-19 00:09:25 -07002264
2265 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08002266 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08002267 # Or the magic value "unknown" if this value is a cannot be evaluated
2268 # at Argument-Clinic-preprocessing time (but is presumed to be valid
2269 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07002270 default = unspecified
2271
Larry Hastings4a55fc52014-01-12 11:09:57 -08002272 # If not None, default must be isinstance() of this type.
2273 # (You can also specify a tuple of types.)
2274 default_type = None
2275
Larry Hastings31826802013-10-19 00:09:25 -07002276 # "default" converted into a C value, as a string.
2277 # Or None if there is no default.
2278 c_default = None
2279
Larry Hastings2a727912014-01-16 11:32:01 -08002280 # "default" converted into a Python value, as a string.
2281 # Or None if there is no default.
2282 py_default = None
2283
Larry Hastingsabc716b2013-11-20 09:13:52 -08002284 # The default value used to initialize the C variable when
2285 # there is no default, but not specifying a default may
2286 # result in an "uninitialized variable" warning. This can
2287 # easily happen when using option groups--although
2288 # properly-written code won't actually use the variable,
2289 # the variable does get passed in to the _impl. (Ah, if
2290 # only dataflow analysis could inline the static function!)
2291 #
2292 # This value is specified as a string.
2293 # Every non-abstract subclass should supply a valid value.
2294 c_ignored_default = 'NULL'
2295
Larry Hastings31826802013-10-19 00:09:25 -07002296 # The C converter *function* to be used, if any.
2297 # (If this is not None, format_unit must be 'O&'.)
2298 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002299
Larry Hastings78cf85c2014-01-04 12:44:57 -08002300 # Should Argument Clinic add a '&' before the name of
2301 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07002302 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08002303
2304 # Should Argument Clinic add a '&' before the name of
2305 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07002306 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08002307
2308 #############################################################
2309 #############################################################
2310 ## You shouldn't need to read anything below this point to ##
2311 ## write your own converter functions. ##
2312 #############################################################
2313 #############################################################
2314
2315 # The "format unit" to specify for this variable when
2316 # parsing arguments using PyArg_ParseTuple (AndKeywords).
2317 # Custom converters should always use the default value of 'O&'.
2318 format_unit = 'O&'
2319
2320 # What encoding do we want for this variable? Only used
2321 # by format units starting with 'e'.
2322 encoding = None
2323
Larry Hastings77561cc2014-01-07 12:13:13 -08002324 # Should this object be required to be a subclass of a specific type?
2325 # If not None, should be a string representing a pointer to a
2326 # PyTypeObject (e.g. "&PyUnicode_Type").
2327 # Only used by the 'O!' format unit (and the "object" converter).
2328 subclass_of = None
2329
Larry Hastings78cf85c2014-01-04 12:44:57 -08002330 # Do we want an adjacent '_length' variable for this variable?
2331 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07002332 length = False
2333
Larry Hastings5c661892014-01-24 06:17:25 -08002334 # Should we show this parameter in the generated
2335 # __text_signature__? This is *almost* always True.
Larry Hastingsc2047262014-01-25 20:43:29 -08002336 # (It's only False for __new__, __init__, and METH_STATIC functions.)
Larry Hastings5c661892014-01-24 06:17:25 -08002337 show_in_signature = True
2338
2339 # Overrides the name used in a text signature.
2340 # The name used for a "self" parameter must be one of
2341 # self, type, or module; however users can set their own.
2342 # This lets the self_converter overrule the user-settable
2343 # name, *just* for the text signature.
2344 # Only set by self_converter.
2345 signature_name = None
2346
2347 # keep in sync with self_converter.__init__!
Larry Hastings7726ac92014-01-31 22:03:12 -08002348 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 -07002349 self.name = name
Larry Hastings7726ac92014-01-31 22:03:12 -08002350 self.py_name = py_name
Larry Hastings31826802013-10-19 00:09:25 -07002351
2352 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08002353 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002354 if isinstance(self.default_type, type):
2355 types_str = self.default_type.__name__
2356 else:
2357 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2358 fail("{}: default value {!r} for field {} is not of type {}".format(
2359 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002360 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002361
Larry Hastingsb4705752014-01-18 21:54:15 -08002362 if c_default:
2363 self.c_default = c_default
2364 if py_default:
2365 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002366
Larry Hastings31826802013-10-19 00:09:25 -07002367 if annotation != unspecified:
2368 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings7726ac92014-01-31 22:03:12 -08002369
2370 # this is deliberate, to prevent you from caching information
2371 # about the function in the init.
2372 # (that breaks if we get cloned.)
2373 # so after this change we will noisily fail.
2374 self.function = LandMine("Don't access members of self.function inside converter_init!")
Larry Hastings31826802013-10-19 00:09:25 -07002375 self.converter_init(**kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002376 self.function = function
Larry Hastings31826802013-10-19 00:09:25 -07002377
2378 def converter_init(self):
2379 pass
2380
2381 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002382 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002383
Larry Hastings5c661892014-01-24 06:17:25 -08002384 def _render_self(self, parameter, data):
2385 self.parameter = parameter
2386 original_name = self.name
2387 name = ensure_legal_c_identifier(original_name)
2388
2389 # impl_arguments
2390 s = ("&" if self.impl_by_reference else "") + name
2391 data.impl_arguments.append(s)
2392 if self.length:
2393 data.impl_arguments.append(self.length_name())
2394
2395 # impl_parameters
2396 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2397 if self.length:
2398 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2399
2400 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002401 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002402 original_name = self.name
2403 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002404
2405 # declarations
2406 d = self.declaration()
2407 data.declarations.append(d)
2408
2409 # initializers
2410 initializers = self.initialize()
2411 if initializers:
2412 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2413
Larry Hastingsc2047262014-01-25 20:43:29 -08002414 # modifications
2415 modifications = self.modify()
2416 if modifications:
2417 data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2418
Larry Hastings31826802013-10-19 00:09:25 -07002419 # keywords
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03002420 if parameter.is_positional_only():
2421 data.keywords.append('')
2422 else:
2423 data.keywords.append(parameter.name)
Larry Hastings31826802013-10-19 00:09:25 -07002424
2425 # format_units
2426 if self.is_optional() and '|' not in data.format_units:
2427 data.format_units.append('|')
2428 if parameter.is_keyword_only() and '$' not in data.format_units:
2429 data.format_units.append('$')
2430 data.format_units.append(self.format_unit)
2431
2432 # parse_arguments
2433 self.parse_argument(data.parse_arguments)
2434
Larry Hastings31826802013-10-19 00:09:25 -07002435 # cleanup
2436 cleanup = self.cleanup()
2437 if cleanup:
2438 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2439
Larry Hastings5c661892014-01-24 06:17:25 -08002440 def render(self, parameter, data):
2441 """
2442 parameter is a clinic.Parameter instance.
2443 data is a CRenderData instance.
2444 """
2445 self._render_self(parameter, data)
2446 self._render_non_self(parameter, data)
2447
Larry Hastingsebdcb502013-11-23 14:54:00 -08002448 def length_name(self):
2449 """Computes the name of the associated "length" variable."""
2450 if not self.length:
2451 return None
2452 return ensure_legal_c_identifier(self.name) + "_length"
2453
Larry Hastings31826802013-10-19 00:09:25 -07002454 # Why is this one broken out separately?
2455 # For "positional-only" function parsing,
2456 # which generates a bunch of PyArg_ParseTuple calls.
2457 def parse_argument(self, list):
2458 assert not (self.converter and self.encoding)
2459 if self.format_unit == 'O&':
2460 assert self.converter
2461 list.append(self.converter)
2462
2463 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002464 list.append(c_repr(self.encoding))
2465 elif self.subclass_of:
2466 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002467
Larry Hastingsebdcb502013-11-23 14:54:00 -08002468 legal_name = ensure_legal_c_identifier(self.name)
2469 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002470 list.append(s)
2471
Larry Hastingsebdcb502013-11-23 14:54:00 -08002472 if self.length:
2473 list.append("&" + self.length_name())
2474
Larry Hastings31826802013-10-19 00:09:25 -07002475 #
2476 # All the functions after here are intended as extension points.
2477 #
2478
2479 def simple_declaration(self, by_reference=False):
2480 """
2481 Computes the basic declaration of the variable.
2482 Used in computing the prototype declaration and the
2483 variable declaration.
2484 """
2485 prototype = [self.type]
2486 if by_reference or not self.type.endswith('*'):
2487 prototype.append(" ")
2488 if by_reference:
2489 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002490 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002491 return "".join(prototype)
2492
2493 def declaration(self):
2494 """
2495 The C statement to declare this variable.
2496 """
2497 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002498 default = self.c_default
2499 if not default and self.parameter.group:
2500 default = self.c_ignored_default
2501 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002502 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002503 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002504 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002505 if self.length:
2506 declaration.append('\nPy_ssize_clean_t ')
2507 declaration.append(self.length_name())
2508 declaration.append(';')
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03002509 return "".join(declaration)
Larry Hastings31826802013-10-19 00:09:25 -07002510
2511 def initialize(self):
2512 """
2513 The C statements required to set up this variable before parsing.
2514 Returns a string containing this code indented at column 0.
2515 If no initialization is necessary, returns an empty string.
2516 """
2517 return ""
2518
Larry Hastingsc2047262014-01-25 20:43:29 -08002519 def modify(self):
2520 """
2521 The C statements required to modify this variable after parsing.
2522 Returns a string containing this code indented at column 0.
2523 If no initialization is necessary, returns an empty string.
2524 """
2525 return ""
2526
Larry Hastings31826802013-10-19 00:09:25 -07002527 def cleanup(self):
2528 """
2529 The C statements required to clean up after this variable.
2530 Returns a string containing this code indented at column 0.
2531 If no cleanup is necessary, returns an empty string.
2532 """
2533 return ""
2534
Larry Hastings7726ac92014-01-31 22:03:12 -08002535 def pre_render(self):
2536 """
2537 A second initialization function, like converter_init,
2538 called just before rendering.
2539 You are permitted to examine self.function here.
2540 """
2541 pass
2542
Larry Hastings31826802013-10-19 00:09:25 -07002543
2544class bool_converter(CConverter):
2545 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002546 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002547 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002548 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002549
Serhiy Storchaka202fda52017-03-12 10:10:47 +02002550 def converter_init(self, *, accept={object}):
2551 if accept == {int}:
2552 self.format_unit = 'i'
2553 elif accept != {object}:
2554 fail("bool_converter: illegal 'accept' argument " + repr(accept))
Larry Hastings2a727912014-01-16 11:32:01 -08002555 if self.default is not unspecified:
2556 self.default = bool(self.default)
2557 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002558
2559class char_converter(CConverter):
2560 type = 'char'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002561 default_type = (bytes, bytearray)
Larry Hastings31826802013-10-19 00:09:25 -07002562 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002563 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002564
Tal Einatc929df32018-07-06 13:17:38 +03002565 # characters which need to be escaped in C code
2566 _escapes = {x: r'\%d' % x for x in range(7)}
2567 _escapes.update({
2568 0x07: r'\a',
2569 0x08: r'\b',
2570 0x09: r'\t',
2571 0x0A: r'\n',
2572 0x0B: r'\v',
2573 0x0C: r'\f',
2574 0x0D: r'\r',
2575 0x22: r'\"',
2576 0x27: r'\'',
2577 0x3F: r'\?',
2578 0x5C: r'\\',
2579 })
2580
Larry Hastings4a55fc52014-01-12 11:09:57 -08002581 def converter_init(self):
Tal Einatc929df32018-07-06 13:17:38 +03002582 if isinstance(self.default, self.default_type):
2583 if len(self.default) != 1:
2584 fail("char_converter: illegal default value " + repr(self.default))
2585
2586 c_ord = self.default[0]
2587 self.c_default = "'%s'" % self._escapes.get(c_ord, chr(c_ord))
Larry Hastings4a55fc52014-01-12 11:09:57 -08002588
2589
Larry Hastings31826802013-10-19 00:09:25 -07002590@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002591class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002592 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002593 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002594 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002595 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002596
2597 def converter_init(self, *, bitwise=False):
2598 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002599 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002600
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002601class byte_converter(unsigned_char_converter): pass
2602
Larry Hastings31826802013-10-19 00:09:25 -07002603class short_converter(CConverter):
2604 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002605 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002606 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002607 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002608
2609class unsigned_short_converter(CConverter):
2610 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002611 default_type = int
Larry Hastingsabc716b2013-11-20 09:13:52 -08002612 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002613
2614 def converter_init(self, *, bitwise=False):
Serhiy Storchaka7cb7bcf2018-07-26 13:22:16 +03002615 if bitwise:
2616 self.format_unit = 'H'
2617 else:
2618 self.converter = '_PyLong_UnsignedShort_Converter'
Larry Hastings31826802013-10-19 00:09:25 -07002619
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002620@add_legacy_c_converter('C', accept={str})
Larry Hastings31826802013-10-19 00:09:25 -07002621class int_converter(CConverter):
2622 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002623 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002624 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002625 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002626
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002627 def converter_init(self, *, accept={int}, type=None):
2628 if accept == {str}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002629 self.format_unit = 'C'
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002630 elif accept != {int}:
2631 fail("int_converter: illegal 'accept' argument " + repr(accept))
Larry Hastingsdfbeb162014-10-13 10:39:41 +01002632 if type != None:
2633 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002634
2635class unsigned_int_converter(CConverter):
2636 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002637 default_type = int
Larry Hastingsabc716b2013-11-20 09:13:52 -08002638 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002639
2640 def converter_init(self, *, bitwise=False):
Serhiy Storchaka7cb7bcf2018-07-26 13:22:16 +03002641 if bitwise:
2642 self.format_unit = 'I'
2643 else:
2644 self.converter = '_PyLong_UnsignedInt_Converter'
Larry Hastings31826802013-10-19 00:09:25 -07002645
2646class long_converter(CConverter):
2647 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002648 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002649 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002650 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002651
2652class unsigned_long_converter(CConverter):
2653 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002654 default_type = int
Larry Hastingsabc716b2013-11-20 09:13:52 -08002655 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002656
2657 def converter_init(self, *, bitwise=False):
Serhiy Storchaka7cb7bcf2018-07-26 13:22:16 +03002658 if bitwise:
2659 self.format_unit = 'k'
2660 else:
2661 self.converter = '_PyLong_UnsignedLong_Converter'
Larry Hastings31826802013-10-19 00:09:25 -07002662
Benjamin Petersoncc854492016-09-08 09:29:11 -07002663class long_long_converter(CConverter):
2664 type = 'long long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002665 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002666 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002667 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002668
Benjamin Petersoncc854492016-09-08 09:29:11 -07002669class unsigned_long_long_converter(CConverter):
2670 type = 'unsigned long long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002671 default_type = int
Larry Hastingsabc716b2013-11-20 09:13:52 -08002672 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002673
2674 def converter_init(self, *, bitwise=False):
Serhiy Storchaka7cb7bcf2018-07-26 13:22:16 +03002675 if bitwise:
2676 self.format_unit = 'K'
2677 else:
2678 self.converter = '_PyLong_UnsignedLongLong_Converter'
Serhiy Storchaka762bf402017-03-30 09:15:31 +03002679
Larry Hastings31826802013-10-19 00:09:25 -07002680class Py_ssize_t_converter(CConverter):
2681 type = 'Py_ssize_t'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002682 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002683
Serhiy Storchaka762bf402017-03-30 09:15:31 +03002684 def converter_init(self, *, accept={int}):
2685 if accept == {int}:
2686 self.format_unit = 'n'
2687 self.default_type = int
2688 elif accept == {int, NoneType}:
2689 self.converter = '_Py_convert_optional_to_ssize_t'
2690 else:
2691 fail("Py_ssize_t_converter: illegal 'accept' argument " + repr(accept))
2692
Larry Hastings31826802013-10-19 00:09:25 -07002693
Serhiy Storchaka80ec8362017-03-19 19:37:40 +02002694class slice_index_converter(CConverter):
2695 type = 'Py_ssize_t'
2696
2697 def converter_init(self, *, accept={int, NoneType}):
2698 if accept == {int}:
Serhiy Storchakad4edfc92017-03-30 18:29:23 +03002699 self.converter = '_PyEval_SliceIndexNotNone'
Serhiy Storchaka80ec8362017-03-19 19:37:40 +02002700 elif accept == {int, NoneType}:
Serhiy Storchakad4edfc92017-03-30 18:29:23 +03002701 self.converter = '_PyEval_SliceIndex'
Serhiy Storchaka80ec8362017-03-19 19:37:40 +02002702 else:
2703 fail("slice_index_converter: illegal 'accept' argument " + repr(accept))
2704
Serhiy Storchaka7cb7bcf2018-07-26 13:22:16 +03002705class size_t_converter(CConverter):
2706 type = 'size_t'
2707 converter = '_PyLong_Size_t_Converter'
2708 c_ignored_default = "0"
2709
Serhiy Storchaka80ec8362017-03-19 19:37:40 +02002710
Larry Hastings31826802013-10-19 00:09:25 -07002711class float_converter(CConverter):
2712 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002713 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002714 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002715 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002716
2717class double_converter(CConverter):
2718 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002719 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002720 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002721 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002722
2723
2724class Py_complex_converter(CConverter):
2725 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002726 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002727 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002728 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002729
2730
2731class object_converter(CConverter):
2732 type = 'PyObject *'
2733 format_unit = 'O'
2734
Larry Hastings4a55fc52014-01-12 11:09:57 -08002735 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2736 if converter:
2737 if subclass_of:
2738 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2739 self.format_unit = 'O&'
2740 self.converter = converter
2741 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002742 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002743 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002744
Larry Hastings77561cc2014-01-07 12:13:13 -08002745 if type is not None:
2746 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002747
2748
Larry Hastings7f90cba2015-04-15 23:02:12 -04002749#
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002750# We define three conventions for buffer types in the 'accept' argument:
2751#
2752# buffer : any object supporting the buffer interface
2753# rwbuffer: any object supporting the buffer interface, but must be writeable
2754# robuffer: any object supporting the buffer interface, but must not be writeable
Larry Hastings7f90cba2015-04-15 23:02:12 -04002755#
2756
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002757class buffer: pass
2758class rwbuffer: pass
2759class robuffer: pass
2760
Larry Hastings38337d12015-05-07 23:30:09 -07002761def str_converter_key(types, encoding, zeroes):
2762 return (frozenset(types), bool(encoding), bool(zeroes))
2763
2764str_converter_argument_map = {}
2765
Larry Hastings31826802013-10-19 00:09:25 -07002766class str_converter(CConverter):
2767 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002768 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002769 format_unit = 's'
2770
Larry Hastings38337d12015-05-07 23:30:09 -07002771 def converter_init(self, *, accept={str}, encoding=None, zeroes=False):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002772
Larry Hastings38337d12015-05-07 23:30:09 -07002773 key = str_converter_key(accept, encoding, zeroes)
2774 format_unit = str_converter_argument_map.get(key)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002775 if not format_unit:
Larry Hastings38337d12015-05-07 23:30:09 -07002776 fail("str_converter: illegal combination of arguments", key)
2777
Larry Hastingsebdcb502013-11-23 14:54:00 -08002778 self.format_unit = format_unit
Larry Hastings38337d12015-05-07 23:30:09 -07002779 self.length = bool(zeroes)
2780 if encoding:
2781 if self.default not in (Null, None, unspecified):
2782 fail("str_converter: Argument Clinic doesn't support default values for encoded strings")
2783 self.encoding = encoding
2784 self.type = 'char *'
2785 # sorry, clinic can't support preallocated buffers
2786 # for es# and et#
2787 self.c_default = "NULL"
2788
2789 def cleanup(self):
2790 if self.encoding:
2791 name = ensure_legal_c_identifier(self.name)
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03002792 return "".join(["if (", name, ") {\n PyMem_FREE(", name, ");\n}\n"])
Larry Hastings38337d12015-05-07 23:30:09 -07002793
2794#
2795# This is the fourth or fifth rewrite of registering all the
Raymond Hettinger14010182018-09-13 21:17:40 -07002796# string converter format units. Previous approaches hid
Larry Hastings38337d12015-05-07 23:30:09 -07002797# bugs--generally mismatches between the semantics of the format
2798# unit and the arguments necessary to represent those semantics
2799# properly. Hopefully with this approach we'll get it 100% right.
2800#
2801# The r() function (short for "register") both registers the
2802# mapping from arguments to format unit *and* registers the
2803# legacy C converter for that format unit.
2804#
2805def r(format_unit, *, accept, encoding=False, zeroes=False):
2806 if not encoding and format_unit != 's':
2807 # add the legacy c converters here too.
2808 #
2809 # note: add_legacy_c_converter can't work for
2810 # es, es#, et, or et#
2811 # because of their extra encoding argument
2812 #
2813 # also don't add the converter for 's' because
2814 # the metaclass for CConverter adds it for us.
2815 kwargs = {}
2816 if accept != {str}:
2817 kwargs['accept'] = accept
2818 if zeroes:
2819 kwargs['zeroes'] = True
2820 added_f = functools.partial(str_converter, **kwargs)
2821 legacy_converters[format_unit] = added_f
2822
2823 d = str_converter_argument_map
2824 key = str_converter_key(accept, encoding, zeroes)
2825 if key in d:
2826 sys.exit("Duplicate keys specified for str_converter_argument_map!")
2827 d[key] = format_unit
2828
2829r('es', encoding=True, accept={str})
2830r('es#', encoding=True, zeroes=True, accept={str})
2831r('et', encoding=True, accept={bytes, bytearray, str})
2832r('et#', encoding=True, zeroes=True, accept={bytes, bytearray, str})
2833r('s', accept={str})
2834r('s#', zeroes=True, accept={robuffer, str})
2835r('y', accept={robuffer})
2836r('y#', zeroes=True, accept={robuffer})
2837r('z', accept={str, NoneType})
2838r('z#', zeroes=True, accept={robuffer, str, NoneType})
2839del r
Larry Hastings31826802013-10-19 00:09:25 -07002840
2841
2842class PyBytesObject_converter(CConverter):
2843 type = 'PyBytesObject *'
2844 format_unit = 'S'
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002845 # accept = {bytes}
Larry Hastings31826802013-10-19 00:09:25 -07002846
2847class PyByteArrayObject_converter(CConverter):
2848 type = 'PyByteArrayObject *'
2849 format_unit = 'Y'
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002850 # accept = {bytearray}
Larry Hastings31826802013-10-19 00:09:25 -07002851
2852class unicode_converter(CConverter):
2853 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002854 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002855 format_unit = 'U'
2856
Larry Hastings38337d12015-05-07 23:30:09 -07002857@add_legacy_c_converter('u#', zeroes=True)
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002858@add_legacy_c_converter('Z', accept={str, NoneType})
Larry Hastings38337d12015-05-07 23:30:09 -07002859@add_legacy_c_converter('Z#', accept={str, NoneType}, zeroes=True)
Larry Hastings31826802013-10-19 00:09:25 -07002860class Py_UNICODE_converter(CConverter):
Serhiy Storchakaafb3e712018-12-14 11:19:51 +02002861 type = 'const Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002862 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002863 format_unit = 'u'
2864
Larry Hastings38337d12015-05-07 23:30:09 -07002865 def converter_init(self, *, accept={str}, zeroes=False):
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002866 format_unit = 'Z' if accept=={str, NoneType} else 'u'
Larry Hastings38337d12015-05-07 23:30:09 -07002867 if zeroes:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002868 format_unit += '#'
2869 self.length = True
2870 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002871
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002872@add_legacy_c_converter('s*', accept={str, buffer})
2873@add_legacy_c_converter('z*', accept={str, buffer, NoneType})
2874@add_legacy_c_converter('w*', accept={rwbuffer})
Larry Hastings31826802013-10-19 00:09:25 -07002875class Py_buffer_converter(CConverter):
2876 type = 'Py_buffer'
2877 format_unit = 'y*'
2878 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002879 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002880
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002881 def converter_init(self, *, accept={buffer}):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002882 if self.default not in (unspecified, None):
2883 fail("The only legal default value for Py_buffer is None.")
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002884
Larry Hastings3f144c22014-01-06 10:34:00 -08002885 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002886
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002887 if accept == {str, buffer, NoneType}:
2888 format_unit = 'z*'
2889 elif accept == {str, buffer}:
2890 format_unit = 's*'
2891 elif accept == {buffer}:
2892 format_unit = 'y*'
2893 elif accept == {rwbuffer}:
2894 format_unit = 'w*'
Larry Hastings31826802013-10-19 00:09:25 -07002895 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002896 fail("Py_buffer_converter: illegal combination of arguments")
2897
2898 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002899
2900 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002901 name = ensure_legal_c_identifier(self.name)
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03002902 return "".join(["if (", name, ".obj) {\n PyBuffer_Release(&", name, ");\n}\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002903
2904
Larry Hastings5c661892014-01-24 06:17:25 -08002905def correct_name_for_self(f):
2906 if f.kind in (CALLABLE, METHOD_INIT):
2907 if f.cls:
2908 return "PyObject *", "self"
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03002909 return "PyObject *", "module"
Larry Hastings5c661892014-01-24 06:17:25 -08002910 if f.kind == STATIC_METHOD:
2911 return "void *", "null"
2912 if f.kind in (CLASS_METHOD, METHOD_NEW):
2913 return "PyTypeObject *", "type"
2914 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2915
Larry Hastingsc2047262014-01-25 20:43:29 -08002916def required_type_for_self_for_parser(f):
2917 type, _ = correct_name_for_self(f)
2918 if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2919 return type
2920 return None
2921
Larry Hastings5c661892014-01-24 06:17:25 -08002922
Larry Hastingsebdcb502013-11-23 14:54:00 -08002923class self_converter(CConverter):
2924 """
2925 A special-case converter:
2926 this is the default converter used for "self".
2927 """
Larry Hastings5c661892014-01-24 06:17:25 -08002928 type = None
2929 format_unit = ''
2930
Larry Hastings78cf85c2014-01-04 12:44:57 -08002931 def converter_init(self, *, type=None):
Larry Hastings7726ac92014-01-31 22:03:12 -08002932 self.specified_type = type
2933
2934 def pre_render(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002935 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002936 default_type, default_name = correct_name_for_self(f)
2937 self.signature_name = default_name
Larry Hastings7726ac92014-01-31 22:03:12 -08002938 self.type = self.specified_type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002939
Larry Hastings5c661892014-01-24 06:17:25 -08002940 kind = self.function.kind
2941 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2942
2943 if (kind == STATIC_METHOD) or new_or_init:
2944 self.show_in_signature = False
2945
2946 # tp_new (METHOD_NEW) functions are of type newfunc:
2947 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2948 # PyTypeObject is a typedef for struct _typeobject.
2949 #
2950 # tp_init (METHOD_INIT) functions are of type initproc:
2951 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2952 #
2953 # All other functions generated by Argument Clinic are stored in
2954 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2955 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2956 # However! We habitually cast these functions to PyCFunction,
2957 # since functions that accept keyword arguments don't fit this signature
2958 # but are stored there anyway. So strict type equality isn't important
2959 # for these functions.
2960 #
2961 # So:
2962 #
2963 # * The name of the first parameter to the impl and the parsing function will always
2964 # be self.name.
2965 #
2966 # * The type of the first parameter to the impl will always be of self.type.
2967 #
2968 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2969 # * The type of the first parameter to the parsing function is also self.type.
2970 # This means that if you step into the parsing function, your "self" parameter
2971 # is of the correct type, which may make debugging more pleasant.
2972 #
2973 # * Else if the function is tp_new (METHOD_NEW):
2974 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2975 # so the type signature of the function call is an exact match.
2976 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2977 # in the impl call.
2978 #
2979 # * Else if the function is tp_init (METHOD_INIT):
2980 # * The type of the first parameter to the parsing function is "PyObject *",
2981 # so the type signature of the function call is an exact match.
2982 # * If self.type != "PyObject *", we cast the first parameter to self.type
2983 # in the impl call.
2984
2985 @property
2986 def parser_type(self):
Larry Hastingsc2047262014-01-25 20:43:29 -08002987 return required_type_for_self_for_parser(self.function) or self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002988
Larry Hastingsebdcb502013-11-23 14:54:00 -08002989 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002990 """
2991 parameter is a clinic.Parameter instance.
2992 data is a CRenderData instance.
2993 """
2994 if self.function.kind == STATIC_METHOD:
2995 return
2996
2997 self._render_self(parameter, data)
2998
2999 if self.type != self.parser_type:
3000 # insert cast to impl_argument[0], aka self.
3001 # we know we're in the first slot in all the CRenderData lists,
3002 # because we render parameters in order, and self is always first.
3003 assert len(data.impl_arguments) == 1
3004 assert data.impl_arguments[0] == self.name
3005 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
3006
3007 def set_template_dict(self, template_dict):
3008 template_dict['self_name'] = self.name
3009 template_dict['self_type'] = self.parser_type
Larry Hastingsf0537e82014-01-25 22:01:12 -08003010 kind = self.function.kind
3011 cls = self.function.cls
3012
3013 if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef):
3014 if kind == METHOD_NEW:
3015 passed_in_type = self.name
3016 else:
3017 passed_in_type = 'Py_TYPE({})'.format(self.name)
3018
3019 line = '({passed_in_type} == {type_object}) &&\n '
3020 d = {
3021 'type_object': self.function.cls.type_object,
3022 'passed_in_type': passed_in_type
3023 }
3024 template_dict['self_type_check'] = line.format_map(d)
Larry Hastingsebdcb502013-11-23 14:54:00 -08003025
Larry Hastings31826802013-10-19 00:09:25 -07003026
3027
3028def add_c_return_converter(f, name=None):
3029 if not name:
3030 name = f.__name__
3031 if not name.endswith('_return_converter'):
3032 return f
3033 name = name[:-len('_return_converter')]
3034 return_converters[name] = f
3035 return f
3036
3037
3038class CReturnConverterAutoRegister(type):
3039 def __init__(cls, name, bases, classdict):
3040 add_c_return_converter(cls)
3041
3042class CReturnConverter(metaclass=CReturnConverterAutoRegister):
3043
Larry Hastings78cf85c2014-01-04 12:44:57 -08003044 # The C type to use for this variable.
3045 # 'type' should be a Python string specifying the type, e.g. "int".
3046 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07003047 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08003048
3049 # The Python default value for this parameter, as a Python value.
3050 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07003051 default = None
3052
Larry Hastings2a727912014-01-16 11:32:01 -08003053 def __init__(self, *, py_default=None, **kwargs):
3054 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07003055 try:
3056 self.return_converter_init(**kwargs)
3057 except TypeError as e:
3058 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
3059 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
3060
3061 def return_converter_init(self):
3062 pass
3063
3064 def declare(self, data, name="_return_value"):
3065 line = []
3066 add = line.append
3067 add(self.type)
3068 if not self.type.endswith('*'):
3069 add(' ')
3070 add(name + ';')
3071 data.declarations.append(''.join(line))
3072 data.return_value = name
3073
3074 def err_occurred_if(self, expr, data):
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03003075 data.return_conversion.append('if (({}) && PyErr_Occurred()) {{\n goto exit;\n}}\n'.format(expr))
Larry Hastings31826802013-10-19 00:09:25 -07003076
3077 def err_occurred_if_null_pointer(self, variable, data):
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03003078 data.return_conversion.append('if ({} == NULL) {{\n goto exit;\n}}\n'.format(variable))
Larry Hastings31826802013-10-19 00:09:25 -07003079
3080 def render(self, function, data):
3081 """
3082 function is a clinic.Function instance.
3083 data is a CRenderData instance.
3084 """
3085 pass
3086
3087add_c_return_converter(CReturnConverter, 'object')
3088
Larry Hastings78cf85c2014-01-04 12:44:57 -08003089class NoneType_return_converter(CReturnConverter):
3090 def render(self, function, data):
3091 self.declare(data)
3092 data.return_conversion.append('''
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03003093if (_return_value != Py_None) {
Larry Hastings78cf85c2014-01-04 12:44:57 -08003094 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03003095}
Larry Hastings78cf85c2014-01-04 12:44:57 -08003096return_value = Py_None;
3097Py_INCREF(Py_None);
3098'''.strip())
3099
Larry Hastings4a55fc52014-01-12 11:09:57 -08003100class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07003101 type = 'int'
3102
3103 def render(self, function, data):
3104 self.declare(data)
3105 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08003106 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07003107
3108class long_return_converter(CReturnConverter):
3109 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003110 conversion_fn = 'PyLong_FromLong'
3111 cast = ''
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003112 unsigned_cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07003113
3114 def render(self, function, data):
3115 self.declare(data)
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003116 self.err_occurred_if("_return_value == {}-1".format(self.unsigned_cast), data)
Larry Hastings31826802013-10-19 00:09:25 -07003117 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08003118 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07003119
Larry Hastings4a55fc52014-01-12 11:09:57 -08003120class int_return_converter(long_return_converter):
3121 type = 'int'
3122 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07003123
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003124class init_return_converter(long_return_converter):
3125 """
3126 Special return converter for __init__ functions.
3127 """
3128 type = 'int'
3129 cast = '(long)'
3130
3131 def render(self, function, data):
3132 pass
3133
Larry Hastings4a55fc52014-01-12 11:09:57 -08003134class unsigned_long_return_converter(long_return_converter):
3135 type = 'unsigned long'
3136 conversion_fn = 'PyLong_FromUnsignedLong'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003137 unsigned_cast = '(unsigned long)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003138
3139class unsigned_int_return_converter(unsigned_long_return_converter):
3140 type = 'unsigned int'
3141 cast = '(unsigned long)'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003142 unsigned_cast = '(unsigned int)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003143
3144class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07003145 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003146 conversion_fn = 'PyLong_FromSsize_t'
3147
3148class size_t_return_converter(long_return_converter):
3149 type = 'size_t'
3150 conversion_fn = 'PyLong_FromSize_t'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003151 unsigned_cast = '(size_t)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003152
3153
3154class double_return_converter(CReturnConverter):
3155 type = 'double'
3156 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07003157
3158 def render(self, function, data):
3159 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08003160 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07003161 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08003162 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
3163
3164class float_return_converter(double_return_converter):
3165 type = 'float'
3166 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07003167
3168
3169class DecodeFSDefault_return_converter(CReturnConverter):
3170 type = 'char *'
3171
3172 def render(self, function, data):
3173 self.declare(data)
3174 self.err_occurred_if_null_pointer("_return_value", data)
3175 data.return_conversion.append(
3176 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
3177
3178
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003179def eval_ast_expr(node, globals, *, filename='-'):
3180 """
3181 Takes an ast.Expr node. Compiles and evaluates it.
3182 Returns the result of the expression.
3183
3184 globals represents the globals dict the expression
3185 should see. (There's no equivalent for "locals" here.)
3186 """
3187
3188 if isinstance(node, ast.Expr):
3189 node = node.value
3190
3191 node = ast.Expression(node)
3192 co = compile(node, filename, 'eval')
3193 fn = types.FunctionType(co, globals)
3194 return fn()
3195
3196
Larry Hastings31826802013-10-19 00:09:25 -07003197class IndentStack:
3198 def __init__(self):
3199 self.indents = []
3200 self.margin = None
3201
3202 def _ensure(self):
3203 if not self.indents:
3204 fail('IndentStack expected indents, but none are defined.')
3205
3206 def measure(self, line):
3207 """
3208 Returns the length of the line's margin.
3209 """
3210 if '\t' in line:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003211 fail('Tab characters are illegal in the Argument Clinic DSL.')
Larry Hastings31826802013-10-19 00:09:25 -07003212 stripped = line.lstrip()
3213 if not len(stripped):
3214 # we can't tell anything from an empty line
3215 # so just pretend it's indented like our current indent
3216 self._ensure()
3217 return self.indents[-1]
3218 return len(line) - len(stripped)
3219
3220 def infer(self, line):
3221 """
3222 Infer what is now the current margin based on this line.
3223 Returns:
3224 1 if we have indented (or this is the first margin)
3225 0 if the margin has not changed
3226 -N if we have dedented N times
3227 """
3228 indent = self.measure(line)
3229 margin = ' ' * indent
3230 if not self.indents:
3231 self.indents.append(indent)
3232 self.margin = margin
3233 return 1
3234 current = self.indents[-1]
3235 if indent == current:
3236 return 0
3237 if indent > current:
3238 self.indents.append(indent)
3239 self.margin = margin
3240 return 1
3241 # indent < current
3242 if indent not in self.indents:
3243 fail("Illegal outdent.")
3244 outdent_count = 0
3245 while indent != current:
3246 self.indents.pop()
3247 current = self.indents[-1]
3248 outdent_count -= 1
3249 self.margin = margin
3250 return outdent_count
3251
3252 @property
3253 def depth(self):
3254 """
3255 Returns how many margins are currently defined.
3256 """
3257 return len(self.indents)
3258
3259 def indent(self, line):
3260 """
3261 Indents a line by the currently defined margin.
3262 """
3263 return self.margin + line
3264
3265 def dedent(self, line):
3266 """
3267 Dedents a line by the currently defined margin.
3268 (The inverse of 'indent'.)
3269 """
3270 margin = self.margin
3271 indent = self.indents[-1]
3272 if not line.startswith(margin):
3273 fail('Cannot dedent, line does not start with the previous margin:')
3274 return line[indent:]
3275
3276
3277class DSLParser:
3278 def __init__(self, clinic):
3279 self.clinic = clinic
3280
3281 self.directives = {}
3282 for name in dir(self):
3283 # functions that start with directive_ are added to directives
3284 _, s, key = name.partition("directive_")
3285 if s:
3286 self.directives[key] = getattr(self, name)
3287
3288 # functions that start with at_ are too, with an @ in front
3289 _, s, key = name.partition("at_")
3290 if s:
3291 self.directives['@' + key] = getattr(self, name)
3292
3293 self.reset()
3294
3295 def reset(self):
3296 self.function = None
3297 self.state = self.state_dsl_start
3298 self.parameter_indent = None
3299 self.keyword_only = False
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03003300 self.positional_only = False
Larry Hastings31826802013-10-19 00:09:25 -07003301 self.group = 0
3302 self.parameter_state = self.ps_start
Larry Hastingsc2047262014-01-25 20:43:29 -08003303 self.seen_positional_with_default = False
Larry Hastings31826802013-10-19 00:09:25 -07003304 self.indent = IndentStack()
3305 self.kind = CALLABLE
3306 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08003307 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08003308 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07003309
Larry Hastingsebdcb502013-11-23 14:54:00 -08003310 def directive_version(self, required):
3311 global version
3312 if version_comparitor(version, required) < 0:
3313 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
3314
Larry Hastings31826802013-10-19 00:09:25 -07003315 def directive_module(self, name):
3316 fields = name.split('.')
3317 new = fields.pop()
3318 module, cls = self.clinic._module_and_class(fields)
3319 if cls:
3320 fail("Can't nest a module inside a class!")
Larry Hastingsc2047262014-01-25 20:43:29 -08003321
3322 if name in module.classes:
3323 fail("Already defined module " + repr(name) + "!")
3324
Larry Hastings31826802013-10-19 00:09:25 -07003325 m = Module(name, module)
3326 module.modules[name] = m
3327 self.block.signatures.append(m)
3328
Larry Hastingsc2047262014-01-25 20:43:29 -08003329 def directive_class(self, name, typedef, type_object):
Larry Hastings31826802013-10-19 00:09:25 -07003330 fields = name.split('.')
3331 in_classes = False
3332 parent = self
3333 name = fields.pop()
3334 so_far = []
3335 module, cls = self.clinic._module_and_class(fields)
3336
Larry Hastingsc2047262014-01-25 20:43:29 -08003337 parent = cls or module
3338 if name in parent.classes:
3339 fail("Already defined class " + repr(name) + "!")
3340
3341 c = Class(name, module, cls, typedef, type_object)
3342 parent.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07003343 self.block.signatures.append(c)
3344
Larry Hastingsbebf7352014-01-17 17:47:17 -08003345 def directive_set(self, name, value):
3346 if name not in ("line_prefix", "line_suffix"):
3347 fail("unknown variable", repr(name))
3348
3349 value = value.format_map({
3350 'block comment start': '/*',
3351 'block comment end': '*/',
3352 })
3353
3354 self.clinic.__dict__[name] = value
3355
3356 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06003357 if command == 'new':
3358 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003359 return
3360
Zachary Ware071baa62014-01-21 23:07:12 -06003361 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08003362 self.clinic.get_destination(name).clear()
3363 fail("unknown destination command", repr(command))
3364
3365
Larry Hastings0759f842015-04-03 13:09:02 -07003366 def directive_output(self, command_or_name, destination=''):
3367 fd = self.clinic.destination_buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08003368
Larry Hastings0759f842015-04-03 13:09:02 -07003369 if command_or_name == "preset":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003370 preset = self.clinic.presets.get(destination)
3371 if not preset:
3372 fail("Unknown preset " + repr(destination) + "!")
3373 fd.update(preset)
3374 return
3375
Larry Hastings0759f842015-04-03 13:09:02 -07003376 if command_or_name == "push":
3377 self.clinic.destination_buffers_stack.append(fd.copy())
Larry Hastingsbebf7352014-01-17 17:47:17 -08003378 return
3379
Larry Hastings0759f842015-04-03 13:09:02 -07003380 if command_or_name == "pop":
3381 if not self.clinic.destination_buffers_stack:
Larry Hastingsbebf7352014-01-17 17:47:17 -08003382 fail("Can't 'output pop', stack is empty!")
Larry Hastings0759f842015-04-03 13:09:02 -07003383 previous_fd = self.clinic.destination_buffers_stack.pop()
Larry Hastingsbebf7352014-01-17 17:47:17 -08003384 fd.update(previous_fd)
3385 return
3386
3387 # secret command for debugging!
Larry Hastings0759f842015-04-03 13:09:02 -07003388 if command_or_name == "print":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003389 self.block.output.append(pprint.pformat(fd))
3390 self.block.output.append('\n')
3391 return
3392
3393 d = self.clinic.get_destination(destination)
3394
Larry Hastings0759f842015-04-03 13:09:02 -07003395 if command_or_name == "everything":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003396 for name in list(fd):
3397 fd[name] = d
3398 return
3399
Larry Hastings0759f842015-04-03 13:09:02 -07003400 if command_or_name not in fd:
3401 fail("Invalid command / destination name " + repr(command_or_name) + ", must be one of:\n preset push pop print everything " + " ".join(fd))
3402 fd[command_or_name] = d
Larry Hastingsbebf7352014-01-17 17:47:17 -08003403
3404 def directive_dump(self, name):
3405 self.block.output.append(self.clinic.get_destination(name).dump())
3406
3407 def directive_print(self, *args):
3408 self.block.output.append(' '.join(args))
3409 self.block.output.append('\n')
3410
3411 def directive_preserve(self):
3412 if self.preserve_output:
3413 fail("Can't have preserve twice in one block!")
3414 self.preserve_output = True
3415
Larry Hastings31826802013-10-19 00:09:25 -07003416 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003417 if self.kind is not CALLABLE:
3418 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003419 self.kind = CLASS_METHOD
3420
3421 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003422 if self.kind is not CALLABLE:
3423 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003424 self.kind = STATIC_METHOD
3425
3426 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003427 if self.coexist:
3428 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07003429 self.coexist = True
3430
3431 def parse(self, block):
3432 self.reset()
3433 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08003434 self.saved_output = self.block.output
3435 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07003436 block_start = self.clinic.block_parser.line_number
3437 lines = block.input.split('\n')
3438 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
3439 if '\t' in line:
3440 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
3441 self.state(line)
3442
3443 self.next(self.state_terminal)
3444 self.state(None)
3445
Larry Hastingsbebf7352014-01-17 17:47:17 -08003446 block.output.extend(self.clinic.language.render(clinic, block.signatures))
3447
3448 if self.preserve_output:
3449 if block.output:
3450 fail("'preserve' only works for blocks that don't produce any output!")
3451 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07003452
3453 @staticmethod
3454 def ignore_line(line):
3455 # ignore comment-only lines
3456 if line.lstrip().startswith('#'):
3457 return True
3458
3459 # Ignore empty lines too
3460 # (but not in docstring sections!)
3461 if not line.strip():
3462 return True
3463
3464 return False
3465
3466 @staticmethod
3467 def calculate_indent(line):
3468 return len(line) - len(line.strip())
3469
3470 def next(self, state, line=None):
3471 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3472 self.state = state
3473 if line is not None:
3474 self.state(line)
3475
3476 def state_dsl_start(self, line):
3477 # self.block = self.ClinicOutputBlock(self)
3478 if self.ignore_line(line):
3479 return
Larry Hastings7726ac92014-01-31 22:03:12 -08003480
3481 # is it a directive?
3482 fields = shlex.split(line)
3483 directive_name = fields[0]
3484 directive = self.directives.get(directive_name, None)
3485 if directive:
3486 try:
3487 directive(*fields[1:])
3488 except TypeError as e:
3489 fail(str(e))
3490 return
3491
Larry Hastings31826802013-10-19 00:09:25 -07003492 self.next(self.state_modulename_name, line)
3493
3494 def state_modulename_name(self, line):
3495 # looking for declaration, which establishes the leftmost column
3496 # line should be
3497 # modulename.fnname [as c_basename] [-> return annotation]
3498 # square brackets denote optional syntax.
3499 #
Larry Hastings4a714d42014-01-14 22:22:41 -08003500 # alternatively:
3501 # modulename.fnname [as c_basename] = modulename.existing_fn_name
3502 # clones the parameters and return converter from that
3503 # function. you can't modify them. you must enter a
3504 # new docstring.
3505 #
Larry Hastings31826802013-10-19 00:09:25 -07003506 # (but we might find a directive first!)
3507 #
3508 # this line is permitted to start with whitespace.
3509 # we'll call this number of spaces F (for "function").
3510
3511 if not line.strip():
3512 return
3513
3514 self.indent.infer(line)
3515
Larry Hastings4a714d42014-01-14 22:22:41 -08003516 # are we cloning?
3517 before, equals, existing = line.rpartition('=')
3518 if equals:
3519 full_name, _, c_basename = before.partition(' as ')
3520 full_name = full_name.strip()
3521 c_basename = c_basename.strip()
3522 existing = existing.strip()
3523 if (is_legal_py_identifier(full_name) and
3524 (not c_basename or is_legal_c_identifier(c_basename)) and
3525 is_legal_py_identifier(existing)):
3526 # we're cloning!
3527 fields = [x.strip() for x in existing.split('.')]
3528 function_name = fields.pop()
3529 module, cls = self.clinic._module_and_class(fields)
3530
3531 for existing_function in (cls or module).functions:
3532 if existing_function.name == function_name:
3533 break
3534 else:
3535 existing_function = None
3536 if not existing_function:
Larry Hastings7726ac92014-01-31 22:03:12 -08003537 print("class", cls, "module", module, "existing", existing)
Larry Hastingsc2047262014-01-25 20:43:29 -08003538 print("cls. functions", cls.functions)
Larry Hastings4a714d42014-01-14 22:22:41 -08003539 fail("Couldn't find existing function " + repr(existing) + "!")
3540
3541 fields = [x.strip() for x in full_name.split('.')]
3542 function_name = fields.pop()
3543 module, cls = self.clinic._module_and_class(fields)
3544
3545 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3546 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
Larry Hastings7726ac92014-01-31 22:03:12 -08003547 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 -08003548
3549 self.block.signatures.append(self.function)
3550 (cls or module).functions.append(self.function)
3551 self.next(self.state_function_docstring)
3552 return
3553
Larry Hastings31826802013-10-19 00:09:25 -07003554 line, _, returns = line.partition('->')
3555
3556 full_name, _, c_basename = line.partition(' as ')
3557 full_name = full_name.strip()
3558 c_basename = c_basename.strip() or None
3559
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003560 if not is_legal_py_identifier(full_name):
3561 fail("Illegal function name: {}".format(full_name))
3562 if c_basename and not is_legal_c_identifier(c_basename):
3563 fail("Illegal C basename: {}".format(c_basename))
3564
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003565 return_converter = None
3566 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003567 ast_input = "def x() -> {}: pass".format(returns)
3568 module = None
3569 try:
3570 module = ast.parse(ast_input)
3571 except SyntaxError:
3572 pass
3573 if not module:
3574 fail("Badly-formed annotation for " + full_name + ": " + returns)
3575 try:
3576 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003577 if legacy:
3578 fail("Legacy converter {!r} not allowed as a return converter"
3579 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003580 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003581 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003582 return_converter = return_converters[name](**kwargs)
3583 except ValueError:
3584 fail("Badly-formed annotation for " + full_name + ": " + returns)
3585
3586 fields = [x.strip() for x in full_name.split('.')]
3587 function_name = fields.pop()
3588 module, cls = self.clinic._module_and_class(fields)
3589
Larry Hastings8666e652014-01-12 14:12:59 -08003590 fields = full_name.split('.')
3591 if fields[-1] == '__new__':
3592 if (self.kind != CLASS_METHOD) or (not cls):
3593 fail("__new__ must be a class method!")
3594 self.kind = METHOD_NEW
3595 elif fields[-1] == '__init__':
3596 if (self.kind != CALLABLE) or (not cls):
3597 fail("__init__ must be a normal method, not a class or static method!")
3598 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003599 if not return_converter:
3600 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003601 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003602 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003603
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003604 if not return_converter:
3605 return_converter = CReturnConverter()
3606
Larry Hastings31826802013-10-19 00:09:25 -07003607 if not module:
3608 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3609 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3610 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3611 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003612
3613 # insert a self converter automatically
Larry Hastingsc2047262014-01-25 20:43:29 -08003614 type, name = correct_name_for_self(self.function)
3615 kwargs = {}
3616 if cls and type == "PyObject *":
3617 kwargs['type'] = cls.typedef
Larry Hastings7726ac92014-01-31 22:03:12 -08003618 sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs)
Larry Hastings5c661892014-01-24 06:17:25 -08003619 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3620 self.function.parameters[sc.name] = p_self
3621
Larry Hastings4a714d42014-01-14 22:22:41 -08003622 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003623 self.next(self.state_parameters_start)
3624
3625 # Now entering the parameters section. The rules, formally stated:
3626 #
3627 # * All lines must be indented with spaces only.
3628 # * The first line must be a parameter declaration.
3629 # * The first line must be indented.
3630 # * This first line establishes the indent for parameters.
3631 # * We'll call this number of spaces P (for "parameter").
3632 # * Thenceforth:
3633 # * Lines indented with P spaces specify a parameter.
3634 # * Lines indented with > P spaces are docstrings for the previous
3635 # parameter.
3636 # * We'll call this number of spaces D (for "docstring").
3637 # * All subsequent lines indented with >= D spaces are stored as
3638 # part of the per-parameter docstring.
3639 # * All lines will have the first D spaces of the indent stripped
3640 # before they are stored.
3641 # * It's illegal to have a line starting with a number of spaces X
3642 # such that P < X < D.
3643 # * A line with < P spaces is the first line of the function
3644 # docstring, which ends processing for parameters and per-parameter
3645 # docstrings.
3646 # * The first line of the function docstring must be at the same
3647 # indent as the function declaration.
3648 # * It's illegal to have any line in the parameters section starting
3649 # with X spaces such that F < X < P. (As before, F is the indent
3650 # of the function declaration.)
3651 #
Larry Hastings31826802013-10-19 00:09:25 -07003652 # Also, currently Argument Clinic places the following restrictions on groups:
3653 # * Each group must contain at least one parameter.
3654 # * Each group may contain at most one group, which must be the furthest
3655 # thing in the group from the required parameters. (The nested group
3656 # must be the first in the group when it's before the required
3657 # parameters, and the last thing in the group when after the required
3658 # parameters.)
3659 # * There may be at most one (top-level) group to the left or right of
3660 # the required parameters.
3661 # * You must specify a slash, and it must be after all parameters.
3662 # (In other words: either all parameters are positional-only,
3663 # or none are.)
3664 #
3665 # Said another way:
3666 # * Each group must contain at least one parameter.
3667 # * All left square brackets before the required parameters must be
3668 # consecutive. (You can't have a left square bracket followed
3669 # by a parameter, then another left square bracket. You can't
3670 # have a left square bracket, a parameter, a right square bracket,
3671 # and then a left square bracket.)
3672 # * All right square brackets after the required parameters must be
3673 # consecutive.
3674 #
3675 # These rules are enforced with a single state variable:
3676 # "parameter_state". (Previously the code was a miasma of ifs and
3677 # separate boolean state variables.) The states are:
3678 #
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03003679 # [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ] <- line
3680 # 01 2 3 4 5 6 <- state transitions
Larry Hastings31826802013-10-19 00:09:25 -07003681 #
3682 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3683 # 1: ps_left_square_before. left square brackets before required parameters.
3684 # 2: ps_group_before. in a group, before required parameters.
Larry Hastingsc2047262014-01-25 20:43:29 -08003685 # 3: ps_required. required parameters, positional-or-keyword or positional-only
3686 # (we don't know yet). (renumber left groups!)
3687 # 4: ps_optional. positional-or-keyword or positional-only parameters that
3688 # now must have default values.
3689 # 5: ps_group_after. in a group, after required parameters.
3690 # 6: ps_right_square_after. right square brackets after required parameters.
Larry Hastings31826802013-10-19 00:09:25 -07003691 ps_start, ps_left_square_before, ps_group_before, ps_required, \
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03003692 ps_optional, ps_group_after, ps_right_square_after = range(7)
Larry Hastings31826802013-10-19 00:09:25 -07003693
3694 def state_parameters_start(self, line):
3695 if self.ignore_line(line):
3696 return
3697
3698 # if this line is not indented, we have no parameters
3699 if not self.indent.infer(line):
3700 return self.next(self.state_function_docstring, line)
3701
Larry Hastings2a727912014-01-16 11:32:01 -08003702 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003703 return self.next(self.state_parameter, line)
3704
3705
3706 def to_required(self):
3707 """
3708 Transition to the "required" parameter state.
3709 """
3710 if self.parameter_state != self.ps_required:
3711 self.parameter_state = self.ps_required
3712 for p in self.function.parameters.values():
3713 p.group = -p.group
3714
3715 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003716 if self.parameter_continuation:
3717 line = self.parameter_continuation + ' ' + line.lstrip()
3718 self.parameter_continuation = ''
3719
Larry Hastings31826802013-10-19 00:09:25 -07003720 if self.ignore_line(line):
3721 return
3722
3723 assert self.indent.depth == 2
3724 indent = self.indent.infer(line)
3725 if indent == -1:
3726 # we outdented, must be to definition column
3727 return self.next(self.state_function_docstring, line)
3728
3729 if indent == 1:
3730 # we indented, must be to new parameter docstring column
3731 return self.next(self.state_parameter_docstring_start, line)
3732
Larry Hastings2a727912014-01-16 11:32:01 -08003733 line = line.rstrip()
3734 if line.endswith('\\'):
3735 self.parameter_continuation = line[:-1]
3736 return
3737
Larry Hastings31826802013-10-19 00:09:25 -07003738 line = line.lstrip()
3739
3740 if line in ('*', '/', '[', ']'):
3741 self.parse_special_symbol(line)
3742 return
3743
3744 if self.parameter_state in (self.ps_start, self.ps_required):
3745 self.to_required()
3746 elif self.parameter_state == self.ps_left_square_before:
3747 self.parameter_state = self.ps_group_before
3748 elif self.parameter_state == self.ps_group_before:
3749 if not self.group:
3750 self.to_required()
Larry Hastingsc2047262014-01-25 20:43:29 -08003751 elif self.parameter_state in (self.ps_group_after, self.ps_optional):
Larry Hastings31826802013-10-19 00:09:25 -07003752 pass
3753 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003754 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
Larry Hastings31826802013-10-19 00:09:25 -07003755
Larry Hastings7726ac92014-01-31 22:03:12 -08003756 # handle "as" for parameters too
3757 c_name = None
3758 name, have_as_token, trailing = line.partition(' as ')
3759 if have_as_token:
3760 name = name.strip()
3761 if ' ' not in name:
3762 fields = trailing.strip().split(' ')
3763 if not fields:
3764 fail("Invalid 'as' clause!")
3765 c_name = fields[0]
3766 if c_name.endswith(':'):
3767 name += ':'
3768 c_name = c_name[:-1]
3769 fields[0] = name
3770 line = ' '.join(fields)
3771
Larry Hastings2a727912014-01-16 11:32:01 -08003772 base, equals, default = line.rpartition('=')
3773 if not equals:
3774 base = default
3775 default = None
Larry Hastingsc2047262014-01-25 20:43:29 -08003776
Larry Hastings31826802013-10-19 00:09:25 -07003777 module = None
3778 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003779 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003780 module = ast.parse(ast_input)
3781 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003782 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08003783 # the last = was probably inside a function call, like
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003784 # c: int(accept={str})
Larry Hastingsc2047262014-01-25 20:43:29 -08003785 # so assume there was no actual default value.
Larry Hastings2a727912014-01-16 11:32:01 -08003786 default = None
3787 ast_input = "def x({}): pass".format(line)
3788 module = ast.parse(ast_input)
3789 except SyntaxError:
3790 pass
Larry Hastings31826802013-10-19 00:09:25 -07003791 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003792 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003793
3794 function_args = module.body[0].args
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003795
3796 if len(function_args.args) > 1:
3797 fail("Function " + self.function.name + " has an invalid parameter declaration (comma?):\n\t" + line)
3798 if function_args.defaults or function_args.kw_defaults:
3799 fail("Function " + self.function.name + " has an invalid parameter declaration (default value?):\n\t" + line)
3800 if function_args.vararg or function_args.kwarg:
3801 fail("Function " + self.function.name + " has an invalid parameter declaration (*args? **kwargs?):\n\t" + line)
3802
Larry Hastings31826802013-10-19 00:09:25 -07003803 parameter = function_args.args[0]
3804
Larry Hastings16c51912014-01-07 11:53:01 -08003805 parameter_name = parameter.arg
3806 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3807
Larry Hastings2a727912014-01-16 11:32:01 -08003808 if not default:
Larry Hastingsc2047262014-01-25 20:43:29 -08003809 if self.parameter_state == self.ps_optional:
3810 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 -08003811 value = unspecified
3812 if 'py_default' in kwargs:
3813 fail("You can't specify py_default without specifying a default value!")
3814 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003815 if self.parameter_state == self.ps_required:
3816 self.parameter_state = self.ps_optional
Larry Hastings2a727912014-01-16 11:32:01 -08003817 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003818 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003819 ast_input = "x = {}".format(default)
Larry Hastingsc2047262014-01-25 20:43:29 -08003820 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003821 try:
3822 module = ast.parse(ast_input)
3823
Larry Hastings5c661892014-01-24 06:17:25 -08003824 if 'c_default' not in kwargs:
3825 # we can only represent very simple data values in C.
3826 # detect whether default is okay, via a blacklist
3827 # of disallowed ast nodes.
3828 class DetectBadNodes(ast.NodeVisitor):
3829 bad = False
3830 def bad_node(self, node):
3831 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003832
Larry Hastings5c661892014-01-24 06:17:25 -08003833 # inline function call
3834 visit_Call = bad_node
3835 # inline if statement ("x = 3 if y else z")
3836 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003837
Larry Hastings5c661892014-01-24 06:17:25 -08003838 # comprehensions and generator expressions
3839 visit_ListComp = visit_SetComp = bad_node
3840 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003841
Larry Hastings5c661892014-01-24 06:17:25 -08003842 # literals for advanced types
3843 visit_Dict = visit_Set = bad_node
3844 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003845
Larry Hastings5c661892014-01-24 06:17:25 -08003846 # "starred": "a = [1, 2, 3]; *a"
3847 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003848
Larry Hastings5c661892014-01-24 06:17:25 -08003849 blacklist = DetectBadNodes()
3850 blacklist.visit(module)
3851 bad = blacklist.bad
3852 else:
3853 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003854 # but at least make an attempt at ensuring it's a valid expression.
3855 try:
3856 value = eval(default)
3857 if value == unspecified:
3858 fail("'unspecified' is not a legal default value!")
3859 except NameError:
3860 pass # probably a named constant
3861 except Exception as e:
3862 fail("Malformed expression given as default value\n"
3863 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003864 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003865 fail("Unsupported expression as default value: " + repr(default))
3866
3867 expr = module.body[0].value
3868 # mild hack: explicitly support NULL as a default value
3869 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3870 value = NULL
3871 py_default = 'None'
3872 c_default = "NULL"
3873 elif (isinstance(expr, ast.BinOp) or
Serhiy Storchaka3f228112018-09-27 17:42:37 +03003874 (isinstance(expr, ast.UnaryOp) and
3875 not (isinstance(expr.operand, ast.Num) or
3876 (hasattr(ast, 'Constant') and
3877 isinstance(expr.operand, ast.Constant) and
3878 type(expr.operand.value) in (int, float, complex)))
3879 )):
Larry Hastings2a727912014-01-16 11:32:01 -08003880 c_default = kwargs.get("c_default")
3881 if not (isinstance(c_default, str) and c_default):
Serhiy Storchaka3f228112018-09-27 17:42:37 +03003882 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default." + ast.dump(expr))
Larry Hastings2a727912014-01-16 11:32:01 -08003883 py_default = default
3884 value = unknown
3885 elif isinstance(expr, ast.Attribute):
3886 a = []
3887 n = expr
3888 while isinstance(n, ast.Attribute):
3889 a.append(n.attr)
3890 n = n.value
3891 if not isinstance(n, ast.Name):
3892 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3893 a.append(n.id)
3894 py_default = ".".join(reversed(a))
3895
3896 c_default = kwargs.get("c_default")
3897 if not (isinstance(c_default, str) and c_default):
3898 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3899
3900 try:
3901 value = eval(py_default)
3902 except NameError:
3903 value = unknown
3904 else:
3905 value = ast.literal_eval(expr)
3906 py_default = repr(value)
3907 if isinstance(value, (bool, None.__class__)):
3908 c_default = "Py_" + py_default
3909 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003910 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003911 else:
3912 c_default = py_default
3913
3914 except SyntaxError as e:
3915 fail("Syntax error: " + repr(e.text))
3916 except (ValueError, AttributeError):
3917 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003918 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003919 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003920 if not (isinstance(c_default, str) and c_default):
3921 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3922
Larry Hastings2a727912014-01-16 11:32:01 -08003923 kwargs.setdefault('c_default', c_default)
3924 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003925
Larry Hastings31826802013-10-19 00:09:25 -07003926 dict = legacy_converters if legacy else converters
3927 legacy_str = "legacy " if legacy else ""
3928 if name not in dict:
3929 fail('{} is not a valid {}converter'.format(name, legacy_str))
Larry Hastings7726ac92014-01-31 22:03:12 -08003930 # if you use a c_name for the parameter, we just give that name to the converter
3931 # but the parameter object gets the python name
3932 converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
Larry Hastings31826802013-10-19 00:09:25 -07003933
3934 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003935
3936 if isinstance(converter, self_converter):
3937 if len(self.function.parameters) == 1:
3938 if (self.parameter_state != self.ps_required):
3939 fail("A 'self' parameter cannot be marked optional.")
3940 if value is not unspecified:
3941 fail("A 'self' parameter cannot have a default value.")
3942 if self.group:
3943 fail("A 'self' parameter cannot be in an optional group.")
3944 kind = inspect.Parameter.POSITIONAL_ONLY
3945 self.parameter_state = self.ps_start
3946 self.function.parameters.clear()
3947 else:
3948 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3949
Larry Hastings31826802013-10-19 00:09:25 -07003950 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003951
3952 if parameter_name in self.function.parameters:
3953 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003954 self.function.parameters[parameter_name] = p
3955
3956 def parse_converter(self, annotation):
Serhiy Storchaka3f228112018-09-27 17:42:37 +03003957 if (hasattr(ast, 'Constant') and
3958 isinstance(annotation, ast.Constant) and
3959 type(annotation.value) is str):
3960 return annotation.value, True, {}
3961
Larry Hastings31826802013-10-19 00:09:25 -07003962 if isinstance(annotation, ast.Str):
3963 return annotation.s, True, {}
3964
3965 if isinstance(annotation, ast.Name):
3966 return annotation.id, False, {}
3967
Larry Hastings4a55fc52014-01-12 11:09:57 -08003968 if not isinstance(annotation, ast.Call):
3969 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003970
3971 name = annotation.func.id
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003972 symbols = globals()
3973
3974 kwargs = {node.arg: eval_ast_expr(node.value, symbols) for node in annotation.keywords}
Larry Hastings31826802013-10-19 00:09:25 -07003975 return name, False, kwargs
3976
3977 def parse_special_symbol(self, symbol):
Larry Hastings31826802013-10-19 00:09:25 -07003978 if symbol == '*':
3979 if self.keyword_only:
3980 fail("Function " + self.function.name + " uses '*' more than once.")
3981 self.keyword_only = True
3982 elif symbol == '[':
3983 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3984 self.parameter_state = self.ps_left_square_before
3985 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3986 self.parameter_state = self.ps_group_after
3987 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003988 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
Larry Hastings31826802013-10-19 00:09:25 -07003989 self.group += 1
Larry Hastings2623c8c2014-02-08 22:15:29 -08003990 self.function.docstring_only = True
Larry Hastings31826802013-10-19 00:09:25 -07003991 elif symbol == ']':
3992 if not self.group:
3993 fail("Function " + self.function.name + " has a ] without a matching [.")
3994 if not any(p.group == self.group for p in self.function.parameters.values()):
3995 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3996 self.group -= 1
3997 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3998 self.parameter_state = self.ps_group_before
3999 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
4000 self.parameter_state = self.ps_right_square_after
4001 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08004002 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
Larry Hastings31826802013-10-19 00:09:25 -07004003 elif symbol == '/':
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03004004 if self.positional_only:
4005 fail("Function " + self.function.name + " uses '/' more than once.")
4006 self.positional_only = True
Larry Hastingsc2047262014-01-25 20:43:29 -08004007 # ps_required and ps_optional are allowed here, that allows positional-only without option groups
Larry Hastings31826802013-10-19 00:09:25 -07004008 # to work (and have default values!)
Larry Hastingsc2047262014-01-25 20:43:29 -08004009 if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
4010 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
Larry Hastings31826802013-10-19 00:09:25 -07004011 if self.keyword_only:
4012 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
Berker Peksagf23530f2014-10-19 18:04:38 +03004013 # fixup preceding parameters
Larry Hastings31826802013-10-19 00:09:25 -07004014 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08004015 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07004016 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
4017 p.kind = inspect.Parameter.POSITIONAL_ONLY
4018
4019 def state_parameter_docstring_start(self, line):
4020 self.parameter_docstring_indent = len(self.indent.margin)
4021 assert self.indent.depth == 3
4022 return self.next(self.state_parameter_docstring, line)
4023
4024 # every line of the docstring must start with at least F spaces,
4025 # where F > P.
4026 # these F spaces will be stripped.
4027 def state_parameter_docstring(self, line):
4028 stripped = line.strip()
4029 if stripped.startswith('#'):
4030 return
4031
4032 indent = self.indent.measure(line)
4033 if indent < self.parameter_docstring_indent:
4034 self.indent.infer(line)
4035 assert self.indent.depth < 3
4036 if self.indent.depth == 2:
4037 # back to a parameter
4038 return self.next(self.state_parameter, line)
4039 assert self.indent.depth == 1
4040 return self.next(self.state_function_docstring, line)
4041
4042 assert self.function.parameters
4043 last_parameter = next(reversed(list(self.function.parameters.values())))
4044
4045 new_docstring = last_parameter.docstring
4046
4047 if new_docstring:
4048 new_docstring += '\n'
4049 if stripped:
4050 new_docstring += self.indent.dedent(line)
4051
4052 last_parameter.docstring = new_docstring
4053
4054 # the final stanza of the DSL is the docstring.
4055 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07004056 if self.group:
4057 fail("Function " + self.function.name + " has a ] without a matching [.")
4058
4059 stripped = line.strip()
4060 if stripped.startswith('#'):
4061 return
4062
4063 new_docstring = self.function.docstring
4064 if new_docstring:
4065 new_docstring += "\n"
4066 if stripped:
4067 line = self.indent.dedent(line).rstrip()
4068 else:
4069 line = ''
4070 new_docstring += line
4071 self.function.docstring = new_docstring
4072
4073 def format_docstring(self):
4074 f = self.function
4075
Larry Hastings5c661892014-01-24 06:17:25 -08004076 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
4077 if new_or_init and not f.docstring:
4078 # don't render a docstring at all, no signature, nothing.
4079 return f.docstring
4080
Larry Hastings2623c8c2014-02-08 22:15:29 -08004081 text, add, output = _text_accumulator()
Larry Hastings7726ac92014-01-31 22:03:12 -08004082 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07004083
4084 ##
4085 ## docstring first line
4086 ##
4087
Larry Hastings2623c8c2014-02-08 22:15:29 -08004088 if new_or_init:
4089 # classes get *just* the name of the class
4090 # not __new__, not __init__, and not module.classname
4091 assert f.cls
4092 add(f.cls.name)
Larry Hastings46258262014-01-22 03:05:49 -08004093 else:
Larry Hastings2623c8c2014-02-08 22:15:29 -08004094 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07004095 add('(')
4096
4097 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08004098 assert parameters, "We should always have a self parameter. " + repr(f)
4099 assert isinstance(parameters[0].converter, self_converter)
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03004100 # self is always positional-only.
4101 assert parameters[0].is_positional_only()
Larry Hastings5c661892014-01-24 06:17:25 -08004102 parameters[0].right_bracket_count = 0
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03004103 positional_only = True
4104 for p in parameters[1:]:
4105 if not p.is_positional_only():
4106 positional_only = False
4107 else:
4108 assert positional_only
4109 if positional_only:
4110 p.right_bracket_count = abs(p.group)
Larry Hastings31826802013-10-19 00:09:25 -07004111 else:
4112 # don't put any right brackets around non-positional-only parameters, ever.
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03004113 p.right_bracket_count = 0
Larry Hastings31826802013-10-19 00:09:25 -07004114
4115 right_bracket_count = 0
4116
4117 def fix_right_bracket_count(desired):
4118 nonlocal right_bracket_count
4119 s = ''
4120 while right_bracket_count < desired:
4121 s += '['
4122 right_bracket_count += 1
4123 while right_bracket_count > desired:
4124 s += ']'
4125 right_bracket_count -= 1
4126 return s
4127
Larry Hastings2623c8c2014-02-08 22:15:29 -08004128 need_slash = False
4129 added_slash = False
4130 need_a_trailing_slash = False
4131
4132 # we only need a trailing slash:
4133 # * if this is not a "docstring_only" signature
4134 # * and if the last *shown* parameter is
4135 # positional only
4136 if not f.docstring_only:
4137 for p in reversed(parameters):
4138 if not p.converter.show_in_signature:
4139 continue
4140 if p.is_positional_only():
4141 need_a_trailing_slash = True
4142 break
4143
4144
Larry Hastings31826802013-10-19 00:09:25 -07004145 added_star = False
Larry Hastings2623c8c2014-02-08 22:15:29 -08004146
4147 first_parameter = True
4148 last_p = parameters[-1]
4149 line_length = len(''.join(text))
4150 indent = " " * line_length
4151 def add_parameter(text):
4152 nonlocal line_length
4153 nonlocal first_parameter
4154 if first_parameter:
4155 s = text
4156 first_parameter = False
4157 else:
4158 s = ' ' + text
4159 if line_length + len(s) >= 72:
4160 add('\n')
4161 add(indent)
4162 line_length = len(indent)
4163 s = text
4164 line_length += len(s)
4165 add(s)
Larry Hastings31826802013-10-19 00:09:25 -07004166
4167 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08004168 if not p.converter.show_in_signature:
4169 continue
Larry Hastings31826802013-10-19 00:09:25 -07004170 assert p.name
4171
Larry Hastings2623c8c2014-02-08 22:15:29 -08004172 is_self = isinstance(p.converter, self_converter)
4173 if is_self and f.docstring_only:
4174 # this isn't a real machine-parsable signature,
4175 # so let's not print the "self" parameter
4176 continue
4177
4178 if p.is_positional_only():
4179 need_slash = not f.docstring_only
4180 elif need_slash and not (added_slash or p.is_positional_only()):
4181 added_slash = True
4182 add_parameter('/,')
4183
Larry Hastings31826802013-10-19 00:09:25 -07004184 if p.is_keyword_only() and not added_star:
4185 added_star = True
Larry Hastings2623c8c2014-02-08 22:15:29 -08004186 add_parameter('*,')
4187
4188 p_add, p_output = text_accumulator()
4189 p_add(fix_right_bracket_count(p.right_bracket_count))
4190
4191 if isinstance(p.converter, self_converter):
4192 # annotate first parameter as being a "self".
4193 #
4194 # if inspect.Signature gets this function,
4195 # and it's already bound, the self parameter
4196 # will be stripped off.
4197 #
4198 # if it's not bound, it should be marked
4199 # as positional-only.
4200 #
4201 # note: we don't print "self" for __init__,
4202 # because this isn't actually the signature
4203 # for __init__. (it can't be, __init__ doesn't
4204 # have a docstring.) if this is an __init__
4205 # (or __new__), then this signature is for
Berker Peksagf23530f2014-10-19 18:04:38 +03004206 # calling the class to construct a new instance.
Larry Hastings2623c8c2014-02-08 22:15:29 -08004207 p_add('$')
Larry Hastings31826802013-10-19 00:09:25 -07004208
Larry Hastings5c661892014-01-24 06:17:25 -08004209 name = p.converter.signature_name or p.name
Larry Hastings2623c8c2014-02-08 22:15:29 -08004210 p_add(name)
Larry Hastings581ee362014-01-28 05:00:08 -08004211
Larry Hastings31826802013-10-19 00:09:25 -07004212 if p.converter.is_optional():
Larry Hastings2623c8c2014-02-08 22:15:29 -08004213 p_add('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08004214 value = p.converter.py_default
4215 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08004216 value = repr(p.converter.default)
Larry Hastings2623c8c2014-02-08 22:15:29 -08004217 p_add(value)
4218
4219 if (p != last_p) or need_a_trailing_slash:
4220 p_add(',')
4221
4222 add_parameter(p_output())
Larry Hastings31826802013-10-19 00:09:25 -07004223
4224 add(fix_right_bracket_count(0))
Larry Hastings2623c8c2014-02-08 22:15:29 -08004225 if need_a_trailing_slash:
4226 add_parameter('/')
Larry Hastings31826802013-10-19 00:09:25 -07004227 add(')')
4228
Larry Hastings2a727912014-01-16 11:32:01 -08004229 # PEP 8 says:
4230 #
4231 # The Python standard library will not use function annotations
4232 # as that would result in a premature commitment to a particular
4233 # annotation style. Instead, the annotations are left for users
4234 # to discover and experiment with useful annotation styles.
4235 #
4236 # therefore this is commented out:
4237 #
4238 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004239 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08004240 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07004241
Larry Hastings2623c8c2014-02-08 22:15:29 -08004242 if not f.docstring_only:
Zachary Ware8ef887c2015-04-13 18:22:35 -05004243 add("\n" + sig_end_marker + "\n")
Larry Hastings2623c8c2014-02-08 22:15:29 -08004244
Larry Hastings31826802013-10-19 00:09:25 -07004245 docstring_first_line = output()
4246
4247 # now fix up the places where the brackets look wrong
4248 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
4249
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004250 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07004251 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004252 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07004253 for p in parameters:
4254 if not p.docstring.strip():
4255 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004256 if spacer_line:
4257 add('\n')
4258 else:
4259 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07004260 add(" ")
4261 add(p.name)
4262 add('\n')
4263 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004264 parameters = output()
4265 if parameters:
4266 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07004267
4268 ##
4269 ## docstring body
4270 ##
4271
4272 docstring = f.docstring.rstrip()
4273 lines = [line.rstrip() for line in docstring.split('\n')]
4274
4275 # Enforce the summary line!
4276 # The first line of a docstring should be a summary of the function.
4277 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
4278 # by itself.
4279 #
4280 # Argument Clinic enforces the following rule:
4281 # * either the docstring is empty,
4282 # * or it must have a summary line.
4283 #
4284 # Guido said Clinic should enforce this:
4285 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
4286
4287 if len(lines) >= 2:
4288 if lines[1]:
4289 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
4290 "Every non-blank function docstring must start with\n" +
4291 "a single line summary followed by an empty line.")
4292 elif len(lines) == 1:
4293 # the docstring is only one line right now--the summary line.
4294 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004295 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07004296 lines.append('')
4297
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004298 parameters_marker_count = len(docstring.split('{parameters}')) - 1
4299 if parameters_marker_count > 1:
4300 fail('You may not specify {parameters} more than once in a docstring!')
4301
4302 if not parameters_marker_count:
4303 # insert after summary line
4304 lines.insert(2, '{parameters}')
4305
4306 # insert at front of docstring
4307 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07004308
4309 docstring = "\n".join(lines)
4310
4311 add(docstring)
4312 docstring = output()
4313
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004314 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07004315 docstring = docstring.rstrip()
4316
4317 return docstring
4318
4319 def state_terminal(self, line):
4320 """
4321 Called when processing the block is done.
4322 """
4323 assert not line
4324
4325 if not self.function:
4326 return
4327
4328 if self.keyword_only:
4329 values = self.function.parameters.values()
4330 if not values:
4331 no_parameter_after_star = True
4332 else:
4333 last_parameter = next(reversed(list(values)))
4334 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
4335 if no_parameter_after_star:
4336 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
4337
4338 # remove trailing whitespace from all parameter docstrings
4339 for name, value in self.function.parameters.items():
4340 if not value:
4341 continue
4342 value.docstring = value.docstring.rstrip()
4343
4344 self.function.docstring = self.format_docstring()
4345
4346
Larry Hastings5c661892014-01-24 06:17:25 -08004347
4348
Larry Hastings31826802013-10-19 00:09:25 -07004349# maps strings to callables.
4350# the callable should return an object
4351# that implements the clinic parser
4352# interface (__init__ and parse).
4353#
4354# example parsers:
4355# "clinic", handles the Clinic DSL
4356# "python", handles running Python code
4357#
4358parsers = {'clinic' : DSLParser, 'python': PythonParser}
4359
4360
4361clinic = None
4362
4363
4364def main(argv):
4365 import sys
4366
4367 if sys.version_info.major < 3 or sys.version_info.minor < 3:
4368 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
4369
4370 import argparse
4371 cmdline = argparse.ArgumentParser()
4372 cmdline.add_argument("-f", "--force", action='store_true')
4373 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08004374 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004375 cmdline.add_argument("--converters", action='store_true')
Gregory P. Smith178418a2017-05-27 16:40:45 -07004376 cmdline.add_argument("--make", action='store_true',
4377 help="Walk --srcdir to run over all relevant files.")
4378 cmdline.add_argument("--srcdir", type=str, default=os.curdir,
4379 help="The directory tree to walk in --make mode.")
Larry Hastings31826802013-10-19 00:09:25 -07004380 cmdline.add_argument("filename", type=str, nargs="*")
4381 ns = cmdline.parse_args(argv)
4382
4383 if ns.converters:
4384 if ns.filename:
4385 print("Usage error: can't specify --converters and a filename at the same time.")
4386 print()
4387 cmdline.print_usage()
4388 sys.exit(-1)
4389 converters = []
4390 return_converters = []
4391 ignored = set("""
4392 add_c_converter
4393 add_c_return_converter
4394 add_default_legacy_c_converter
4395 add_legacy_c_converter
4396 """.strip().split())
4397 module = globals()
4398 for name in module:
4399 for suffix, ids in (
4400 ("_return_converter", return_converters),
4401 ("_converter", converters),
4402 ):
4403 if name in ignored:
4404 continue
4405 if name.endswith(suffix):
4406 ids.append((name, name[:-len(suffix)]))
4407 break
4408 print()
4409
4410 print("Legacy converters:")
4411 legacy = sorted(legacy_converters)
4412 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
4413 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
4414 print()
4415
4416 for title, attribute, ids in (
4417 ("Converters", 'converter_init', converters),
4418 ("Return converters", 'return_converter_init', return_converters),
4419 ):
4420 print(title + ":")
4421 longest = -1
4422 for name, short_name in ids:
4423 longest = max(longest, len(short_name))
4424 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
4425 cls = module[name]
4426 callable = getattr(cls, attribute, None)
4427 if not callable:
4428 continue
4429 signature = inspect.signature(callable)
4430 parameters = []
4431 for parameter_name, parameter in signature.parameters.items():
4432 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
4433 if parameter.default != inspect.Parameter.empty:
4434 s = '{}={!r}'.format(parameter_name, parameter.default)
4435 else:
4436 s = parameter_name
4437 parameters.append(s)
4438 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07004439 print()
Larry Hastings2a727912014-01-16 11:32:01 -08004440 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
4441 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07004442 sys.exit(0)
4443
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004444 if ns.make:
4445 if ns.output or ns.filename:
4446 print("Usage error: can't use -o or filenames with --make.")
4447 print()
4448 cmdline.print_usage()
4449 sys.exit(-1)
Gregory P. Smith178418a2017-05-27 16:40:45 -07004450 if not ns.srcdir:
4451 print("Usage error: --srcdir must not be empty with --make.")
4452 print()
4453 cmdline.print_usage()
4454 sys.exit(-1)
4455 for root, dirs, files in os.walk(ns.srcdir):
Zachary Warebbbbe7e2015-04-13 18:33:41 -05004456 for rcs_dir in ('.svn', '.git', '.hg', 'build', 'externals'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004457 if rcs_dir in dirs:
4458 dirs.remove(rcs_dir)
4459 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08004460 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004461 continue
4462 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08004463 if ns.verbose:
4464 print(path)
Larry Hastings581ee362014-01-28 05:00:08 -08004465 parse_file(path, force=ns.force, verify=not ns.force)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004466 return
4467
Larry Hastings31826802013-10-19 00:09:25 -07004468 if not ns.filename:
4469 cmdline.print_usage()
4470 sys.exit(-1)
4471
4472 if ns.output and len(ns.filename) > 1:
4473 print("Usage error: can't use -o with multiple filenames.")
4474 print()
4475 cmdline.print_usage()
4476 sys.exit(-1)
4477
4478 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08004479 if ns.verbose:
4480 print(filename)
Larry Hastings581ee362014-01-28 05:00:08 -08004481 parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
Larry Hastings31826802013-10-19 00:09:25 -07004482
4483
4484if __name__ == "__main__":
4485 sys.exit(main(sys.argv[1:]))