blob: c964093fc592a4a9a2751cc9bea6648d11528974 [file] [log] [blame]
Larry Hastings31826802013-10-19 00:09:25 -07001#!/usr/bin/env python3
2#
3# Argument Clinic
4# Copyright 2012-2013 by Larry Hastings.
5# Licensed to the PSF under a contributor agreement.
6#
7
8import abc
9import ast
10import atexit
Larry Hastings31826802013-10-19 00:09:25 -070011import collections
12import contextlib
Larry Hastings7726ac92014-01-31 22:03:12 -080013import copy
14import cpp
Larry Hastings31826802013-10-19 00:09:25 -070015import functools
16import hashlib
17import inspect
18import io
19import itertools
20import os
Larry Hastingsbebf7352014-01-17 17:47:17 -080021import pprint
Larry Hastings31826802013-10-19 00:09:25 -070022import re
23import shlex
Larry Hastings581ee362014-01-28 05:00:08 -080024import string
Larry Hastings31826802013-10-19 00:09:25 -070025import sys
26import tempfile
27import textwrap
Georg Brandlaabebde2014-01-16 06:53:54 +010028import traceback
Larry Hastingsdbfdc382015-05-04 06:59:46 -070029import types
Larry Hastingsbebf7352014-01-17 17:47:17 -080030import uuid
Larry Hastings31826802013-10-19 00:09:25 -070031
Larry Hastingsdbfdc382015-05-04 06:59:46 -070032from types import *
33NoneType = type(None)
34
Larry Hastings31826802013-10-19 00:09:25 -070035# TODO:
Larry Hastings31826802013-10-19 00:09:25 -070036#
37# soon:
38#
39# * allow mixing any two of {positional-only, positional-or-keyword,
40# keyword-only}
41# * dict constructor uses positional-only and keyword-only
42# * max and min use positional only with an optional group
43# and keyword-only
44#
Larry Hastings31826802013-10-19 00:09:25 -070045
Larry Hastingsebdcb502013-11-23 14:54:00 -080046version = '1'
47
Larry Hastings31826802013-10-19 00:09:25 -070048_empty = inspect._empty
49_void = inspect._void
50
Larry Hastings4a55fc52014-01-12 11:09:57 -080051NoneType = type(None)
Larry Hastings31826802013-10-19 00:09:25 -070052
53class Unspecified:
54 def __repr__(self):
55 return '<Unspecified>'
56
57unspecified = Unspecified()
58
59
60class Null:
61 def __repr__(self):
62 return '<Null>'
63
64NULL = Null()
65
66
Larry Hastings2a727912014-01-16 11:32:01 -080067class Unknown:
68 def __repr__(self):
69 return '<Unknown>'
70
71unknown = Unknown()
72
Zachary Ware8ef887c2015-04-13 18:22:35 -050073sig_end_marker = '--'
74
Larry Hastings2a727912014-01-16 11:32:01 -080075
Larry Hastings0759f842015-04-03 13:09:02 -070076_text_accumulator_nt = collections.namedtuple("_text_accumulator", "text append output")
77
Larry Hastings31826802013-10-19 00:09:25 -070078def _text_accumulator():
79 text = []
80 def output():
81 s = ''.join(text)
82 text.clear()
83 return s
Larry Hastings0759f842015-04-03 13:09:02 -070084 return _text_accumulator_nt(text, text.append, output)
Larry Hastings31826802013-10-19 00:09:25 -070085
86
Larry Hastings0759f842015-04-03 13:09:02 -070087text_accumulator_nt = collections.namedtuple("text_accumulator", "text append")
88
Larry Hastings31826802013-10-19 00:09:25 -070089def text_accumulator():
90 """
91 Creates a simple text accumulator / joiner.
92
93 Returns a pair of callables:
94 append, output
95 "append" appends a string to the accumulator.
96 "output" returns the contents of the accumulator
97 joined together (''.join(accumulator)) and
98 empties the accumulator.
99 """
100 text, append, output = _text_accumulator()
Larry Hastings0759f842015-04-03 13:09:02 -0700101 return text_accumulator_nt(append, output)
Larry Hastings31826802013-10-19 00:09:25 -0700102
103
Larry Hastingsbebf7352014-01-17 17:47:17 -0800104def warn_or_fail(fail=False, *args, filename=None, line_number=None):
Larry Hastings31826802013-10-19 00:09:25 -0700105 joined = " ".join([str(a) for a in args])
106 add, output = text_accumulator()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800107 if fail:
108 add("Error")
109 else:
110 add("Warning")
Larry Hastings31826802013-10-19 00:09:25 -0700111 if clinic:
112 if filename is None:
113 filename = clinic.filename
Larry Hastings581ee362014-01-28 05:00:08 -0800114 if getattr(clinic, 'block_parser', None) and (line_number is None):
Larry Hastings31826802013-10-19 00:09:25 -0700115 line_number = clinic.block_parser.line_number
116 if filename is not None:
117 add(' in file "' + filename + '"')
118 if line_number is not None:
119 add(" on line " + str(line_number))
120 add(':\n')
121 add(joined)
122 print(output())
Larry Hastingsbebf7352014-01-17 17:47:17 -0800123 if fail:
124 sys.exit(-1)
Larry Hastings31826802013-10-19 00:09:25 -0700125
126
Larry Hastingsbebf7352014-01-17 17:47:17 -0800127def warn(*args, filename=None, line_number=None):
128 return warn_or_fail(False, *args, filename=filename, line_number=line_number)
129
130def fail(*args, filename=None, line_number=None):
131 return warn_or_fail(True, *args, filename=filename, line_number=line_number)
132
Larry Hastings31826802013-10-19 00:09:25 -0700133
134def quoted_for_c_string(s):
135 for old, new in (
Zachary Ware9d7849f2014-01-25 03:26:20 -0600136 ('\\', '\\\\'), # must be first!
Larry Hastings31826802013-10-19 00:09:25 -0700137 ('"', '\\"'),
138 ("'", "\\'"),
139 ):
140 s = s.replace(old, new)
141 return s
142
Larry Hastings4903e002014-01-18 00:26:16 -0800143def c_repr(s):
144 return '"' + s + '"'
145
146
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700147is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
148
149def is_legal_py_identifier(s):
150 return all(is_legal_c_identifier(field) for field in s.split('.'))
151
Larry Hastingsbebf7352014-01-17 17:47:17 -0800152# identifiers that are okay in Python but aren't a good idea in C.
153# so if they're used Argument Clinic will add "_value" to the end
154# of the name in C.
Larry Hastings31826802013-10-19 00:09:25 -0700155c_keywords = set("""
Larry Hastings5c661892014-01-24 06:17:25 -0800156asm auto break case char const continue default do double
157else enum extern float for goto if inline int long
158register return short signed sizeof static struct switch
Larry Hastingsbebf7352014-01-17 17:47:17 -0800159typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700160""".strip().split())
161
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700162def ensure_legal_c_identifier(s):
163 # for now, just complain if what we're given isn't legal
164 if not is_legal_c_identifier(s):
165 fail("Illegal C identifier: {}".format(s))
166 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700167 if s in c_keywords:
168 return s + "_value"
169 return s
170
171def rstrip_lines(s):
172 text, add, output = _text_accumulator()
173 for line in s.split('\n'):
174 add(line.rstrip())
175 add('\n')
176 text.pop()
177 return output()
178
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +0300179def format_escape(s):
180 # double up curly-braces, this string will be used
181 # as part of a format_map() template later
182 s = s.replace('{', '{{')
183 s = s.replace('}', '}}')
184 return s
185
Larry Hastings31826802013-10-19 00:09:25 -0700186def linear_format(s, **kwargs):
187 """
188 Perform str.format-like substitution, except:
189 * The strings substituted must be on lines by
190 themselves. (This line is the "source line".)
191 * If the substitution text is empty, the source line
192 is removed in the output.
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800193 * If the field is not recognized, the original line
194 is passed unmodified through to the output.
Larry Hastings31826802013-10-19 00:09:25 -0700195 * If the substitution text is not empty:
196 * Each line of the substituted text is indented
197 by the indent of the source line.
198 * A newline will be added to the end.
199 """
200
201 add, output = text_accumulator()
202 for line in s.split('\n'):
203 indent, curly, trailing = line.partition('{')
204 if not curly:
205 add(line)
206 add('\n')
207 continue
208
Martin Panter4177e7c2016-02-14 03:23:13 +0000209 name, curly, trailing = trailing.partition('}')
Larry Hastings31826802013-10-19 00:09:25 -0700210 if not curly or name not in kwargs:
211 add(line)
212 add('\n')
213 continue
214
215 if trailing:
216 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
217 if indent.strip():
218 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
219
220 value = kwargs[name]
221 if not value:
222 continue
223
224 value = textwrap.indent(rstrip_lines(value), indent)
225 add(value)
226 add('\n')
227
228 return output()[:-1]
229
Larry Hastingsbebf7352014-01-17 17:47:17 -0800230def indent_all_lines(s, prefix):
231 """
232 Returns 's', with 'prefix' prepended to all lines.
233
234 If the last line is empty, prefix is not prepended
235 to it. (If s is blank, returns s unchanged.)
236
237 (textwrap.indent only adds to non-blank lines.)
238 """
239 split = s.split('\n')
240 last = split.pop()
241 final = []
242 for line in split:
243 final.append(prefix)
244 final.append(line)
245 final.append('\n')
246 if last:
247 final.append(prefix)
248 final.append(last)
249 return ''.join(final)
250
251def suffix_all_lines(s, suffix):
252 """
253 Returns 's', with 'suffix' appended to all lines.
254
255 If the last line is empty, suffix is not appended
256 to it. (If s is blank, returns s unchanged.)
257 """
258 split = s.split('\n')
259 last = split.pop()
260 final = []
261 for line in split:
262 final.append(line)
263 final.append(suffix)
264 final.append('\n')
265 if last:
266 final.append(last)
267 final.append(suffix)
268 return ''.join(final)
269
270
Larry Hastingsebdcb502013-11-23 14:54:00 -0800271def version_splitter(s):
272 """Splits a version string into a tuple of integers.
273
274 The following ASCII characters are allowed, and employ
275 the following conversions:
276 a -> -3
277 b -> -2
278 c -> -1
279 (This permits Python-style version strings such as "1.4b3".)
280 """
281 version = []
282 accumulator = []
283 def flush():
284 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800285 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800286 version.append(int(''.join(accumulator)))
287 accumulator.clear()
288
289 for c in s:
290 if c.isdigit():
291 accumulator.append(c)
292 elif c == '.':
293 flush()
294 elif c in 'abc':
295 flush()
296 version.append('abc'.index(c) - 3)
297 else:
298 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
299 flush()
300 return tuple(version)
301
302def version_comparitor(version1, version2):
303 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
304 for i, (a, b) in enumerate(iterator):
305 if a < b:
306 return -1
307 if a > b:
308 return 1
309 return 0
310
Larry Hastings31826802013-10-19 00:09:25 -0700311
312class CRenderData:
313 def __init__(self):
314
315 # The C statements to declare variables.
316 # Should be full lines with \n eol characters.
317 self.declarations = []
318
319 # The C statements required to initialize the variables before the parse call.
320 # Should be full lines with \n eol characters.
321 self.initializers = []
322
Larry Hastingsc2047262014-01-25 20:43:29 -0800323 # The C statements needed to dynamically modify the values
324 # parsed by the parse call, before calling the impl.
325 self.modifications = []
326
Larry Hastings31826802013-10-19 00:09:25 -0700327 # The entries for the "keywords" array for PyArg_ParseTuple.
328 # Should be individual strings representing the names.
329 self.keywords = []
330
331 # The "format units" for PyArg_ParseTuple.
332 # Should be individual strings that will get
333 self.format_units = []
334
335 # The varargs arguments for PyArg_ParseTuple.
336 self.parse_arguments = []
337
338 # The parameter declarations for the impl function.
339 self.impl_parameters = []
340
341 # The arguments to the impl function at the time it's called.
342 self.impl_arguments = []
343
344 # For return converters: the name of the variable that
345 # should receive the value returned by the impl.
346 self.return_value = "return_value"
347
348 # For return converters: the code to convert the return
349 # value from the parse function. This is also where
350 # you should check the _return_value for errors, and
351 # "goto exit" if there are any.
352 self.return_conversion = []
353
354 # The C statements required to clean up after the impl call.
355 self.cleanup = []
356
357
Larry Hastings581ee362014-01-28 05:00:08 -0800358class FormatCounterFormatter(string.Formatter):
359 """
360 This counts how many instances of each formatter
361 "replacement string" appear in the format string.
362
363 e.g. after evaluating "string {a}, {b}, {c}, {a}"
364 the counts dict would now look like
365 {'a': 2, 'b': 1, 'c': 1}
366 """
367 def __init__(self):
368 self.counts = collections.Counter()
369
370 def get_value(self, key, args, kwargs):
371 self.counts[key] += 1
372 return ''
373
Larry Hastings31826802013-10-19 00:09:25 -0700374class Language(metaclass=abc.ABCMeta):
375
376 start_line = ""
377 body_prefix = ""
378 stop_line = ""
379 checksum_line = ""
380
Larry Hastings7726ac92014-01-31 22:03:12 -0800381 def __init__(self, filename):
382 pass
383
Larry Hastings31826802013-10-19 00:09:25 -0700384 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800385 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700386 pass
387
Larry Hastings7726ac92014-01-31 22:03:12 -0800388 def parse_line(self, line):
389 pass
390
Larry Hastings31826802013-10-19 00:09:25 -0700391 def validate(self):
Larry Hastings581ee362014-01-28 05:00:08 -0800392 def assert_only_one(attr, *additional_fields):
393 """
394 Ensures that the string found at getattr(self, attr)
395 contains exactly one formatter replacement string for
396 each valid field. The list of valid fields is
397 ['dsl_name'] extended by additional_fields.
398
399 e.g.
400 self.fmt = "{dsl_name} {a} {b}"
401
402 # this passes
403 self.assert_only_one('fmt', 'a', 'b')
404
405 # this fails, the format string has a {b} in it
406 self.assert_only_one('fmt', 'a')
407
408 # this fails, the format string doesn't have a {c} in it
409 self.assert_only_one('fmt', 'a', 'b', 'c')
410
411 # this fails, the format string has two {a}s in it,
412 # it must contain exactly one
413 self.fmt2 = '{dsl_name} {a} {a}'
414 self.assert_only_one('fmt2', 'a')
415
416 """
417 fields = ['dsl_name']
418 fields.extend(additional_fields)
419 line = getattr(self, attr)
420 fcf = FormatCounterFormatter()
421 fcf.format(line)
422 def local_fail(should_be_there_but_isnt):
423 if should_be_there_but_isnt:
424 fail("{} {} must contain {{{}}} exactly once!".format(
425 self.__class__.__name__, attr, name))
426 else:
427 fail("{} {} must not contain {{{}}}!".format(
428 self.__class__.__name__, attr, name))
429
430 for name, count in fcf.counts.items():
431 if name in fields:
432 if count > 1:
433 local_fail(True)
434 else:
435 local_fail(False)
436 for name in fields:
437 if fcf.counts.get(name) != 1:
438 local_fail(True)
439
Larry Hastings31826802013-10-19 00:09:25 -0700440 assert_only_one('start_line')
441 assert_only_one('stop_line')
Larry Hastings31826802013-10-19 00:09:25 -0700442
Larry Hastings581ee362014-01-28 05:00:08 -0800443 field = "arguments" if "{arguments}" in self.checksum_line else "checksum"
444 assert_only_one('checksum_line', field)
Larry Hastings31826802013-10-19 00:09:25 -0700445
446
447
448class PythonLanguage(Language):
449
450 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800451 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700452 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800453 stop_line = "#[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800454 checksum_line = "#/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700455
456
457def permute_left_option_groups(l):
458 """
459 Given [1, 2, 3], should yield:
460 ()
461 (3,)
462 (2, 3)
463 (1, 2, 3)
464 """
465 yield tuple()
466 accumulator = []
467 for group in reversed(l):
468 accumulator = list(group) + accumulator
469 yield tuple(accumulator)
470
471
472def permute_right_option_groups(l):
473 """
474 Given [1, 2, 3], should yield:
475 ()
476 (1,)
477 (1, 2)
478 (1, 2, 3)
479 """
480 yield tuple()
481 accumulator = []
482 for group in l:
483 accumulator.extend(group)
484 yield tuple(accumulator)
485
486
487def permute_optional_groups(left, required, right):
488 """
489 Generator function that computes the set of acceptable
490 argument lists for the provided iterables of
491 argument groups. (Actually it generates a tuple of tuples.)
492
493 Algorithm: prefer left options over right options.
494
495 If required is empty, left must also be empty.
496 """
497 required = tuple(required)
498 result = []
499
500 if not required:
501 assert not left
502
503 accumulator = []
504 counts = set()
505 for r in permute_right_option_groups(right):
506 for l in permute_left_option_groups(left):
507 t = l + required + r
508 if len(t) in counts:
509 continue
510 counts.add(len(t))
511 accumulator.append(t)
512
513 accumulator.sort(key=len)
514 return tuple(accumulator)
515
516
Larry Hastings7726ac92014-01-31 22:03:12 -0800517def strip_leading_and_trailing_blank_lines(s):
518 lines = s.rstrip().split('\n')
519 while lines:
520 line = lines[0]
521 if line.strip():
522 break
523 del lines[0]
524 return '\n'.join(lines)
525
526@functools.lru_cache()
527def normalize_snippet(s, *, indent=0):
528 """
529 Reformats s:
530 * removes leading and trailing blank lines
531 * ensures that it does not end with a newline
532 * dedents so the first nonwhite character on any line is at column "indent"
533 """
534 s = strip_leading_and_trailing_blank_lines(s)
535 s = textwrap.dedent(s)
536 if indent:
537 s = textwrap.indent(s, ' ' * indent)
538 return s
539
540
Larry Hastings89964c42015-04-14 18:07:59 -0400541def wrap_declarations(text, length=78):
542 """
543 A simple-minded text wrapper for C function declarations.
544
545 It views a declaration line as looking like this:
546 xxxxxxxx(xxxxxxxxx,xxxxxxxxx)
547 If called with length=30, it would wrap that line into
548 xxxxxxxx(xxxxxxxxx,
549 xxxxxxxxx)
550 (If the declaration has zero or one parameters, this
551 function won't wrap it.)
552
553 If this doesn't work properly, it's probably better to
554 start from scratch with a more sophisticated algorithm,
555 rather than try and improve/debug this dumb little function.
556 """
557 lines = []
558 for line in text.split('\n'):
559 prefix, _, after_l_paren = line.partition('(')
560 if not after_l_paren:
561 lines.append(line)
562 continue
563 parameters, _, after_r_paren = after_l_paren.partition(')')
564 if not _:
565 lines.append(line)
566 continue
567 if ',' not in parameters:
568 lines.append(line)
569 continue
570 parameters = [x.strip() + ", " for x in parameters.split(',')]
571 prefix += "("
572 if len(prefix) < length:
573 spaces = " " * len(prefix)
574 else:
575 spaces = " " * 4
576
577 while parameters:
578 line = prefix
579 first = True
580 while parameters:
581 if (not first and
582 (len(line) + len(parameters[0]) > length)):
583 break
584 line += parameters.pop(0)
585 first = False
586 if not parameters:
587 line = line.rstrip(", ") + ")" + after_r_paren
588 lines.append(line.rstrip())
589 prefix = spaces
590 return "\n".join(lines)
591
592
Larry Hastings31826802013-10-19 00:09:25 -0700593class CLanguage(Language):
594
Larry Hastings61272b72014-01-07 12:41:53 -0800595 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700596 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800597 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700598 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800599 stop_line = "[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800600 checksum_line = "/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700601
Larry Hastings7726ac92014-01-31 22:03:12 -0800602 def __init__(self, filename):
603 super().__init__(filename)
604 self.cpp = cpp.Monitor(filename)
605 self.cpp.fail = fail
606
607 def parse_line(self, line):
608 self.cpp.writeline(line)
609
Larry Hastingsbebf7352014-01-17 17:47:17 -0800610 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700611 function = None
612 for o in signatures:
613 if isinstance(o, Function):
614 if function:
615 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
616 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800617 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700618
619 def docstring_for_c_string(self, f):
620 text, add, output = _text_accumulator()
621 # turn docstring into a properly quoted C string
622 for line in f.docstring.split('\n'):
623 add('"')
624 add(quoted_for_c_string(line))
625 add('\\n"\n')
626
Zachary Ware8ef887c2015-04-13 18:22:35 -0500627 if text[-2] == sig_end_marker:
628 # If we only have a signature, add the blank line that the
629 # __text_signature__ getter expects to be there.
630 add('"\\n"')
631 else:
632 text.pop()
633 add('"')
Larry Hastings31826802013-10-19 00:09:25 -0700634 return ''.join(text)
635
Larry Hastingsbebf7352014-01-17 17:47:17 -0800636 def output_templates(self, f):
637 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800638 assert parameters
639 assert isinstance(parameters[0].converter, self_converter)
640 del parameters[0]
Larry Hastingsbebf7352014-01-17 17:47:17 -0800641 converters = [p.converter for p in parameters]
642
643 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
644 default_return_converter = (not f.return_converter or
645 f.return_converter.type == 'PyObject *')
646
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300647 positional = parameters and parameters[-1].is_positional_only()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800648 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
649 first_optional = len(parameters)
650 for i, p in enumerate(parameters):
651 c = p.converter
652 if type(c) != object_converter:
653 break
654 if c.format_unit != 'O':
655 break
656 if p.default is not unspecified:
657 first_optional = min(first_optional, i)
658 else:
659 all_boring_objects = True
660
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800661 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
662
Larry Hastingsbebf7352014-01-17 17:47:17 -0800663 meth_o = (len(parameters) == 1 and
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +0300664 parameters[0].is_positional_only() and
Larry Hastingsbebf7352014-01-17 17:47:17 -0800665 not converters[0].is_optional() and
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800666 not new_or_init)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800667
Larry Hastings7726ac92014-01-31 22:03:12 -0800668 # we have to set these things before we're done:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800669 #
670 # docstring_prototype
671 # docstring_definition
672 # impl_prototype
673 # methoddef_define
674 # parser_prototype
675 # parser_definition
676 # impl_definition
Larry Hastings7726ac92014-01-31 22:03:12 -0800677 # cpp_if
678 # cpp_endif
679 # methoddef_ifndef
Larry Hastingsbebf7352014-01-17 17:47:17 -0800680
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800681 return_value_declaration = "PyObject *return_value = NULL;"
Larry Hastings31826802013-10-19 00:09:25 -0700682
Larry Hastings7726ac92014-01-31 22:03:12 -0800683 methoddef_define = normalize_snippet("""
684 #define {methoddef_name} \\
685 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
686 """)
Larry Hastings5c661892014-01-24 06:17:25 -0800687 if new_or_init and not f.docstring:
688 docstring_prototype = docstring_definition = ''
689 else:
Larry Hastings7726ac92014-01-31 22:03:12 -0800690 docstring_prototype = normalize_snippet("""
691 PyDoc_VAR({c_basename}__doc__);
692 """)
693 docstring_definition = normalize_snippet("""
694 PyDoc_STRVAR({c_basename}__doc__,
695 {docstring});
696 """)
697 impl_definition = normalize_snippet("""
698 static {impl_return_type}
699 {c_basename}_impl({impl_parameters})
700 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800701 impl_prototype = parser_prototype = parser_definition = None
702
Larry Hastings7726ac92014-01-31 22:03:12 -0800703 parser_prototype_keyword = normalize_snippet("""
704 static PyObject *
705 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
706 """)
707
708 parser_prototype_varargs = normalize_snippet("""
709 static PyObject *
710 {c_basename}({self_type}{self_name}, PyObject *args)
711 """)
712
713 # parser_body_fields remembers the fields passed in to the
714 # previous call to parser_body. this is used for an awful hack.
Larry Hastingsc2047262014-01-25 20:43:29 -0800715 parser_body_fields = ()
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800716 def parser_body(prototype, *fields):
717 nonlocal parser_body_fields
718 add, output = text_accumulator()
719 add(prototype)
720 parser_body_fields = fields
Larry Hastings7726ac92014-01-31 22:03:12 -0800721
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800722 fields = list(fields)
Larry Hastings7726ac92014-01-31 22:03:12 -0800723 fields.insert(0, normalize_snippet("""
724 {{
725 {return_value_declaration}
726 {declarations}
727 {initializers}
728 """) + "\n")
729 # just imagine--your code is here in the middle
730 fields.append(normalize_snippet("""
731 {modifications}
732 {return_value} = {c_basename}_impl({impl_arguments});
733 {return_conversion}
734
735 {exit_label}
736 {cleanup}
737 return return_value;
738 }}
739 """))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800740 for field in fields:
741 add('\n')
Larry Hastings7726ac92014-01-31 22:03:12 -0800742 add(field)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800743 return output()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800744
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800745 def insert_keywords(s):
746 return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
Larry Hastingsbebf7352014-01-17 17:47:17 -0800747
748 if not parameters:
749 # no parameters, METH_NOARGS
750
751 flags = "METH_NOARGS"
752
Larry Hastings7726ac92014-01-31 22:03:12 -0800753 parser_prototype = normalize_snippet("""
754 static PyObject *
755 {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
756 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800757 parser_definition = parser_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800758
759 if default_return_converter:
Larry Hastings7726ac92014-01-31 22:03:12 -0800760 parser_definition = parser_prototype + '\n' + normalize_snippet("""
761 {{
762 return {c_basename}_impl({impl_arguments});
763 }}
764 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800765 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800766 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700767
Larry Hastingsbebf7352014-01-17 17:47:17 -0800768 elif meth_o:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800769 flags = "METH_O"
Larry Hastings7726ac92014-01-31 22:03:12 -0800770
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300771 if (isinstance(converters[0], object_converter) and
772 converters[0].format_unit == 'O'):
773 meth_o_prototype = normalize_snippet("""
774 static PyObject *
775 {c_basename}({impl_parameters})
776 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800777
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300778 if default_return_converter:
779 # maps perfectly to METH_O, doesn't need a return converter.
780 # so we skip making a parse function
781 # and call directly into the impl function.
782 impl_prototype = parser_prototype = parser_definition = ''
783 impl_definition = meth_o_prototype
784 else:
785 # SLIGHT HACK
786 # use impl_parameters for the parser here!
787 parser_prototype = meth_o_prototype
788 parser_definition = parser_body(parser_prototype)
789
Larry Hastingsbebf7352014-01-17 17:47:17 -0800790 else:
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300791 argname = 'arg'
792 if parameters[0].name == argname:
793 argname += '_'
794 parser_prototype = normalize_snippet("""
795 static PyObject *
796 {c_basename}({self_type}{self_name}, PyObject *%s)
797 """ % argname)
798
799 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300800 if (!PyArg_Parse(%s, "{format_units}:{name}", {parse_arguments})) {{
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300801 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300802 }}
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300803 """ % argname, indent=4))
Larry Hastings31826802013-10-19 00:09:25 -0700804
Larry Hastingsbebf7352014-01-17 17:47:17 -0800805 elif has_option_groups:
806 # positional parameters with option groups
807 # (we have to generate lots of PyArg_ParseTuple calls
808 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700809
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800810 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800811 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700812
Larry Hastings7726ac92014-01-31 22:03:12 -0800813 parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')
Larry Hastings31826802013-10-19 00:09:25 -0700814
Larry Hastingsbebf7352014-01-17 17:47:17 -0800815 elif positional and all_boring_objects:
816 # positional-only, but no option groups,
817 # and nothing but normal objects:
818 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700819
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800820 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800821 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700822
Larry Hastings7726ac92014-01-31 22:03:12 -0800823 parser_definition = parser_body(parser_prototype, normalize_snippet("""
824 if (!PyArg_UnpackTuple(args, "{name}",
825 {unpack_min}, {unpack_max},
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300826 {parse_arguments})) {{
Larry Hastings7726ac92014-01-31 22:03:12 -0800827 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300828 }}
Larry Hastings7726ac92014-01-31 22:03:12 -0800829 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800830
831 elif positional:
832 # positional-only, but no option groups
833 # we only need one call to PyArg_ParseTuple
834
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800835 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800836 parser_prototype = parser_prototype_varargs
Larry Hastingsbebf7352014-01-17 17:47:17 -0800837
Larry Hastings7726ac92014-01-31 22:03:12 -0800838 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300839 if (!PyArg_ParseTuple(args, "{format_units}:{name}",
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300840 {parse_arguments})) {{
Larry Hastings7726ac92014-01-31 22:03:12 -0800841 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300842 }}
Larry Hastings7726ac92014-01-31 22:03:12 -0800843 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800844
845 else:
846 # positional-or-keyword arguments
847 flags = "METH_VARARGS|METH_KEYWORDS"
848
Larry Hastings7726ac92014-01-31 22:03:12 -0800849 parser_prototype = parser_prototype_keyword
Larry Hastingsbebf7352014-01-17 17:47:17 -0800850
Larry Hastings7726ac92014-01-31 22:03:12 -0800851 body = normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300852 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords,
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300853 {parse_arguments})) {{
Larry Hastings7726ac92014-01-31 22:03:12 -0800854 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300855 }}
856 """, indent=4)
Larry Hastings7726ac92014-01-31 22:03:12 -0800857 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300858 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords,
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300859 {parse_arguments})) {{
Larry Hastings7726ac92014-01-31 22:03:12 -0800860 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300861 }}
Larry Hastings7726ac92014-01-31 22:03:12 -0800862 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800863 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700864
Larry Hastings31826802013-10-19 00:09:25 -0700865
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800866 if new_or_init:
867 methoddef_define = ''
868
869 if f.kind == METHOD_NEW:
Larry Hastings7726ac92014-01-31 22:03:12 -0800870 parser_prototype = parser_prototype_keyword
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800871 else:
872 return_value_declaration = "int return_value = -1;"
Larry Hastings7726ac92014-01-31 22:03:12 -0800873 parser_prototype = normalize_snippet("""
874 static int
875 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
876 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800877
878 fields = list(parser_body_fields)
879 parses_positional = 'METH_NOARGS' not in flags
880 parses_keywords = 'METH_KEYWORDS' in flags
881 if parses_keywords:
882 assert parses_positional
883
884 if not parses_keywords:
Larry Hastings7726ac92014-01-31 22:03:12 -0800885 fields.insert(0, normalize_snippet("""
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300886 if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) {{
Larry Hastings7726ac92014-01-31 22:03:12 -0800887 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300888 }}
Larry Hastings7726ac92014-01-31 22:03:12 -0800889 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800890 if not parses_positional:
Larry Hastings7726ac92014-01-31 22:03:12 -0800891 fields.insert(0, normalize_snippet("""
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300892 if ({self_type_check}!_PyArg_NoPositional("{name}", args)) {{
Larry Hastings7726ac92014-01-31 22:03:12 -0800893 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300894 }}
Larry Hastings7726ac92014-01-31 22:03:12 -0800895 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800896
897 parser_definition = parser_body(parser_prototype, *fields)
898 if parses_keywords:
899 parser_definition = insert_keywords(parser_definition)
900
Larry Hastings31826802013-10-19 00:09:25 -0700901
Larry Hastingsbebf7352014-01-17 17:47:17 -0800902 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800903 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700904
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800905 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700906
Larry Hastings7726ac92014-01-31 22:03:12 -0800907 methoddef_ifndef = ''
908 conditional = self.cpp.condition()
909 if not conditional:
910 cpp_if = cpp_endif = ''
911 else:
912 cpp_if = "#if " + conditional
913 cpp_endif = "#endif /* " + conditional + " */"
914
Larry Hastings0759f842015-04-03 13:09:02 -0700915 if methoddef_define and f.name not in clinic.ifndef_symbols:
916 clinic.ifndef_symbols.add(f.name)
Larry Hastings7726ac92014-01-31 22:03:12 -0800917 methoddef_ifndef = normalize_snippet("""
918 #ifndef {methoddef_name}
919 #define {methoddef_name}
920 #endif /* !defined({methoddef_name}) */
921 """)
922
923
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800924 # add ';' to the end of parser_prototype and impl_prototype
925 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800926 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800927 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800928 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800929 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700930
Larry Hastingsbebf7352014-01-17 17:47:17 -0800931 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800932 impl_prototype = impl_definition
933 if impl_prototype:
934 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700935
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800936 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800937
938 d = {
939 "docstring_prototype" : docstring_prototype,
940 "docstring_definition" : docstring_definition,
941 "impl_prototype" : impl_prototype,
942 "methoddef_define" : methoddef_define,
943 "parser_prototype" : parser_prototype,
944 "parser_definition" : parser_definition,
945 "impl_definition" : impl_definition,
Larry Hastings7726ac92014-01-31 22:03:12 -0800946 "cpp_if" : cpp_if,
947 "cpp_endif" : cpp_endif,
948 "methoddef_ifndef" : methoddef_ifndef,
Larry Hastingsbebf7352014-01-17 17:47:17 -0800949 }
950
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800951 # make sure we didn't forget to assign something,
952 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -0800953 d2 = {}
954 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800955 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800956 if value:
957 value = '\n' + value + '\n'
958 d2[name] = value
959 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700960
961 @staticmethod
962 def group_to_variable_name(group):
963 adjective = "left_" if group < 0 else "right_"
964 return "group_" + adjective + str(abs(group))
965
966 def render_option_group_parsing(self, f, template_dict):
967 # positional only, grouped, optional arguments!
968 # can be optional on the left or right.
969 # here's an example:
970 #
971 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
972 #
973 # Here group D are required, and all other groups are optional.
974 # (Group D's "group" is actually None.)
975 # We can figure out which sets of arguments we have based on
976 # how many arguments are in the tuple.
977 #
978 # Note that you need to count up on both sides. For example,
979 # you could have groups C+D, or C+D+E, or C+D+E+F.
980 #
981 # What if the number of arguments leads us to an ambiguous result?
982 # Clinic prefers groups on the left. So in the above example,
983 # five arguments would map to B+C, not C+D.
984
985 add, output = text_accumulator()
986 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800987 if isinstance(parameters[0].converter, self_converter):
988 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -0700989
990 groups = []
991 group = None
992 left = []
993 right = []
994 required = []
995 last = unspecified
996
997 for p in parameters:
998 group_id = p.group
999 if group_id != last:
1000 last = group_id
1001 group = []
1002 if group_id < 0:
1003 left.append(group)
1004 elif group_id == 0:
1005 group = required
1006 else:
1007 right.append(group)
1008 group.append(p)
1009
1010 count_min = sys.maxsize
1011 count_max = -1
1012
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03001013 add("switch (PyTuple_GET_SIZE(args)) {\n")
Larry Hastings31826802013-10-19 00:09:25 -07001014 for subset in permute_optional_groups(left, required, right):
1015 count = len(subset)
1016 count_min = min(count_min, count)
1017 count_max = max(count_max, count)
1018
Larry Hastings583baa82014-01-12 08:49:30 -08001019 if count == 0:
1020 add(""" case 0:
1021 break;
1022""")
1023 continue
1024
Larry Hastings31826802013-10-19 00:09:25 -07001025 group_ids = {p.group for p in subset} # eliminate duplicates
1026 d = {}
1027 d['count'] = count
1028 d['name'] = f.name
Larry Hastings31826802013-10-19 00:09:25 -07001029 d['format_units'] = "".join(p.converter.format_unit for p in subset)
1030
1031 parse_arguments = []
1032 for p in subset:
1033 p.converter.parse_argument(parse_arguments)
1034 d['parse_arguments'] = ", ".join(parse_arguments)
1035
1036 group_ids.discard(0)
1037 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
1038 lines = "\n".join(lines)
1039
1040 s = """
1041 case {count}:
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03001042 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments})) {{
Larry Hastings46258262014-01-22 03:05:49 -08001043 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03001044 }}
Larry Hastings31826802013-10-19 00:09:25 -07001045 {group_booleans}
1046 break;
1047"""[1:]
1048 s = linear_format(s, group_booleans=lines)
1049 s = s.format_map(d)
1050 add(s)
1051
1052 add(" default:\n")
1053 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
1054 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -08001055 add(' goto exit;\n')
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03001056 add("}")
1057 template_dict['option_group_parsing'] = format_escape(output())
Larry Hastings31826802013-10-19 00:09:25 -07001058
Larry Hastingsbebf7352014-01-17 17:47:17 -08001059 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -07001060 if not f:
1061 return ""
1062
1063 add, output = text_accumulator()
1064 data = CRenderData()
1065
Larry Hastings7726ac92014-01-31 22:03:12 -08001066 assert f.parameters, "We should always have a 'self' at this point!"
1067 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07001068 converters = [p.converter for p in parameters]
1069
Larry Hastings5c661892014-01-24 06:17:25 -08001070 templates = self.output_templates(f)
1071
1072 f_self = parameters[0]
1073 selfless = parameters[1:]
1074 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
1075
1076 last_group = 0
1077 first_optional = len(selfless)
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03001078 positional = selfless and selfless[-1].is_positional_only()
Larry Hastings5c661892014-01-24 06:17:25 -08001079 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
1080 default_return_converter = (not f.return_converter or
1081 f.return_converter.type == 'PyObject *')
1082 has_option_groups = False
1083
1084 # offset i by -1 because first_optional needs to ignore self
1085 for i, p in enumerate(parameters, -1):
1086 c = p.converter
1087
1088 if (i != -1) and (p.default is not unspecified):
1089 first_optional = min(first_optional, i)
1090
1091 # insert group variable
1092 group = p.group
1093 if last_group != group:
1094 last_group = group
1095 if group:
1096 group_name = self.group_to_variable_name(group)
1097 data.impl_arguments.append(group_name)
1098 data.declarations.append("int " + group_name + " = 0;")
1099 data.impl_parameters.append("int " + group_name)
1100 has_option_groups = True
1101
1102 c.render(p, data)
1103
1104 if has_option_groups and (not positional):
1105 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
1106
1107 # HACK
1108 # when we're METH_O, but have a custom return converter,
1109 # we use "impl_parameters" for the parsing function
1110 # because that works better. but that means we must
Berker Peksagf23530f2014-10-19 18:04:38 +03001111 # suppress actually declaring the impl's parameters
Larry Hastings5c661892014-01-24 06:17:25 -08001112 # as variables in the parsing function. but since it's
1113 # METH_O, we have exactly one anyway, so we know exactly
1114 # where it is.
1115 if ("METH_O" in templates['methoddef_define'] and
Serhiy Storchaka92e8af62015-04-04 00:12:11 +03001116 '{impl_parameters}' in templates['parser_prototype']):
Larry Hastings5c661892014-01-24 06:17:25 -08001117 data.declarations.pop(0)
1118
Larry Hastings31826802013-10-19 00:09:25 -07001119 template_dict = {}
1120
1121 full_name = f.full_name
1122 template_dict['full_name'] = full_name
1123
Larry Hastings5c661892014-01-24 06:17:25 -08001124 if new_or_init:
1125 name = f.cls.name
1126 else:
1127 name = f.name
1128
Larry Hastings31826802013-10-19 00:09:25 -07001129 template_dict['name'] = name
1130
Larry Hastings8666e652014-01-12 14:12:59 -08001131 if f.c_basename:
1132 c_basename = f.c_basename
1133 else:
1134 fields = full_name.split(".")
1135 if fields[-1] == '__new__':
1136 fields.pop()
1137 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001138
Larry Hastings31826802013-10-19 00:09:25 -07001139 template_dict['c_basename'] = c_basename
1140
1141 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1142 template_dict['methoddef_name'] = methoddef_name
1143
1144 template_dict['docstring'] = self.docstring_for_c_string(f)
1145
Larry Hastingsc2047262014-01-25 20:43:29 -08001146 template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
Larry Hastings5c661892014-01-24 06:17:25 -08001147 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001148
Larry Hastings31826802013-10-19 00:09:25 -07001149 f.return_converter.render(f, data)
1150 template_dict['impl_return_type'] = f.return_converter.type
1151
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03001152 template_dict['declarations'] = format_escape("\n".join(data.declarations))
Larry Hastings31826802013-10-19 00:09:25 -07001153 template_dict['initializers'] = "\n\n".join(data.initializers)
Larry Hastingsc2047262014-01-25 20:43:29 -08001154 template_dict['modifications'] = '\n\n'.join(data.modifications)
Larry Hastings31826802013-10-19 00:09:25 -07001155 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1156 template_dict['format_units'] = ''.join(data.format_units)
1157 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1158 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1159 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03001160 template_dict['return_conversion'] = format_escape("".join(data.return_conversion).rstrip())
1161 template_dict['cleanup'] = format_escape("".join(data.cleanup))
Larry Hastings31826802013-10-19 00:09:25 -07001162 template_dict['return_value'] = data.return_value
1163
Larry Hastings5c661892014-01-24 06:17:25 -08001164 # used by unpack tuple code generator
1165 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1166 unpack_min = first_optional
1167 unpack_max = len(selfless)
1168 template_dict['unpack_min'] = str(unpack_min)
1169 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001170
Larry Hastingsbebf7352014-01-17 17:47:17 -08001171 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001172 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001173
Larry Hastings0759f842015-04-03 13:09:02 -07001174 # buffers, not destination
1175 for name, destination in clinic.destination_buffers.items():
Larry Hastingsbebf7352014-01-17 17:47:17 -08001176 template = templates[name]
1177 if has_option_groups:
1178 template = linear_format(template,
1179 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001180 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001181 declarations=template_dict['declarations'],
1182 return_conversion=template_dict['return_conversion'],
1183 initializers=template_dict['initializers'],
Larry Hastingsc2047262014-01-25 20:43:29 -08001184 modifications=template_dict['modifications'],
Larry Hastingsbebf7352014-01-17 17:47:17 -08001185 cleanup=template_dict['cleanup'],
1186 )
Larry Hastings31826802013-10-19 00:09:25 -07001187
Larry Hastingsbebf7352014-01-17 17:47:17 -08001188 # Only generate the "exit:" label
1189 # if we have any gotos
1190 need_exit_label = "goto exit;" in template
1191 template = linear_format(template,
1192 exit_label="exit:" if need_exit_label else ''
1193 )
Larry Hastings31826802013-10-19 00:09:25 -07001194
Larry Hastingsbebf7352014-01-17 17:47:17 -08001195 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001196
Larry Hastings89964c42015-04-14 18:07:59 -04001197 # mild hack:
1198 # reflow long impl declarations
1199 if name in {"impl_prototype", "impl_definition"}:
1200 s = wrap_declarations(s)
1201
Larry Hastingsbebf7352014-01-17 17:47:17 -08001202 if clinic.line_prefix:
1203 s = indent_all_lines(s, clinic.line_prefix)
1204 if clinic.line_suffix:
1205 s = suffix_all_lines(s, clinic.line_suffix)
1206
1207 destination.append(s)
1208
1209 return clinic.get_destination('block').dump()
1210
Larry Hastings31826802013-10-19 00:09:25 -07001211
1212
Larry Hastings5c661892014-01-24 06:17:25 -08001213
Larry Hastings31826802013-10-19 00:09:25 -07001214@contextlib.contextmanager
1215def OverrideStdioWith(stdout):
1216 saved_stdout = sys.stdout
1217 sys.stdout = stdout
1218 try:
1219 yield
1220 finally:
1221 assert sys.stdout is stdout
1222 sys.stdout = saved_stdout
1223
1224
Larry Hastings2623c8c2014-02-08 22:15:29 -08001225def create_regex(before, after, word=True, whole_line=True):
Larry Hastings31826802013-10-19 00:09:25 -07001226 """Create an re object for matching marker lines."""
Larry Hastings581ee362014-01-28 05:00:08 -08001227 group_re = "\w+" if word else ".+"
Larry Hastings2623c8c2014-02-08 22:15:29 -08001228 pattern = r'{}({}){}'
1229 if whole_line:
1230 pattern = '^' + pattern + '$'
Larry Hastings581ee362014-01-28 05:00:08 -08001231 pattern = pattern.format(re.escape(before), group_re, re.escape(after))
1232 return re.compile(pattern)
Larry Hastings31826802013-10-19 00:09:25 -07001233
1234
1235class Block:
1236 r"""
1237 Represents a single block of text embedded in
1238 another file. If dsl_name is None, the block represents
1239 verbatim text, raw original text from the file, in
1240 which case "input" will be the only non-false member.
1241 If dsl_name is not None, the block represents a Clinic
1242 block.
1243
1244 input is always str, with embedded \n characters.
1245 input represents the original text from the file;
1246 if it's a Clinic block, it is the original text with
1247 the body_prefix and redundant leading whitespace removed.
1248
1249 dsl_name is either str or None. If str, it's the text
1250 found on the start line of the block between the square
1251 brackets.
1252
1253 signatures is either list or None. If it's a list,
1254 it may only contain clinic.Module, clinic.Class, and
1255 clinic.Function objects. At the moment it should
1256 contain at most one of each.
1257
1258 output is either str or None. If str, it's the output
1259 from this block, with embedded '\n' characters.
1260
1261 indent is either str or None. It's the leading whitespace
1262 that was found on every line of input. (If body_prefix is
1263 not empty, this is the indent *after* removing the
1264 body_prefix.)
1265
1266 preindent is either str or None. It's the whitespace that
1267 was found in front of every line of input *before* the
1268 "body_prefix" (see the Language object). If body_prefix
1269 is empty, preindent must always be empty too.
1270
1271 To illustrate indent and preindent: Assume that '_'
1272 represents whitespace. If the block processed was in a
1273 Python file, and looked like this:
1274 ____#/*[python]
1275 ____#__for a in range(20):
1276 ____#____print(a)
1277 ____#[python]*/
1278 "preindent" would be "____" and "indent" would be "__".
1279
1280 """
1281 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1282 assert isinstance(input, str)
1283 self.input = input
1284 self.dsl_name = dsl_name
1285 self.signatures = signatures or []
1286 self.output = output
1287 self.indent = indent
1288 self.preindent = preindent
1289
Larry Hastings581ee362014-01-28 05:00:08 -08001290 def __repr__(self):
1291 dsl_name = self.dsl_name or "text"
1292 def summarize(s):
1293 s = repr(s)
1294 if len(s) > 30:
1295 return s[:26] + "..." + s[0]
1296 return s
1297 return "".join((
1298 "<Block ", dsl_name, " input=", summarize(self.input), " output=", summarize(self.output), ">"))
1299
Larry Hastings31826802013-10-19 00:09:25 -07001300
1301class BlockParser:
1302 """
1303 Block-oriented parser for Argument Clinic.
1304 Iterator, yields Block objects.
1305 """
1306
1307 def __init__(self, input, language, *, verify=True):
1308 """
1309 "input" should be a str object
1310 with embedded \n characters.
1311
1312 "language" should be a Language object.
1313 """
1314 language.validate()
1315
1316 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1317 self.block_start_line_number = self.line_number = 0
1318
1319 self.language = language
1320 before, _, after = language.start_line.partition('{dsl_name}')
1321 assert _ == '{dsl_name}'
Larry Hastings2623c8c2014-02-08 22:15:29 -08001322 self.find_start_re = create_regex(before, after, whole_line=False)
Larry Hastings31826802013-10-19 00:09:25 -07001323 self.start_re = create_regex(before, after)
1324 self.verify = verify
1325 self.last_checksum_re = None
1326 self.last_dsl_name = None
1327 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001328 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001329
1330 def __iter__(self):
1331 return self
1332
1333 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001334 while True:
1335 if not self.input:
1336 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001337
Larry Hastingsbebf7352014-01-17 17:47:17 -08001338 if self.dsl_name:
1339 return_value = self.parse_clinic_block(self.dsl_name)
1340 self.dsl_name = None
1341 self.first_block = False
1342 return return_value
1343 block = self.parse_verbatim_block()
1344 if self.first_block and not block.input:
1345 continue
1346 self.first_block = False
1347 return block
1348
Larry Hastings31826802013-10-19 00:09:25 -07001349
1350 def is_start_line(self, line):
1351 match = self.start_re.match(line.lstrip())
1352 return match.group(1) if match else None
1353
Larry Hastingse1b82532014-07-27 16:22:20 +02001354 def _line(self, lookahead=False):
Larry Hastings31826802013-10-19 00:09:25 -07001355 self.line_number += 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001356 line = self.input.pop()
Larry Hastingse1b82532014-07-27 16:22:20 +02001357 if not lookahead:
1358 self.language.parse_line(line)
Larry Hastings7726ac92014-01-31 22:03:12 -08001359 return line
Larry Hastings31826802013-10-19 00:09:25 -07001360
1361 def parse_verbatim_block(self):
1362 add, output = text_accumulator()
1363 self.block_start_line_number = self.line_number
1364
1365 while self.input:
1366 line = self._line()
1367 dsl_name = self.is_start_line(line)
1368 if dsl_name:
1369 self.dsl_name = dsl_name
1370 break
1371 add(line)
1372
1373 return Block(output())
1374
1375 def parse_clinic_block(self, dsl_name):
1376 input_add, input_output = text_accumulator()
1377 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001378 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001379 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1380
Larry Hastings90261132014-01-07 12:21:08 -08001381 def is_stop_line(line):
1382 # make sure to recognize stop line even if it
1383 # doesn't end with EOL (it could be the very end of the file)
1384 if not line.startswith(stop_line):
1385 return False
1386 remainder = line[len(stop_line):]
1387 return (not remainder) or remainder.isspace()
1388
Larry Hastings31826802013-10-19 00:09:25 -07001389 # consume body of program
1390 while self.input:
1391 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001392 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001393 break
1394 if body_prefix:
1395 line = line.lstrip()
1396 assert line.startswith(body_prefix)
1397 line = line[len(body_prefix):]
1398 input_add(line)
1399
1400 # consume output and checksum line, if present.
1401 if self.last_dsl_name == dsl_name:
1402 checksum_re = self.last_checksum_re
1403 else:
Larry Hastings581ee362014-01-28 05:00:08 -08001404 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, arguments='{arguments}').partition('{arguments}')
1405 assert _ == '{arguments}'
1406 checksum_re = create_regex(before, after, word=False)
Larry Hastings31826802013-10-19 00:09:25 -07001407 self.last_dsl_name = dsl_name
1408 self.last_checksum_re = checksum_re
1409
1410 # scan forward for checksum line
1411 output_add, output_output = text_accumulator()
Larry Hastings581ee362014-01-28 05:00:08 -08001412 arguments = None
Larry Hastings31826802013-10-19 00:09:25 -07001413 while self.input:
Larry Hastingse1b82532014-07-27 16:22:20 +02001414 line = self._line(lookahead=True)
Larry Hastings31826802013-10-19 00:09:25 -07001415 match = checksum_re.match(line.lstrip())
Larry Hastings581ee362014-01-28 05:00:08 -08001416 arguments = match.group(1) if match else None
1417 if arguments:
Larry Hastings31826802013-10-19 00:09:25 -07001418 break
1419 output_add(line)
1420 if self.is_start_line(line):
1421 break
1422
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001423 output = output_output()
Larry Hastings581ee362014-01-28 05:00:08 -08001424 if arguments:
1425 d = {}
1426 for field in shlex.split(arguments):
1427 name, equals, value = field.partition('=')
1428 if not equals:
1429 fail("Mangled Argument Clinic marker line: {!r}".format(line))
1430 d[name.strip()] = value.strip()
1431
Larry Hastings31826802013-10-19 00:09:25 -07001432 if self.verify:
Larry Hastings581ee362014-01-28 05:00:08 -08001433 if 'input' in d:
1434 checksum = d['output']
1435 input_checksum = d['input']
1436 else:
1437 checksum = d['checksum']
1438 input_checksum = None
1439
1440 computed = compute_checksum(output, len(checksum))
Larry Hastings31826802013-10-19 00:09:25 -07001441 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001442 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1443 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001444 "the end marker,\n"
1445 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001446 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001447 else:
1448 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001449 output_lines = output.splitlines(keepends=True)
1450 self.line_number -= len(output_lines)
1451 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001452 output = None
1453
1454 return Block(input_output(), dsl_name, output=output)
1455
1456
1457class BlockPrinter:
1458
1459 def __init__(self, language, f=None):
1460 self.language = language
1461 self.f = f or io.StringIO()
1462
1463 def print_block(self, block):
1464 input = block.input
1465 output = block.output
1466 dsl_name = block.dsl_name
1467 write = self.f.write
1468
Larry Hastings31826802013-10-19 00:09:25 -07001469 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1470
1471 if not dsl_name:
1472 write(input)
1473 return
1474
1475 write(self.language.start_line.format(dsl_name=dsl_name))
1476 write("\n")
1477
1478 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1479 if not body_prefix:
1480 write(input)
1481 else:
1482 for line in input.split('\n'):
1483 write(body_prefix)
1484 write(line)
1485 write("\n")
1486
1487 write(self.language.stop_line.format(dsl_name=dsl_name))
1488 write("\n")
1489
Larry Hastings581ee362014-01-28 05:00:08 -08001490 input = ''.join(block.input)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001491 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001492 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001493 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001494 output += '\n'
1495 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001496
Larry Hastings581ee362014-01-28 05:00:08 -08001497 arguments="output={} input={}".format(compute_checksum(output, 16), compute_checksum(input, 16))
1498 write(self.language.checksum_line.format(dsl_name=dsl_name, arguments=arguments))
Larry Hastings31826802013-10-19 00:09:25 -07001499 write("\n")
1500
Larry Hastingsbebf7352014-01-17 17:47:17 -08001501 def write(self, text):
1502 self.f.write(text)
1503
1504
Larry Hastings0759f842015-04-03 13:09:02 -07001505class BufferSeries:
1506 """
1507 Behaves like a "defaultlist".
1508 When you ask for an index that doesn't exist yet,
1509 the object grows the list until that item exists.
1510 So o[n] will always work.
1511
1512 Supports negative indices for actual items.
1513 e.g. o[-1] is an element immediately preceding o[0].
1514 """
1515
1516 def __init__(self):
1517 self._start = 0
1518 self._array = []
1519 self._constructor = _text_accumulator
1520
1521 def __getitem__(self, i):
1522 i -= self._start
1523 if i < 0:
1524 self._start += i
1525 prefix = [self._constructor() for x in range(-i)]
1526 self._array = prefix + self._array
1527 i = 0
1528 while i >= len(self._array):
1529 self._array.append(self._constructor())
1530 return self._array[i]
1531
1532 def clear(self):
1533 for ta in self._array:
1534 ta._text.clear()
1535
1536 def dump(self):
1537 texts = [ta.output() for ta in self._array]
1538 return "".join(texts)
1539
1540
Larry Hastingsbebf7352014-01-17 17:47:17 -08001541class Destination:
1542 def __init__(self, name, type, clinic, *args):
1543 self.name = name
1544 self.type = type
1545 self.clinic = clinic
Larry Hastings0759f842015-04-03 13:09:02 -07001546 valid_types = ('buffer', 'file', 'suppress')
Larry Hastingsbebf7352014-01-17 17:47:17 -08001547 if type not in valid_types:
1548 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1549 extra_arguments = 1 if type == "file" else 0
1550 if len(args) < extra_arguments:
1551 fail("Not enough arguments for destination " + name + " new " + type)
1552 if len(args) > extra_arguments:
1553 fail("Too many arguments for destination " + name + " new " + type)
1554 if type =='file':
1555 d = {}
Larry Hastingsc2047262014-01-25 20:43:29 -08001556 filename = clinic.filename
1557 d['path'] = filename
1558 dirname, basename = os.path.split(filename)
1559 if not dirname:
1560 dirname = '.'
1561 d['dirname'] = dirname
1562 d['basename'] = basename
1563 d['basename_root'], d['basename_extension'] = os.path.splitext(filename)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001564 self.filename = args[0].format_map(d)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001565
Larry Hastings0759f842015-04-03 13:09:02 -07001566 self.buffers = BufferSeries()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001567
1568 def __repr__(self):
1569 if self.type == 'file':
1570 file_repr = " " + repr(self.filename)
1571 else:
1572 file_repr = ''
1573 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1574
1575 def clear(self):
1576 if self.type != 'buffer':
1577 fail("Can't clear destination" + self.name + " , it's not of type buffer")
Larry Hastings0759f842015-04-03 13:09:02 -07001578 self.buffers.clear()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001579
1580 def dump(self):
Larry Hastings0759f842015-04-03 13:09:02 -07001581 return self.buffers.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001582
Larry Hastings31826802013-10-19 00:09:25 -07001583
1584# maps strings to Language objects.
1585# "languages" maps the name of the language ("C", "Python").
1586# "extensions" maps the file extension ("c", "py").
1587languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001588extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1589extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001590
1591
1592# maps strings to callables.
1593# these callables must be of the form:
1594# def foo(name, default, *, ...)
1595# The callable may have any number of keyword-only parameters.
1596# The callable must return a CConverter object.
1597# The callable should not call builtins.print.
1598converters = {}
1599
1600# maps strings to callables.
1601# these callables follow the same rules as those for "converters" above.
1602# note however that they will never be called with keyword-only parameters.
1603legacy_converters = {}
1604
1605
1606# maps strings to callables.
1607# these callables must be of the form:
1608# def foo(*, ...)
1609# The callable may have any number of keyword-only parameters.
1610# The callable must return a CConverter object.
1611# The callable should not call builtins.print.
1612return_converters = {}
1613
Larry Hastings7726ac92014-01-31 22:03:12 -08001614clinic = None
Larry Hastings31826802013-10-19 00:09:25 -07001615class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001616
1617 presets_text = """
Larry Hastings7726ac92014-01-31 22:03:12 -08001618preset block
1619everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001620methoddef_ifndef buffer 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001621docstring_prototype suppress
1622parser_prototype suppress
1623cpp_if suppress
1624cpp_endif suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001625
Larry Hastingsbebf7352014-01-17 17:47:17 -08001626preset original
1627everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001628methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001629docstring_prototype suppress
1630parser_prototype suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001631cpp_if suppress
1632cpp_endif suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001633
1634preset file
1635everything file
Larry Hastings0759f842015-04-03 13:09:02 -07001636methoddef_ifndef file 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001637docstring_prototype suppress
1638parser_prototype suppress
1639impl_definition block
1640
1641preset buffer
1642everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001643methoddef_ifndef buffer 1
1644impl_definition block
Larry Hastingsbebf7352014-01-17 17:47:17 -08001645docstring_prototype suppress
1646impl_prototype suppress
1647parser_prototype suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001648
1649preset partial-buffer
1650everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001651methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001652docstring_prototype block
1653impl_prototype suppress
1654methoddef_define block
1655parser_prototype block
1656impl_definition block
1657
Larry Hastingsbebf7352014-01-17 17:47:17 -08001658"""
1659
Larry Hastings581ee362014-01-28 05:00:08 -08001660 def __init__(self, language, printer=None, *, force=False, verify=True, filename=None):
Larry Hastings31826802013-10-19 00:09:25 -07001661 # maps strings to Parser objects.
1662 # (instantiated from the "parsers" global.)
1663 self.parsers = {}
1664 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001665 if printer:
1666 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001667 self.printer = printer or BlockPrinter(language)
1668 self.verify = verify
Larry Hastings581ee362014-01-28 05:00:08 -08001669 self.force = force
Larry Hastings31826802013-10-19 00:09:25 -07001670 self.filename = filename
1671 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001672 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001673 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001674
Larry Hastingsbebf7352014-01-17 17:47:17 -08001675 self.line_prefix = self.line_suffix = ''
1676
1677 self.destinations = {}
1678 self.add_destination("block", "buffer")
1679 self.add_destination("suppress", "suppress")
1680 self.add_destination("buffer", "buffer")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001681 if filename:
Larry Hastingsc2047262014-01-25 20:43:29 -08001682 self.add_destination("file", "file", "{dirname}/clinic/{basename}.h")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001683
Larry Hastings0759f842015-04-03 13:09:02 -07001684 d = self.get_destination_buffer
1685 self.destination_buffers = collections.OrderedDict((
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001686 ('cpp_if', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001687 ('docstring_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001688 ('docstring_definition', d('file')),
1689 ('methoddef_define', d('file')),
1690 ('impl_prototype', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001691 ('parser_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001692 ('parser_definition', d('file')),
1693 ('cpp_endif', d('file')),
1694 ('methoddef_ifndef', d('file', 1)),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001695 ('impl_definition', d('block')),
1696 ))
1697
Larry Hastings0759f842015-04-03 13:09:02 -07001698 self.destination_buffers_stack = []
1699 self.ifndef_symbols = set()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001700
1701 self.presets = {}
1702 preset = None
1703 for line in self.presets_text.strip().split('\n'):
1704 line = line.strip()
1705 if not line:
1706 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001707 name, value, *options = line.split()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001708 if name == 'preset':
1709 self.presets[value] = preset = collections.OrderedDict()
1710 continue
1711
Larry Hastings0759f842015-04-03 13:09:02 -07001712 if len(options):
1713 index = int(options[0])
1714 else:
1715 index = 0
1716 buffer = self.get_destination_buffer(value, index)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001717
1718 if name == 'everything':
Larry Hastings0759f842015-04-03 13:09:02 -07001719 for name in self.destination_buffers:
1720 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001721 continue
1722
Larry Hastings0759f842015-04-03 13:09:02 -07001723 assert name in self.destination_buffers
1724 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001725
Larry Hastings31826802013-10-19 00:09:25 -07001726 global clinic
1727 clinic = self
1728
Larry Hastingsbebf7352014-01-17 17:47:17 -08001729 def add_destination(self, name, type, *args):
1730 if name in self.destinations:
1731 fail("Destination already exists: " + repr(name))
1732 self.destinations[name] = Destination(name, type, self, *args)
1733
Larry Hastings0759f842015-04-03 13:09:02 -07001734 def get_destination(self, name):
1735 d = self.destinations.get(name)
1736 if not d:
1737 fail("Destination does not exist: " + repr(name))
1738 return d
1739
1740 def get_destination_buffer(self, name, item=0):
1741 d = self.get_destination(name)
1742 return d.buffers[item]
1743
Larry Hastings31826802013-10-19 00:09:25 -07001744 def parse(self, input):
1745 printer = self.printer
1746 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1747 for block in self.block_parser:
1748 dsl_name = block.dsl_name
1749 if dsl_name:
1750 if dsl_name not in self.parsers:
1751 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1752 self.parsers[dsl_name] = parsers[dsl_name](self)
1753 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001754 try:
1755 parser.parse(block)
1756 except Exception:
1757 fail('Exception raised during parsing:\n' +
1758 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001759 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001760
1761 second_pass_replacements = {}
1762
Larry Hastings0759f842015-04-03 13:09:02 -07001763 # these are destinations not buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08001764 for name, destination in self.destinations.items():
1765 if destination.type == 'suppress':
1766 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001767 output = destination.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001768
1769 if output:
1770
1771 block = Block("", dsl_name="clinic", output=output)
1772
1773 if destination.type == 'buffer':
1774 block.input = "dump " + name + "\n"
1775 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1776 printer.write("\n")
1777 printer.print_block(block)
1778 continue
1779
1780 if destination.type == 'file':
1781 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08001782 dirname = os.path.dirname(destination.filename)
1783 try:
1784 os.makedirs(dirname)
1785 except FileExistsError:
1786 if not os.path.isdir(dirname):
1787 fail("Can't write to destination {}, "
1788 "can't make directory {}!".format(
1789 destination.filename, dirname))
Larry Hastings581ee362014-01-28 05:00:08 -08001790 if self.verify:
1791 with open(destination.filename, "rt") as f:
1792 parser_2 = BlockParser(f.read(), language=self.language)
1793 blocks = list(parser_2)
1794 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1795 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001796 except FileNotFoundError:
1797 pass
1798
1799 block.input = 'preserve\n'
1800 printer_2 = BlockPrinter(self.language)
1801 printer_2.print_block(block)
1802 with open(destination.filename, "wt") as f:
1803 f.write(printer_2.f.getvalue())
1804 continue
1805 text = printer.f.getvalue()
1806
1807 if second_pass_replacements:
1808 printer_2 = BlockPrinter(self.language)
1809 parser_2 = BlockParser(text, self.language)
1810 changed = False
1811 for block in parser_2:
1812 if block.dsl_name:
1813 for id, replacement in second_pass_replacements.items():
1814 if id in block.output:
1815 changed = True
1816 block.output = block.output.replace(id, replacement)
1817 printer_2.print_block(block)
1818 if changed:
1819 text = printer_2.f.getvalue()
1820
1821 return text
1822
Larry Hastings31826802013-10-19 00:09:25 -07001823
1824 def _module_and_class(self, fields):
1825 """
1826 fields should be an iterable of field names.
1827 returns a tuple of (module, class).
1828 the module object could actually be self (a clinic object).
1829 this function is only ever used to find the parent of where
1830 a new class/module should go.
1831 """
1832 in_classes = False
1833 parent = module = self
1834 cls = None
1835 so_far = []
1836
1837 for field in fields:
1838 so_far.append(field)
1839 if not in_classes:
1840 child = parent.modules.get(field)
1841 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001842 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001843 continue
1844 in_classes = True
1845 if not hasattr(parent, 'classes'):
1846 return module, cls
1847 child = parent.classes.get(field)
1848 if not child:
1849 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1850 cls = parent = child
1851
1852 return module, cls
1853
1854
Larry Hastings581ee362014-01-28 05:00:08 -08001855def parse_file(filename, *, force=False, verify=True, output=None, encoding='utf-8'):
Larry Hastings31826802013-10-19 00:09:25 -07001856 extension = os.path.splitext(filename)[1][1:]
1857 if not extension:
1858 fail("Can't extract file type for file " + repr(filename))
1859
1860 try:
Larry Hastings7726ac92014-01-31 22:03:12 -08001861 language = extensions[extension](filename)
Larry Hastings31826802013-10-19 00:09:25 -07001862 except KeyError:
1863 fail("Can't identify file type for file " + repr(filename))
1864
Larry Hastings31826802013-10-19 00:09:25 -07001865 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001866 raw = f.read()
1867
Larry Hastings2623c8c2014-02-08 22:15:29 -08001868 # exit quickly if there are no clinic markers in the file
1869 find_start_re = BlockParser("", language).find_start_re
1870 if not find_start_re.search(raw):
1871 return
1872
1873 clinic = Clinic(language, force=force, verify=verify, filename=filename)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001874 cooked = clinic.parse(raw)
Larry Hastings581ee362014-01-28 05:00:08 -08001875 if (cooked == raw) and not force:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001876 return
Larry Hastings31826802013-10-19 00:09:25 -07001877
1878 directory = os.path.dirname(filename) or '.'
1879
1880 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001881 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001882 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1883 with open(tmpfilename, "wb") as f:
1884 f.write(bytes)
1885 os.replace(tmpfilename, output or filename)
1886
1887
Larry Hastings581ee362014-01-28 05:00:08 -08001888def compute_checksum(input, length=None):
Larry Hastings31826802013-10-19 00:09:25 -07001889 input = input or ''
Larry Hastings581ee362014-01-28 05:00:08 -08001890 s = hashlib.sha1(input.encode('utf-8')).hexdigest()
1891 if length:
1892 s = s[:length]
1893 return s
Larry Hastings31826802013-10-19 00:09:25 -07001894
1895
1896
1897
1898class PythonParser:
1899 def __init__(self, clinic):
1900 pass
1901
1902 def parse(self, block):
1903 s = io.StringIO()
1904 with OverrideStdioWith(s):
1905 exec(block.input)
1906 block.output = s.getvalue()
1907
1908
1909class Module:
1910 def __init__(self, name, module=None):
1911 self.name = name
1912 self.module = self.parent = module
1913
1914 self.modules = collections.OrderedDict()
1915 self.classes = collections.OrderedDict()
1916 self.functions = []
1917
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001918 def __repr__(self):
1919 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1920
Larry Hastings31826802013-10-19 00:09:25 -07001921class Class:
Larry Hastingsc2047262014-01-25 20:43:29 -08001922 def __init__(self, name, module=None, cls=None, typedef=None, type_object=None):
Larry Hastings31826802013-10-19 00:09:25 -07001923 self.name = name
1924 self.module = module
1925 self.cls = cls
Larry Hastingsc2047262014-01-25 20:43:29 -08001926 self.typedef = typedef
1927 self.type_object = type_object
Larry Hastings31826802013-10-19 00:09:25 -07001928 self.parent = cls or module
1929
1930 self.classes = collections.OrderedDict()
1931 self.functions = []
1932
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001933 def __repr__(self):
1934 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1935
Larry Hastings8666e652014-01-12 14:12:59 -08001936unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001937
Larry Hastings8666e652014-01-12 14:12:59 -08001938__abs__
1939__add__
1940__and__
1941__bytes__
1942__call__
1943__complex__
1944__delitem__
1945__divmod__
1946__eq__
1947__float__
1948__floordiv__
1949__ge__
1950__getattr__
1951__getattribute__
1952__getitem__
1953__gt__
1954__hash__
1955__iadd__
1956__iand__
Larry Hastings8666e652014-01-12 14:12:59 -08001957__ifloordiv__
1958__ilshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001959__imatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001960__imod__
1961__imul__
1962__index__
1963__int__
1964__invert__
1965__ior__
1966__ipow__
1967__irshift__
1968__isub__
1969__iter__
1970__itruediv__
1971__ixor__
1972__le__
1973__len__
1974__lshift__
1975__lt__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001976__matmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001977__mod__
1978__mul__
1979__neg__
1980__new__
1981__next__
1982__or__
1983__pos__
1984__pow__
1985__radd__
1986__rand__
1987__rdivmod__
1988__repr__
1989__rfloordiv__
1990__rlshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001991__rmatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001992__rmod__
1993__rmul__
1994__ror__
1995__round__
1996__rpow__
1997__rrshift__
1998__rshift__
1999__rsub__
2000__rtruediv__
2001__rxor__
2002__setattr__
2003__setitem__
2004__str__
2005__sub__
2006__truediv__
2007__xor__
2008
2009""".strip().split())
2010
2011
Larry Hastings5c661892014-01-24 06:17:25 -08002012INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
2013INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
2014""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07002015
2016class Function:
2017 """
2018 Mutable duck type for inspect.Function.
2019
2020 docstring - a str containing
2021 * embedded line breaks
2022 * text outdented to the left margin
2023 * no trailing whitespace.
2024 It will always be true that
2025 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
2026 """
2027
2028 def __init__(self, parameters=None, *, name,
2029 module, cls=None, c_basename=None,
2030 full_name=None,
2031 return_converter, return_annotation=_empty,
Larry Hastings581ee362014-01-28 05:00:08 -08002032 docstring=None, kind=CALLABLE, coexist=False,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002033 docstring_only=False):
Larry Hastings31826802013-10-19 00:09:25 -07002034 self.parameters = parameters or collections.OrderedDict()
2035 self.return_annotation = return_annotation
2036 self.name = name
2037 self.full_name = full_name
2038 self.module = module
2039 self.cls = cls
2040 self.parent = cls or module
2041 self.c_basename = c_basename
2042 self.return_converter = return_converter
2043 self.docstring = docstring or ''
2044 self.kind = kind
2045 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08002046 self.self_converter = None
Larry Hastings2623c8c2014-02-08 22:15:29 -08002047 # docstring_only means "don't generate a machine-readable
2048 # signature, just a normal docstring". it's True for
2049 # functions with optional groups because we can't represent
2050 # those accurately with inspect.Signature in 3.4.
2051 self.docstring_only = docstring_only
Larry Hastingsebdcb502013-11-23 14:54:00 -08002052
Larry Hastings7726ac92014-01-31 22:03:12 -08002053 self.rendered_parameters = None
2054
2055 __render_parameters__ = None
2056 @property
2057 def render_parameters(self):
2058 if not self.__render_parameters__:
2059 self.__render_parameters__ = l = []
2060 for p in self.parameters.values():
2061 p = p.copy()
2062 p.converter.pre_render()
2063 l.append(p)
2064 return self.__render_parameters__
2065
Larry Hastingsebdcb502013-11-23 14:54:00 -08002066 @property
2067 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08002068 if self.kind in (METHOD_INIT, METHOD_NEW):
2069 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002070 flags = []
2071 if self.kind == CLASS_METHOD:
2072 flags.append('METH_CLASS')
2073 elif self.kind == STATIC_METHOD:
2074 flags.append('METH_STATIC')
2075 else:
2076 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
2077 if self.coexist:
2078 flags.append('METH_COEXIST')
2079 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07002080
2081 def __repr__(self):
2082 return '<clinic.Function ' + self.name + '>'
2083
Larry Hastings7726ac92014-01-31 22:03:12 -08002084 def copy(self, **overrides):
2085 kwargs = {
2086 'name': self.name, 'module': self.module, 'parameters': self.parameters,
2087 'cls': self.cls, 'c_basename': self.c_basename,
2088 'full_name': self.full_name,
2089 'return_converter': self.return_converter, 'return_annotation': self.return_annotation,
2090 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002091 'docstring_only': self.docstring_only,
Larry Hastings7726ac92014-01-31 22:03:12 -08002092 }
2093 kwargs.update(overrides)
2094 f = Function(**kwargs)
2095
2096 parameters = collections.OrderedDict()
2097 for name, value in f.parameters.items():
2098 value = value.copy(function=f)
2099 parameters[name] = value
2100 f.parameters = parameters
2101 return f
2102
Larry Hastings31826802013-10-19 00:09:25 -07002103
2104class Parameter:
2105 """
2106 Mutable duck type of inspect.Parameter.
2107 """
2108
2109 def __init__(self, name, kind, *, default=_empty,
2110 function, converter, annotation=_empty,
2111 docstring=None, group=0):
2112 self.name = name
2113 self.kind = kind
2114 self.default = default
2115 self.function = function
2116 self.converter = converter
2117 self.annotation = annotation
2118 self.docstring = docstring or ''
2119 self.group = group
2120
2121 def __repr__(self):
2122 return '<clinic.Parameter ' + self.name + '>'
2123
2124 def is_keyword_only(self):
2125 return self.kind == inspect.Parameter.KEYWORD_ONLY
2126
Larry Hastings2623c8c2014-02-08 22:15:29 -08002127 def is_positional_only(self):
2128 return self.kind == inspect.Parameter.POSITIONAL_ONLY
2129
Larry Hastings7726ac92014-01-31 22:03:12 -08002130 def copy(self, **overrides):
2131 kwargs = {
2132 'name': self.name, 'kind': self.kind, 'default':self.default,
2133 'function': self.function, 'converter': self.converter, 'annotation': self.annotation,
2134 'docstring': self.docstring, 'group': self.group,
2135 }
2136 kwargs.update(overrides)
2137 if 'converter' not in overrides:
2138 converter = copy.copy(self.converter)
2139 converter.function = kwargs['function']
2140 kwargs['converter'] = converter
2141 return Parameter(**kwargs)
2142
2143
2144
2145class LandMine:
2146 # try to access any
2147 def __init__(self, message):
2148 self.__message__ = message
2149
2150 def __repr__(self):
2151 return '<LandMine ' + repr(self.__message__) + ">"
2152
2153 def __getattribute__(self, name):
2154 if name in ('__repr__', '__message__'):
2155 return super().__getattribute__(name)
2156 # raise RuntimeError(repr(name))
2157 fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__)
Larry Hastings31826802013-10-19 00:09:25 -07002158
Larry Hastings31826802013-10-19 00:09:25 -07002159
2160def add_c_converter(f, name=None):
2161 if not name:
2162 name = f.__name__
2163 if not name.endswith('_converter'):
2164 return f
2165 name = name[:-len('_converter')]
2166 converters[name] = f
2167 return f
2168
2169def add_default_legacy_c_converter(cls):
2170 # automatically add converter for default format unit
2171 # (but without stomping on the existing one if it's already
2172 # set, in case you subclass)
Larry Hastingsf1503782014-06-11 04:31:29 -07002173 if ((cls.format_unit not in ('O&', '')) and
Larry Hastings31826802013-10-19 00:09:25 -07002174 (cls.format_unit not in legacy_converters)):
2175 legacy_converters[cls.format_unit] = cls
2176 return cls
2177
2178def add_legacy_c_converter(format_unit, **kwargs):
2179 """
2180 Adds a legacy converter.
2181 """
2182 def closure(f):
2183 if not kwargs:
2184 added_f = f
2185 else:
2186 added_f = functools.partial(f, **kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002187 if format_unit:
2188 legacy_converters[format_unit] = added_f
Larry Hastings31826802013-10-19 00:09:25 -07002189 return f
2190 return closure
2191
2192class CConverterAutoRegister(type):
2193 def __init__(cls, name, bases, classdict):
2194 add_c_converter(cls)
2195 add_default_legacy_c_converter(cls)
2196
2197class CConverter(metaclass=CConverterAutoRegister):
2198 """
2199 For the init function, self, name, function, and default
2200 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08002201 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07002202 """
2203
Larry Hastings7726ac92014-01-31 22:03:12 -08002204 # The C name to use for this variable.
2205 name = None
2206
2207 # The Python name to use for this variable.
2208 py_name = None
2209
Larry Hastings78cf85c2014-01-04 12:44:57 -08002210 # The C type to use for this variable.
2211 # 'type' should be a Python string specifying the type, e.g. "int".
2212 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002213 type = None
Larry Hastings31826802013-10-19 00:09:25 -07002214
2215 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08002216 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08002217 # Or the magic value "unknown" if this value is a cannot be evaluated
2218 # at Argument-Clinic-preprocessing time (but is presumed to be valid
2219 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07002220 default = unspecified
2221
Larry Hastings4a55fc52014-01-12 11:09:57 -08002222 # If not None, default must be isinstance() of this type.
2223 # (You can also specify a tuple of types.)
2224 default_type = None
2225
Larry Hastings31826802013-10-19 00:09:25 -07002226 # "default" converted into a C value, as a string.
2227 # Or None if there is no default.
2228 c_default = None
2229
Larry Hastings2a727912014-01-16 11:32:01 -08002230 # "default" converted into a Python value, as a string.
2231 # Or None if there is no default.
2232 py_default = None
2233
Larry Hastingsabc716b2013-11-20 09:13:52 -08002234 # The default value used to initialize the C variable when
2235 # there is no default, but not specifying a default may
2236 # result in an "uninitialized variable" warning. This can
2237 # easily happen when using option groups--although
2238 # properly-written code won't actually use the variable,
2239 # the variable does get passed in to the _impl. (Ah, if
2240 # only dataflow analysis could inline the static function!)
2241 #
2242 # This value is specified as a string.
2243 # Every non-abstract subclass should supply a valid value.
2244 c_ignored_default = 'NULL'
2245
Larry Hastings31826802013-10-19 00:09:25 -07002246 # The C converter *function* to be used, if any.
2247 # (If this is not None, format_unit must be 'O&'.)
2248 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002249
Larry Hastings78cf85c2014-01-04 12:44:57 -08002250 # Should Argument Clinic add a '&' before the name of
2251 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07002252 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08002253
2254 # Should Argument Clinic add a '&' before the name of
2255 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07002256 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08002257
2258 #############################################################
2259 #############################################################
2260 ## You shouldn't need to read anything below this point to ##
2261 ## write your own converter functions. ##
2262 #############################################################
2263 #############################################################
2264
2265 # The "format unit" to specify for this variable when
2266 # parsing arguments using PyArg_ParseTuple (AndKeywords).
2267 # Custom converters should always use the default value of 'O&'.
2268 format_unit = 'O&'
2269
2270 # What encoding do we want for this variable? Only used
2271 # by format units starting with 'e'.
2272 encoding = None
2273
Larry Hastings77561cc2014-01-07 12:13:13 -08002274 # Should this object be required to be a subclass of a specific type?
2275 # If not None, should be a string representing a pointer to a
2276 # PyTypeObject (e.g. "&PyUnicode_Type").
2277 # Only used by the 'O!' format unit (and the "object" converter).
2278 subclass_of = None
2279
Larry Hastings78cf85c2014-01-04 12:44:57 -08002280 # Do we want an adjacent '_length' variable for this variable?
2281 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07002282 length = False
2283
Larry Hastings5c661892014-01-24 06:17:25 -08002284 # Should we show this parameter in the generated
2285 # __text_signature__? This is *almost* always True.
Larry Hastingsc2047262014-01-25 20:43:29 -08002286 # (It's only False for __new__, __init__, and METH_STATIC functions.)
Larry Hastings5c661892014-01-24 06:17:25 -08002287 show_in_signature = True
2288
2289 # Overrides the name used in a text signature.
2290 # The name used for a "self" parameter must be one of
2291 # self, type, or module; however users can set their own.
2292 # This lets the self_converter overrule the user-settable
2293 # name, *just* for the text signature.
2294 # Only set by self_converter.
2295 signature_name = None
2296
2297 # keep in sync with self_converter.__init__!
Larry Hastings7726ac92014-01-31 22:03:12 -08002298 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 -07002299 self.name = name
Larry Hastings7726ac92014-01-31 22:03:12 -08002300 self.py_name = py_name
Larry Hastings31826802013-10-19 00:09:25 -07002301
2302 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08002303 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002304 if isinstance(self.default_type, type):
2305 types_str = self.default_type.__name__
2306 else:
2307 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2308 fail("{}: default value {!r} for field {} is not of type {}".format(
2309 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002310 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002311
Larry Hastingsb4705752014-01-18 21:54:15 -08002312 if c_default:
2313 self.c_default = c_default
2314 if py_default:
2315 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002316
Larry Hastings31826802013-10-19 00:09:25 -07002317 if annotation != unspecified:
2318 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings7726ac92014-01-31 22:03:12 -08002319
2320 # this is deliberate, to prevent you from caching information
2321 # about the function in the init.
2322 # (that breaks if we get cloned.)
2323 # so after this change we will noisily fail.
2324 self.function = LandMine("Don't access members of self.function inside converter_init!")
Larry Hastings31826802013-10-19 00:09:25 -07002325 self.converter_init(**kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002326 self.function = function
Larry Hastings31826802013-10-19 00:09:25 -07002327
2328 def converter_init(self):
2329 pass
2330
2331 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002332 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002333
Larry Hastings5c661892014-01-24 06:17:25 -08002334 def _render_self(self, parameter, data):
2335 self.parameter = parameter
2336 original_name = self.name
2337 name = ensure_legal_c_identifier(original_name)
2338
2339 # impl_arguments
2340 s = ("&" if self.impl_by_reference else "") + name
2341 data.impl_arguments.append(s)
2342 if self.length:
2343 data.impl_arguments.append(self.length_name())
2344
2345 # impl_parameters
2346 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2347 if self.length:
2348 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2349
2350 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002351 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002352 original_name = self.name
2353 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002354
2355 # declarations
2356 d = self.declaration()
2357 data.declarations.append(d)
2358
2359 # initializers
2360 initializers = self.initialize()
2361 if initializers:
2362 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2363
Larry Hastingsc2047262014-01-25 20:43:29 -08002364 # modifications
2365 modifications = self.modify()
2366 if modifications:
2367 data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2368
Larry Hastings31826802013-10-19 00:09:25 -07002369 # keywords
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03002370 if parameter.is_positional_only():
2371 data.keywords.append('')
2372 else:
2373 data.keywords.append(parameter.name)
Larry Hastings31826802013-10-19 00:09:25 -07002374
2375 # format_units
2376 if self.is_optional() and '|' not in data.format_units:
2377 data.format_units.append('|')
2378 if parameter.is_keyword_only() and '$' not in data.format_units:
2379 data.format_units.append('$')
2380 data.format_units.append(self.format_unit)
2381
2382 # parse_arguments
2383 self.parse_argument(data.parse_arguments)
2384
Larry Hastings31826802013-10-19 00:09:25 -07002385 # cleanup
2386 cleanup = self.cleanup()
2387 if cleanup:
2388 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2389
Larry Hastings5c661892014-01-24 06:17:25 -08002390 def render(self, parameter, data):
2391 """
2392 parameter is a clinic.Parameter instance.
2393 data is a CRenderData instance.
2394 """
2395 self._render_self(parameter, data)
2396 self._render_non_self(parameter, data)
2397
Larry Hastingsebdcb502013-11-23 14:54:00 -08002398 def length_name(self):
2399 """Computes the name of the associated "length" variable."""
2400 if not self.length:
2401 return None
2402 return ensure_legal_c_identifier(self.name) + "_length"
2403
Larry Hastings31826802013-10-19 00:09:25 -07002404 # Why is this one broken out separately?
2405 # For "positional-only" function parsing,
2406 # which generates a bunch of PyArg_ParseTuple calls.
2407 def parse_argument(self, list):
2408 assert not (self.converter and self.encoding)
2409 if self.format_unit == 'O&':
2410 assert self.converter
2411 list.append(self.converter)
2412
2413 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002414 list.append(c_repr(self.encoding))
2415 elif self.subclass_of:
2416 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002417
Larry Hastingsebdcb502013-11-23 14:54:00 -08002418 legal_name = ensure_legal_c_identifier(self.name)
2419 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002420 list.append(s)
2421
Larry Hastingsebdcb502013-11-23 14:54:00 -08002422 if self.length:
2423 list.append("&" + self.length_name())
2424
Larry Hastings31826802013-10-19 00:09:25 -07002425 #
2426 # All the functions after here are intended as extension points.
2427 #
2428
2429 def simple_declaration(self, by_reference=False):
2430 """
2431 Computes the basic declaration of the variable.
2432 Used in computing the prototype declaration and the
2433 variable declaration.
2434 """
2435 prototype = [self.type]
2436 if by_reference or not self.type.endswith('*'):
2437 prototype.append(" ")
2438 if by_reference:
2439 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002440 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002441 return "".join(prototype)
2442
2443 def declaration(self):
2444 """
2445 The C statement to declare this variable.
2446 """
2447 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002448 default = self.c_default
2449 if not default and self.parameter.group:
2450 default = self.c_ignored_default
2451 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002452 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002453 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002454 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002455 if self.length:
2456 declaration.append('\nPy_ssize_clean_t ')
2457 declaration.append(self.length_name())
2458 declaration.append(';')
Serhiy Storchakaebe95fd2016-06-09 16:02:15 +03002459 return "".join(declaration)
Larry Hastings31826802013-10-19 00:09:25 -07002460
2461 def initialize(self):
2462 """
2463 The C statements required to set up this variable before parsing.
2464 Returns a string containing this code indented at column 0.
2465 If no initialization is necessary, returns an empty string.
2466 """
2467 return ""
2468
Larry Hastingsc2047262014-01-25 20:43:29 -08002469 def modify(self):
2470 """
2471 The C statements required to modify this variable after parsing.
2472 Returns a string containing this code indented at column 0.
2473 If no initialization is necessary, returns an empty string.
2474 """
2475 return ""
2476
Larry Hastings31826802013-10-19 00:09:25 -07002477 def cleanup(self):
2478 """
2479 The C statements required to clean up after this variable.
2480 Returns a string containing this code indented at column 0.
2481 If no cleanup is necessary, returns an empty string.
2482 """
2483 return ""
2484
Larry Hastings7726ac92014-01-31 22:03:12 -08002485 def pre_render(self):
2486 """
2487 A second initialization function, like converter_init,
2488 called just before rendering.
2489 You are permitted to examine self.function here.
2490 """
2491 pass
2492
Larry Hastings31826802013-10-19 00:09:25 -07002493
2494class bool_converter(CConverter):
2495 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002496 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002497 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002498 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002499
2500 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002501 if self.default is not unspecified:
2502 self.default = bool(self.default)
2503 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002504
2505class char_converter(CConverter):
2506 type = 'char'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002507 default_type = (bytes, bytearray)
Larry Hastings31826802013-10-19 00:09:25 -07002508 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002509 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002510
Larry Hastings4a55fc52014-01-12 11:09:57 -08002511 def converter_init(self):
Larry Hastings7f90cba2015-04-15 23:02:12 -04002512 if isinstance(self.default, self.default_type) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002513 fail("char_converter: illegal default value " + repr(self.default))
2514
2515
Larry Hastings31826802013-10-19 00:09:25 -07002516@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002517class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002518 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002519 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002520 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002521 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002522
2523 def converter_init(self, *, bitwise=False):
2524 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002525 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002526
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002527class byte_converter(unsigned_char_converter): pass
2528
Larry Hastings31826802013-10-19 00:09:25 -07002529class short_converter(CConverter):
2530 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002531 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002532 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002533 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002534
2535class unsigned_short_converter(CConverter):
2536 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002537 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002538 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002539 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002540
2541 def converter_init(self, *, bitwise=False):
2542 if not bitwise:
2543 fail("Unsigned shorts must be bitwise (for now).")
2544
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002545@add_legacy_c_converter('C', accept={str})
Larry Hastings31826802013-10-19 00:09:25 -07002546class int_converter(CConverter):
2547 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002548 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002549 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002550 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002551
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002552 def converter_init(self, *, accept={int}, type=None):
2553 if accept == {str}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002554 self.format_unit = 'C'
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002555 elif accept != {int}:
2556 fail("int_converter: illegal 'accept' argument " + repr(accept))
Larry Hastingsdfbeb162014-10-13 10:39:41 +01002557 if type != None:
2558 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002559
2560class unsigned_int_converter(CConverter):
2561 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002562 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002563 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002564 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002565
2566 def converter_init(self, *, bitwise=False):
2567 if not bitwise:
2568 fail("Unsigned ints must be bitwise (for now).")
2569
2570class long_converter(CConverter):
2571 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002572 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002573 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002574 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002575
2576class unsigned_long_converter(CConverter):
2577 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002578 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002579 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002580 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002581
2582 def converter_init(self, *, bitwise=False):
2583 if not bitwise:
2584 fail("Unsigned longs must be bitwise (for now).")
2585
2586class PY_LONG_LONG_converter(CConverter):
2587 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002588 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002589 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002590 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002591
2592class unsigned_PY_LONG_LONG_converter(CConverter):
2593 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002594 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002595 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002596 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002597
2598 def converter_init(self, *, bitwise=False):
2599 if not bitwise:
2600 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2601
2602class Py_ssize_t_converter(CConverter):
2603 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002604 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002605 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002606 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002607
2608
2609class float_converter(CConverter):
2610 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002611 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002612 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002613 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002614
2615class double_converter(CConverter):
2616 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002617 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002618 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002619 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002620
2621
2622class Py_complex_converter(CConverter):
2623 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002624 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002625 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002626 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002627
2628
2629class object_converter(CConverter):
2630 type = 'PyObject *'
2631 format_unit = 'O'
2632
Larry Hastings4a55fc52014-01-12 11:09:57 -08002633 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2634 if converter:
2635 if subclass_of:
2636 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2637 self.format_unit = 'O&'
2638 self.converter = converter
2639 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002640 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002641 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002642
Larry Hastings77561cc2014-01-07 12:13:13 -08002643 if type is not None:
2644 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002645
2646
Larry Hastings7f90cba2015-04-15 23:02:12 -04002647#
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002648# We define three conventions for buffer types in the 'accept' argument:
2649#
2650# buffer : any object supporting the buffer interface
2651# rwbuffer: any object supporting the buffer interface, but must be writeable
2652# robuffer: any object supporting the buffer interface, but must not be writeable
Larry Hastings7f90cba2015-04-15 23:02:12 -04002653#
2654
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002655class buffer: pass
2656class rwbuffer: pass
2657class robuffer: pass
2658
Larry Hastings38337d12015-05-07 23:30:09 -07002659def str_converter_key(types, encoding, zeroes):
2660 return (frozenset(types), bool(encoding), bool(zeroes))
2661
2662str_converter_argument_map = {}
2663
Larry Hastings31826802013-10-19 00:09:25 -07002664class str_converter(CConverter):
2665 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002666 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002667 format_unit = 's'
2668
Larry Hastings38337d12015-05-07 23:30:09 -07002669 def converter_init(self, *, accept={str}, encoding=None, zeroes=False):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002670
Larry Hastings38337d12015-05-07 23:30:09 -07002671 key = str_converter_key(accept, encoding, zeroes)
2672 format_unit = str_converter_argument_map.get(key)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002673 if not format_unit:
Larry Hastings38337d12015-05-07 23:30:09 -07002674 fail("str_converter: illegal combination of arguments", key)
2675
Larry Hastingsebdcb502013-11-23 14:54:00 -08002676 self.format_unit = format_unit
Larry Hastings38337d12015-05-07 23:30:09 -07002677 self.length = bool(zeroes)
2678 if encoding:
2679 if self.default not in (Null, None, unspecified):
2680 fail("str_converter: Argument Clinic doesn't support default values for encoded strings")
2681 self.encoding = encoding
2682 self.type = 'char *'
2683 # sorry, clinic can't support preallocated buffers
2684 # for es# and et#
2685 self.c_default = "NULL"
2686
2687 def cleanup(self):
2688 if self.encoding:
2689 name = ensure_legal_c_identifier(self.name)
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03002690 return "".join(["if (", name, ") {\n PyMem_FREE(", name, ");\n}\n"])
Larry Hastings38337d12015-05-07 23:30:09 -07002691
2692#
2693# This is the fourth or fifth rewrite of registering all the
2694# crazy string converter format units. Previous approaches hid
2695# bugs--generally mismatches between the semantics of the format
2696# unit and the arguments necessary to represent those semantics
2697# properly. Hopefully with this approach we'll get it 100% right.
2698#
2699# The r() function (short for "register") both registers the
2700# mapping from arguments to format unit *and* registers the
2701# legacy C converter for that format unit.
2702#
2703def r(format_unit, *, accept, encoding=False, zeroes=False):
2704 if not encoding and format_unit != 's':
2705 # add the legacy c converters here too.
2706 #
2707 # note: add_legacy_c_converter can't work for
2708 # es, es#, et, or et#
2709 # because of their extra encoding argument
2710 #
2711 # also don't add the converter for 's' because
2712 # the metaclass for CConverter adds it for us.
2713 kwargs = {}
2714 if accept != {str}:
2715 kwargs['accept'] = accept
2716 if zeroes:
2717 kwargs['zeroes'] = True
2718 added_f = functools.partial(str_converter, **kwargs)
2719 legacy_converters[format_unit] = added_f
2720
2721 d = str_converter_argument_map
2722 key = str_converter_key(accept, encoding, zeroes)
2723 if key in d:
2724 sys.exit("Duplicate keys specified for str_converter_argument_map!")
2725 d[key] = format_unit
2726
2727r('es', encoding=True, accept={str})
2728r('es#', encoding=True, zeroes=True, accept={str})
2729r('et', encoding=True, accept={bytes, bytearray, str})
2730r('et#', encoding=True, zeroes=True, accept={bytes, bytearray, str})
2731r('s', accept={str})
2732r('s#', zeroes=True, accept={robuffer, str})
2733r('y', accept={robuffer})
2734r('y#', zeroes=True, accept={robuffer})
2735r('z', accept={str, NoneType})
2736r('z#', zeroes=True, accept={robuffer, str, NoneType})
2737del r
Larry Hastings31826802013-10-19 00:09:25 -07002738
2739
2740class PyBytesObject_converter(CConverter):
2741 type = 'PyBytesObject *'
2742 format_unit = 'S'
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002743 # accept = {bytes}
Larry Hastings31826802013-10-19 00:09:25 -07002744
2745class PyByteArrayObject_converter(CConverter):
2746 type = 'PyByteArrayObject *'
2747 format_unit = 'Y'
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002748 # accept = {bytearray}
Larry Hastings31826802013-10-19 00:09:25 -07002749
2750class unicode_converter(CConverter):
2751 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002752 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002753 format_unit = 'U'
2754
Larry Hastings38337d12015-05-07 23:30:09 -07002755@add_legacy_c_converter('u#', zeroes=True)
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002756@add_legacy_c_converter('Z', accept={str, NoneType})
Larry Hastings38337d12015-05-07 23:30:09 -07002757@add_legacy_c_converter('Z#', accept={str, NoneType}, zeroes=True)
Larry Hastings31826802013-10-19 00:09:25 -07002758class Py_UNICODE_converter(CConverter):
2759 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002760 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002761 format_unit = 'u'
2762
Larry Hastings38337d12015-05-07 23:30:09 -07002763 def converter_init(self, *, accept={str}, zeroes=False):
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002764 format_unit = 'Z' if accept=={str, NoneType} else 'u'
Larry Hastings38337d12015-05-07 23:30:09 -07002765 if zeroes:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002766 format_unit += '#'
2767 self.length = True
2768 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002769
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002770@add_legacy_c_converter('s*', accept={str, buffer})
2771@add_legacy_c_converter('z*', accept={str, buffer, NoneType})
2772@add_legacy_c_converter('w*', accept={rwbuffer})
Larry Hastings31826802013-10-19 00:09:25 -07002773class Py_buffer_converter(CConverter):
2774 type = 'Py_buffer'
2775 format_unit = 'y*'
2776 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002777 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002778
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002779 def converter_init(self, *, accept={buffer}):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002780 if self.default not in (unspecified, None):
2781 fail("The only legal default value for Py_buffer is None.")
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002782
Larry Hastings3f144c22014-01-06 10:34:00 -08002783 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002784
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002785 if accept == {str, buffer, NoneType}:
2786 format_unit = 'z*'
2787 elif accept == {str, buffer}:
2788 format_unit = 's*'
2789 elif accept == {buffer}:
2790 format_unit = 'y*'
2791 elif accept == {rwbuffer}:
2792 format_unit = 'w*'
Larry Hastings31826802013-10-19 00:09:25 -07002793 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002794 fail("Py_buffer_converter: illegal combination of arguments")
2795
2796 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002797
2798 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002799 name = ensure_legal_c_identifier(self.name)
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03002800 return "".join(["if (", name, ".obj) {\n PyBuffer_Release(&", name, ");\n}\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002801
2802
Larry Hastings5c661892014-01-24 06:17:25 -08002803def correct_name_for_self(f):
2804 if f.kind in (CALLABLE, METHOD_INIT):
2805 if f.cls:
2806 return "PyObject *", "self"
2807 return "PyModuleDef *", "module"
2808 if f.kind == STATIC_METHOD:
2809 return "void *", "null"
2810 if f.kind in (CLASS_METHOD, METHOD_NEW):
2811 return "PyTypeObject *", "type"
2812 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2813
Larry Hastingsc2047262014-01-25 20:43:29 -08002814def required_type_for_self_for_parser(f):
2815 type, _ = correct_name_for_self(f)
2816 if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2817 return type
2818 return None
2819
Larry Hastings5c661892014-01-24 06:17:25 -08002820
Larry Hastingsebdcb502013-11-23 14:54:00 -08002821class self_converter(CConverter):
2822 """
2823 A special-case converter:
2824 this is the default converter used for "self".
2825 """
Larry Hastings5c661892014-01-24 06:17:25 -08002826 type = None
2827 format_unit = ''
2828
Larry Hastings78cf85c2014-01-04 12:44:57 -08002829 def converter_init(self, *, type=None):
Larry Hastings7726ac92014-01-31 22:03:12 -08002830 self.specified_type = type
2831
2832 def pre_render(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002833 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002834 default_type, default_name = correct_name_for_self(f)
2835 self.signature_name = default_name
Larry Hastings7726ac92014-01-31 22:03:12 -08002836 self.type = self.specified_type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002837
Larry Hastings5c661892014-01-24 06:17:25 -08002838 kind = self.function.kind
2839 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2840
2841 if (kind == STATIC_METHOD) or new_or_init:
2842 self.show_in_signature = False
2843
2844 # tp_new (METHOD_NEW) functions are of type newfunc:
2845 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2846 # PyTypeObject is a typedef for struct _typeobject.
2847 #
2848 # tp_init (METHOD_INIT) functions are of type initproc:
2849 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2850 #
2851 # All other functions generated by Argument Clinic are stored in
2852 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2853 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2854 # However! We habitually cast these functions to PyCFunction,
2855 # since functions that accept keyword arguments don't fit this signature
2856 # but are stored there anyway. So strict type equality isn't important
2857 # for these functions.
2858 #
2859 # So:
2860 #
2861 # * The name of the first parameter to the impl and the parsing function will always
2862 # be self.name.
2863 #
2864 # * The type of the first parameter to the impl will always be of self.type.
2865 #
2866 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2867 # * The type of the first parameter to the parsing function is also self.type.
2868 # This means that if you step into the parsing function, your "self" parameter
2869 # is of the correct type, which may make debugging more pleasant.
2870 #
2871 # * Else if the function is tp_new (METHOD_NEW):
2872 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2873 # so the type signature of the function call is an exact match.
2874 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2875 # in the impl call.
2876 #
2877 # * Else if the function is tp_init (METHOD_INIT):
2878 # * The type of the first parameter to the parsing function is "PyObject *",
2879 # so the type signature of the function call is an exact match.
2880 # * If self.type != "PyObject *", we cast the first parameter to self.type
2881 # in the impl call.
2882
2883 @property
2884 def parser_type(self):
Larry Hastingsc2047262014-01-25 20:43:29 -08002885 return required_type_for_self_for_parser(self.function) or self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002886
Larry Hastingsebdcb502013-11-23 14:54:00 -08002887 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002888 """
2889 parameter is a clinic.Parameter instance.
2890 data is a CRenderData instance.
2891 """
2892 if self.function.kind == STATIC_METHOD:
2893 return
2894
2895 self._render_self(parameter, data)
2896
2897 if self.type != self.parser_type:
2898 # insert cast to impl_argument[0], aka self.
2899 # we know we're in the first slot in all the CRenderData lists,
2900 # because we render parameters in order, and self is always first.
2901 assert len(data.impl_arguments) == 1
2902 assert data.impl_arguments[0] == self.name
2903 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2904
2905 def set_template_dict(self, template_dict):
2906 template_dict['self_name'] = self.name
2907 template_dict['self_type'] = self.parser_type
Larry Hastingsf0537e82014-01-25 22:01:12 -08002908 kind = self.function.kind
2909 cls = self.function.cls
2910
2911 if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef):
2912 if kind == METHOD_NEW:
2913 passed_in_type = self.name
2914 else:
2915 passed_in_type = 'Py_TYPE({})'.format(self.name)
2916
2917 line = '({passed_in_type} == {type_object}) &&\n '
2918 d = {
2919 'type_object': self.function.cls.type_object,
2920 'passed_in_type': passed_in_type
2921 }
2922 template_dict['self_type_check'] = line.format_map(d)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002923
Larry Hastings31826802013-10-19 00:09:25 -07002924
2925
2926def add_c_return_converter(f, name=None):
2927 if not name:
2928 name = f.__name__
2929 if not name.endswith('_return_converter'):
2930 return f
2931 name = name[:-len('_return_converter')]
2932 return_converters[name] = f
2933 return f
2934
2935
2936class CReturnConverterAutoRegister(type):
2937 def __init__(cls, name, bases, classdict):
2938 add_c_return_converter(cls)
2939
2940class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2941
Larry Hastings78cf85c2014-01-04 12:44:57 -08002942 # The C type to use for this variable.
2943 # 'type' should be a Python string specifying the type, e.g. "int".
2944 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002945 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002946
2947 # The Python default value for this parameter, as a Python value.
2948 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002949 default = None
2950
Larry Hastings2a727912014-01-16 11:32:01 -08002951 def __init__(self, *, py_default=None, **kwargs):
2952 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002953 try:
2954 self.return_converter_init(**kwargs)
2955 except TypeError as e:
2956 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2957 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2958
2959 def return_converter_init(self):
2960 pass
2961
2962 def declare(self, data, name="_return_value"):
2963 line = []
2964 add = line.append
2965 add(self.type)
2966 if not self.type.endswith('*'):
2967 add(' ')
2968 add(name + ';')
2969 data.declarations.append(''.join(line))
2970 data.return_value = name
2971
2972 def err_occurred_if(self, expr, data):
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03002973 data.return_conversion.append('if (({}) && PyErr_Occurred()) {{\n goto exit;\n}}\n'.format(expr))
Larry Hastings31826802013-10-19 00:09:25 -07002974
2975 def err_occurred_if_null_pointer(self, variable, data):
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03002976 data.return_conversion.append('if ({} == NULL) {{\n goto exit;\n}}\n'.format(variable))
Larry Hastings31826802013-10-19 00:09:25 -07002977
2978 def render(self, function, data):
2979 """
2980 function is a clinic.Function instance.
2981 data is a CRenderData instance.
2982 """
2983 pass
2984
2985add_c_return_converter(CReturnConverter, 'object')
2986
Larry Hastings78cf85c2014-01-04 12:44:57 -08002987class NoneType_return_converter(CReturnConverter):
2988 def render(self, function, data):
2989 self.declare(data)
2990 data.return_conversion.append('''
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03002991if (_return_value != Py_None) {
Larry Hastings78cf85c2014-01-04 12:44:57 -08002992 goto exit;
Serhiy Storchaka5dee6552016-06-09 16:16:06 +03002993}
Larry Hastings78cf85c2014-01-04 12:44:57 -08002994return_value = Py_None;
2995Py_INCREF(Py_None);
2996'''.strip())
2997
Larry Hastings4a55fc52014-01-12 11:09:57 -08002998class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002999 type = 'int'
3000
3001 def render(self, function, data):
3002 self.declare(data)
3003 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08003004 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07003005
3006class long_return_converter(CReturnConverter):
3007 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003008 conversion_fn = 'PyLong_FromLong'
3009 cast = ''
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003010 unsigned_cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07003011
3012 def render(self, function, data):
3013 self.declare(data)
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003014 self.err_occurred_if("_return_value == {}-1".format(self.unsigned_cast), data)
Larry Hastings31826802013-10-19 00:09:25 -07003015 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08003016 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07003017
Larry Hastings4a55fc52014-01-12 11:09:57 -08003018class int_return_converter(long_return_converter):
3019 type = 'int'
3020 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07003021
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003022class init_return_converter(long_return_converter):
3023 """
3024 Special return converter for __init__ functions.
3025 """
3026 type = 'int'
3027 cast = '(long)'
3028
3029 def render(self, function, data):
3030 pass
3031
Larry Hastings4a55fc52014-01-12 11:09:57 -08003032class unsigned_long_return_converter(long_return_converter):
3033 type = 'unsigned long'
3034 conversion_fn = 'PyLong_FromUnsignedLong'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003035 unsigned_cast = '(unsigned long)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003036
3037class unsigned_int_return_converter(unsigned_long_return_converter):
3038 type = 'unsigned int'
3039 cast = '(unsigned long)'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003040 unsigned_cast = '(unsigned int)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003041
3042class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07003043 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003044 conversion_fn = 'PyLong_FromSsize_t'
3045
3046class size_t_return_converter(long_return_converter):
3047 type = 'size_t'
3048 conversion_fn = 'PyLong_FromSize_t'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003049 unsigned_cast = '(size_t)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003050
3051
3052class double_return_converter(CReturnConverter):
3053 type = 'double'
3054 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07003055
3056 def render(self, function, data):
3057 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08003058 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07003059 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08003060 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
3061
3062class float_return_converter(double_return_converter):
3063 type = 'float'
3064 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07003065
3066
3067class DecodeFSDefault_return_converter(CReturnConverter):
3068 type = 'char *'
3069
3070 def render(self, function, data):
3071 self.declare(data)
3072 self.err_occurred_if_null_pointer("_return_value", data)
3073 data.return_conversion.append(
3074 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
3075
3076
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003077def eval_ast_expr(node, globals, *, filename='-'):
3078 """
3079 Takes an ast.Expr node. Compiles and evaluates it.
3080 Returns the result of the expression.
3081
3082 globals represents the globals dict the expression
3083 should see. (There's no equivalent for "locals" here.)
3084 """
3085
3086 if isinstance(node, ast.Expr):
3087 node = node.value
3088
3089 node = ast.Expression(node)
3090 co = compile(node, filename, 'eval')
3091 fn = types.FunctionType(co, globals)
3092 return fn()
3093
3094
Larry Hastings31826802013-10-19 00:09:25 -07003095class IndentStack:
3096 def __init__(self):
3097 self.indents = []
3098 self.margin = None
3099
3100 def _ensure(self):
3101 if not self.indents:
3102 fail('IndentStack expected indents, but none are defined.')
3103
3104 def measure(self, line):
3105 """
3106 Returns the length of the line's margin.
3107 """
3108 if '\t' in line:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003109 fail('Tab characters are illegal in the Argument Clinic DSL.')
Larry Hastings31826802013-10-19 00:09:25 -07003110 stripped = line.lstrip()
3111 if not len(stripped):
3112 # we can't tell anything from an empty line
3113 # so just pretend it's indented like our current indent
3114 self._ensure()
3115 return self.indents[-1]
3116 return len(line) - len(stripped)
3117
3118 def infer(self, line):
3119 """
3120 Infer what is now the current margin based on this line.
3121 Returns:
3122 1 if we have indented (or this is the first margin)
3123 0 if the margin has not changed
3124 -N if we have dedented N times
3125 """
3126 indent = self.measure(line)
3127 margin = ' ' * indent
3128 if not self.indents:
3129 self.indents.append(indent)
3130 self.margin = margin
3131 return 1
3132 current = self.indents[-1]
3133 if indent == current:
3134 return 0
3135 if indent > current:
3136 self.indents.append(indent)
3137 self.margin = margin
3138 return 1
3139 # indent < current
3140 if indent not in self.indents:
3141 fail("Illegal outdent.")
3142 outdent_count = 0
3143 while indent != current:
3144 self.indents.pop()
3145 current = self.indents[-1]
3146 outdent_count -= 1
3147 self.margin = margin
3148 return outdent_count
3149
3150 @property
3151 def depth(self):
3152 """
3153 Returns how many margins are currently defined.
3154 """
3155 return len(self.indents)
3156
3157 def indent(self, line):
3158 """
3159 Indents a line by the currently defined margin.
3160 """
3161 return self.margin + line
3162
3163 def dedent(self, line):
3164 """
3165 Dedents a line by the currently defined margin.
3166 (The inverse of 'indent'.)
3167 """
3168 margin = self.margin
3169 indent = self.indents[-1]
3170 if not line.startswith(margin):
3171 fail('Cannot dedent, line does not start with the previous margin:')
3172 return line[indent:]
3173
3174
3175class DSLParser:
3176 def __init__(self, clinic):
3177 self.clinic = clinic
3178
3179 self.directives = {}
3180 for name in dir(self):
3181 # functions that start with directive_ are added to directives
3182 _, s, key = name.partition("directive_")
3183 if s:
3184 self.directives[key] = getattr(self, name)
3185
3186 # functions that start with at_ are too, with an @ in front
3187 _, s, key = name.partition("at_")
3188 if s:
3189 self.directives['@' + key] = getattr(self, name)
3190
3191 self.reset()
3192
3193 def reset(self):
3194 self.function = None
3195 self.state = self.state_dsl_start
3196 self.parameter_indent = None
3197 self.keyword_only = False
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03003198 self.positional_only = False
Larry Hastings31826802013-10-19 00:09:25 -07003199 self.group = 0
3200 self.parameter_state = self.ps_start
Larry Hastingsc2047262014-01-25 20:43:29 -08003201 self.seen_positional_with_default = False
Larry Hastings31826802013-10-19 00:09:25 -07003202 self.indent = IndentStack()
3203 self.kind = CALLABLE
3204 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08003205 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08003206 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07003207
Larry Hastingsebdcb502013-11-23 14:54:00 -08003208 def directive_version(self, required):
3209 global version
3210 if version_comparitor(version, required) < 0:
3211 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
3212
Larry Hastings31826802013-10-19 00:09:25 -07003213 def directive_module(self, name):
3214 fields = name.split('.')
3215 new = fields.pop()
3216 module, cls = self.clinic._module_and_class(fields)
3217 if cls:
3218 fail("Can't nest a module inside a class!")
Larry Hastingsc2047262014-01-25 20:43:29 -08003219
3220 if name in module.classes:
3221 fail("Already defined module " + repr(name) + "!")
3222
Larry Hastings31826802013-10-19 00:09:25 -07003223 m = Module(name, module)
3224 module.modules[name] = m
3225 self.block.signatures.append(m)
3226
Larry Hastingsc2047262014-01-25 20:43:29 -08003227 def directive_class(self, name, typedef, type_object):
Larry Hastings31826802013-10-19 00:09:25 -07003228 fields = name.split('.')
3229 in_classes = False
3230 parent = self
3231 name = fields.pop()
3232 so_far = []
3233 module, cls = self.clinic._module_and_class(fields)
3234
Larry Hastingsc2047262014-01-25 20:43:29 -08003235 parent = cls or module
3236 if name in parent.classes:
3237 fail("Already defined class " + repr(name) + "!")
3238
3239 c = Class(name, module, cls, typedef, type_object)
3240 parent.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07003241 self.block.signatures.append(c)
3242
Larry Hastingsbebf7352014-01-17 17:47:17 -08003243 def directive_set(self, name, value):
3244 if name not in ("line_prefix", "line_suffix"):
3245 fail("unknown variable", repr(name))
3246
3247 value = value.format_map({
3248 'block comment start': '/*',
3249 'block comment end': '*/',
3250 })
3251
3252 self.clinic.__dict__[name] = value
3253
3254 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06003255 if command == 'new':
3256 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003257 return
3258
Zachary Ware071baa62014-01-21 23:07:12 -06003259 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08003260 self.clinic.get_destination(name).clear()
3261 fail("unknown destination command", repr(command))
3262
3263
Larry Hastings0759f842015-04-03 13:09:02 -07003264 def directive_output(self, command_or_name, destination=''):
3265 fd = self.clinic.destination_buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08003266
Larry Hastings0759f842015-04-03 13:09:02 -07003267 if command_or_name == "preset":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003268 preset = self.clinic.presets.get(destination)
3269 if not preset:
3270 fail("Unknown preset " + repr(destination) + "!")
3271 fd.update(preset)
3272 return
3273
Larry Hastings0759f842015-04-03 13:09:02 -07003274 if command_or_name == "push":
3275 self.clinic.destination_buffers_stack.append(fd.copy())
Larry Hastingsbebf7352014-01-17 17:47:17 -08003276 return
3277
Larry Hastings0759f842015-04-03 13:09:02 -07003278 if command_or_name == "pop":
3279 if not self.clinic.destination_buffers_stack:
Larry Hastingsbebf7352014-01-17 17:47:17 -08003280 fail("Can't 'output pop', stack is empty!")
Larry Hastings0759f842015-04-03 13:09:02 -07003281 previous_fd = self.clinic.destination_buffers_stack.pop()
Larry Hastingsbebf7352014-01-17 17:47:17 -08003282 fd.update(previous_fd)
3283 return
3284
3285 # secret command for debugging!
Larry Hastings0759f842015-04-03 13:09:02 -07003286 if command_or_name == "print":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003287 self.block.output.append(pprint.pformat(fd))
3288 self.block.output.append('\n')
3289 return
3290
3291 d = self.clinic.get_destination(destination)
3292
Larry Hastings0759f842015-04-03 13:09:02 -07003293 if command_or_name == "everything":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003294 for name in list(fd):
3295 fd[name] = d
3296 return
3297
Larry Hastings0759f842015-04-03 13:09:02 -07003298 if command_or_name not in fd:
3299 fail("Invalid command / destination name " + repr(command_or_name) + ", must be one of:\n preset push pop print everything " + " ".join(fd))
3300 fd[command_or_name] = d
Larry Hastingsbebf7352014-01-17 17:47:17 -08003301
3302 def directive_dump(self, name):
3303 self.block.output.append(self.clinic.get_destination(name).dump())
3304
3305 def directive_print(self, *args):
3306 self.block.output.append(' '.join(args))
3307 self.block.output.append('\n')
3308
3309 def directive_preserve(self):
3310 if self.preserve_output:
3311 fail("Can't have preserve twice in one block!")
3312 self.preserve_output = True
3313
Larry Hastings31826802013-10-19 00:09:25 -07003314 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003315 if self.kind is not CALLABLE:
3316 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003317 self.kind = CLASS_METHOD
3318
3319 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003320 if self.kind is not CALLABLE:
3321 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003322 self.kind = STATIC_METHOD
3323
3324 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003325 if self.coexist:
3326 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07003327 self.coexist = True
3328
3329 def parse(self, block):
3330 self.reset()
3331 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08003332 self.saved_output = self.block.output
3333 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07003334 block_start = self.clinic.block_parser.line_number
3335 lines = block.input.split('\n')
3336 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
3337 if '\t' in line:
3338 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
3339 self.state(line)
3340
3341 self.next(self.state_terminal)
3342 self.state(None)
3343
Larry Hastingsbebf7352014-01-17 17:47:17 -08003344 block.output.extend(self.clinic.language.render(clinic, block.signatures))
3345
3346 if self.preserve_output:
3347 if block.output:
3348 fail("'preserve' only works for blocks that don't produce any output!")
3349 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07003350
3351 @staticmethod
3352 def ignore_line(line):
3353 # ignore comment-only lines
3354 if line.lstrip().startswith('#'):
3355 return True
3356
3357 # Ignore empty lines too
3358 # (but not in docstring sections!)
3359 if not line.strip():
3360 return True
3361
3362 return False
3363
3364 @staticmethod
3365 def calculate_indent(line):
3366 return len(line) - len(line.strip())
3367
3368 def next(self, state, line=None):
3369 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3370 self.state = state
3371 if line is not None:
3372 self.state(line)
3373
3374 def state_dsl_start(self, line):
3375 # self.block = self.ClinicOutputBlock(self)
3376 if self.ignore_line(line):
3377 return
Larry Hastings7726ac92014-01-31 22:03:12 -08003378
3379 # is it a directive?
3380 fields = shlex.split(line)
3381 directive_name = fields[0]
3382 directive = self.directives.get(directive_name, None)
3383 if directive:
3384 try:
3385 directive(*fields[1:])
3386 except TypeError as e:
3387 fail(str(e))
3388 return
3389
Larry Hastings31826802013-10-19 00:09:25 -07003390 self.next(self.state_modulename_name, line)
3391
3392 def state_modulename_name(self, line):
3393 # looking for declaration, which establishes the leftmost column
3394 # line should be
3395 # modulename.fnname [as c_basename] [-> return annotation]
3396 # square brackets denote optional syntax.
3397 #
Larry Hastings4a714d42014-01-14 22:22:41 -08003398 # alternatively:
3399 # modulename.fnname [as c_basename] = modulename.existing_fn_name
3400 # clones the parameters and return converter from that
3401 # function. you can't modify them. you must enter a
3402 # new docstring.
3403 #
Larry Hastings31826802013-10-19 00:09:25 -07003404 # (but we might find a directive first!)
3405 #
3406 # this line is permitted to start with whitespace.
3407 # we'll call this number of spaces F (for "function").
3408
3409 if not line.strip():
3410 return
3411
3412 self.indent.infer(line)
3413
Larry Hastings4a714d42014-01-14 22:22:41 -08003414 # are we cloning?
3415 before, equals, existing = line.rpartition('=')
3416 if equals:
3417 full_name, _, c_basename = before.partition(' as ')
3418 full_name = full_name.strip()
3419 c_basename = c_basename.strip()
3420 existing = existing.strip()
3421 if (is_legal_py_identifier(full_name) and
3422 (not c_basename or is_legal_c_identifier(c_basename)) and
3423 is_legal_py_identifier(existing)):
3424 # we're cloning!
3425 fields = [x.strip() for x in existing.split('.')]
3426 function_name = fields.pop()
3427 module, cls = self.clinic._module_and_class(fields)
3428
3429 for existing_function in (cls or module).functions:
3430 if existing_function.name == function_name:
3431 break
3432 else:
3433 existing_function = None
3434 if not existing_function:
Larry Hastings7726ac92014-01-31 22:03:12 -08003435 print("class", cls, "module", module, "existing", existing)
Larry Hastingsc2047262014-01-25 20:43:29 -08003436 print("cls. functions", cls.functions)
Larry Hastings4a714d42014-01-14 22:22:41 -08003437 fail("Couldn't find existing function " + repr(existing) + "!")
3438
3439 fields = [x.strip() for x in full_name.split('.')]
3440 function_name = fields.pop()
3441 module, cls = self.clinic._module_and_class(fields)
3442
3443 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3444 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
Larry Hastings7726ac92014-01-31 22:03:12 -08003445 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 -08003446
3447 self.block.signatures.append(self.function)
3448 (cls or module).functions.append(self.function)
3449 self.next(self.state_function_docstring)
3450 return
3451
Larry Hastings31826802013-10-19 00:09:25 -07003452 line, _, returns = line.partition('->')
3453
3454 full_name, _, c_basename = line.partition(' as ')
3455 full_name = full_name.strip()
3456 c_basename = c_basename.strip() or None
3457
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003458 if not is_legal_py_identifier(full_name):
3459 fail("Illegal function name: {}".format(full_name))
3460 if c_basename and not is_legal_c_identifier(c_basename):
3461 fail("Illegal C basename: {}".format(c_basename))
3462
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003463 return_converter = None
3464 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003465 ast_input = "def x() -> {}: pass".format(returns)
3466 module = None
3467 try:
3468 module = ast.parse(ast_input)
3469 except SyntaxError:
3470 pass
3471 if not module:
3472 fail("Badly-formed annotation for " + full_name + ": " + returns)
3473 try:
3474 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003475 if legacy:
3476 fail("Legacy converter {!r} not allowed as a return converter"
3477 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003478 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003479 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003480 return_converter = return_converters[name](**kwargs)
3481 except ValueError:
3482 fail("Badly-formed annotation for " + full_name + ": " + returns)
3483
3484 fields = [x.strip() for x in full_name.split('.')]
3485 function_name = fields.pop()
3486 module, cls = self.clinic._module_and_class(fields)
3487
Larry Hastings8666e652014-01-12 14:12:59 -08003488 fields = full_name.split('.')
3489 if fields[-1] == '__new__':
3490 if (self.kind != CLASS_METHOD) or (not cls):
3491 fail("__new__ must be a class method!")
3492 self.kind = METHOD_NEW
3493 elif fields[-1] == '__init__':
3494 if (self.kind != CALLABLE) or (not cls):
3495 fail("__init__ must be a normal method, not a class or static method!")
3496 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003497 if not return_converter:
3498 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003499 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003500 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003501
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003502 if not return_converter:
3503 return_converter = CReturnConverter()
3504
Larry Hastings31826802013-10-19 00:09:25 -07003505 if not module:
3506 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3507 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3508 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3509 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003510
3511 # insert a self converter automatically
Larry Hastingsc2047262014-01-25 20:43:29 -08003512 type, name = correct_name_for_self(self.function)
3513 kwargs = {}
3514 if cls and type == "PyObject *":
3515 kwargs['type'] = cls.typedef
Larry Hastings7726ac92014-01-31 22:03:12 -08003516 sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs)
Larry Hastings5c661892014-01-24 06:17:25 -08003517 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3518 self.function.parameters[sc.name] = p_self
3519
Larry Hastings4a714d42014-01-14 22:22:41 -08003520 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003521 self.next(self.state_parameters_start)
3522
3523 # Now entering the parameters section. The rules, formally stated:
3524 #
3525 # * All lines must be indented with spaces only.
3526 # * The first line must be a parameter declaration.
3527 # * The first line must be indented.
3528 # * This first line establishes the indent for parameters.
3529 # * We'll call this number of spaces P (for "parameter").
3530 # * Thenceforth:
3531 # * Lines indented with P spaces specify a parameter.
3532 # * Lines indented with > P spaces are docstrings for the previous
3533 # parameter.
3534 # * We'll call this number of spaces D (for "docstring").
3535 # * All subsequent lines indented with >= D spaces are stored as
3536 # part of the per-parameter docstring.
3537 # * All lines will have the first D spaces of the indent stripped
3538 # before they are stored.
3539 # * It's illegal to have a line starting with a number of spaces X
3540 # such that P < X < D.
3541 # * A line with < P spaces is the first line of the function
3542 # docstring, which ends processing for parameters and per-parameter
3543 # docstrings.
3544 # * The first line of the function docstring must be at the same
3545 # indent as the function declaration.
3546 # * It's illegal to have any line in the parameters section starting
3547 # with X spaces such that F < X < P. (As before, F is the indent
3548 # of the function declaration.)
3549 #
Larry Hastings31826802013-10-19 00:09:25 -07003550 # Also, currently Argument Clinic places the following restrictions on groups:
3551 # * Each group must contain at least one parameter.
3552 # * Each group may contain at most one group, which must be the furthest
3553 # thing in the group from the required parameters. (The nested group
3554 # must be the first in the group when it's before the required
3555 # parameters, and the last thing in the group when after the required
3556 # parameters.)
3557 # * There may be at most one (top-level) group to the left or right of
3558 # the required parameters.
3559 # * You must specify a slash, and it must be after all parameters.
3560 # (In other words: either all parameters are positional-only,
3561 # or none are.)
3562 #
3563 # Said another way:
3564 # * Each group must contain at least one parameter.
3565 # * All left square brackets before the required parameters must be
3566 # consecutive. (You can't have a left square bracket followed
3567 # by a parameter, then another left square bracket. You can't
3568 # have a left square bracket, a parameter, a right square bracket,
3569 # and then a left square bracket.)
3570 # * All right square brackets after the required parameters must be
3571 # consecutive.
3572 #
3573 # These rules are enforced with a single state variable:
3574 # "parameter_state". (Previously the code was a miasma of ifs and
3575 # separate boolean state variables.) The states are:
3576 #
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03003577 # [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ] <- line
3578 # 01 2 3 4 5 6 <- state transitions
Larry Hastings31826802013-10-19 00:09:25 -07003579 #
3580 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3581 # 1: ps_left_square_before. left square brackets before required parameters.
3582 # 2: ps_group_before. in a group, before required parameters.
Larry Hastingsc2047262014-01-25 20:43:29 -08003583 # 3: ps_required. required parameters, positional-or-keyword or positional-only
3584 # (we don't know yet). (renumber left groups!)
3585 # 4: ps_optional. positional-or-keyword or positional-only parameters that
3586 # now must have default values.
3587 # 5: ps_group_after. in a group, after required parameters.
3588 # 6: ps_right_square_after. right square brackets after required parameters.
Larry Hastings31826802013-10-19 00:09:25 -07003589 ps_start, ps_left_square_before, ps_group_before, ps_required, \
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03003590 ps_optional, ps_group_after, ps_right_square_after = range(7)
Larry Hastings31826802013-10-19 00:09:25 -07003591
3592 def state_parameters_start(self, line):
3593 if self.ignore_line(line):
3594 return
3595
3596 # if this line is not indented, we have no parameters
3597 if not self.indent.infer(line):
3598 return self.next(self.state_function_docstring, line)
3599
Larry Hastings2a727912014-01-16 11:32:01 -08003600 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003601 return self.next(self.state_parameter, line)
3602
3603
3604 def to_required(self):
3605 """
3606 Transition to the "required" parameter state.
3607 """
3608 if self.parameter_state != self.ps_required:
3609 self.parameter_state = self.ps_required
3610 for p in self.function.parameters.values():
3611 p.group = -p.group
3612
3613 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003614 if self.parameter_continuation:
3615 line = self.parameter_continuation + ' ' + line.lstrip()
3616 self.parameter_continuation = ''
3617
Larry Hastings31826802013-10-19 00:09:25 -07003618 if self.ignore_line(line):
3619 return
3620
3621 assert self.indent.depth == 2
3622 indent = self.indent.infer(line)
3623 if indent == -1:
3624 # we outdented, must be to definition column
3625 return self.next(self.state_function_docstring, line)
3626
3627 if indent == 1:
3628 # we indented, must be to new parameter docstring column
3629 return self.next(self.state_parameter_docstring_start, line)
3630
Larry Hastings2a727912014-01-16 11:32:01 -08003631 line = line.rstrip()
3632 if line.endswith('\\'):
3633 self.parameter_continuation = line[:-1]
3634 return
3635
Larry Hastings31826802013-10-19 00:09:25 -07003636 line = line.lstrip()
3637
3638 if line in ('*', '/', '[', ']'):
3639 self.parse_special_symbol(line)
3640 return
3641
3642 if self.parameter_state in (self.ps_start, self.ps_required):
3643 self.to_required()
3644 elif self.parameter_state == self.ps_left_square_before:
3645 self.parameter_state = self.ps_group_before
3646 elif self.parameter_state == self.ps_group_before:
3647 if not self.group:
3648 self.to_required()
Larry Hastingsc2047262014-01-25 20:43:29 -08003649 elif self.parameter_state in (self.ps_group_after, self.ps_optional):
Larry Hastings31826802013-10-19 00:09:25 -07003650 pass
3651 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003652 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
Larry Hastings31826802013-10-19 00:09:25 -07003653
Larry Hastings7726ac92014-01-31 22:03:12 -08003654 # handle "as" for parameters too
3655 c_name = None
3656 name, have_as_token, trailing = line.partition(' as ')
3657 if have_as_token:
3658 name = name.strip()
3659 if ' ' not in name:
3660 fields = trailing.strip().split(' ')
3661 if not fields:
3662 fail("Invalid 'as' clause!")
3663 c_name = fields[0]
3664 if c_name.endswith(':'):
3665 name += ':'
3666 c_name = c_name[:-1]
3667 fields[0] = name
3668 line = ' '.join(fields)
3669
Larry Hastings2a727912014-01-16 11:32:01 -08003670 base, equals, default = line.rpartition('=')
3671 if not equals:
3672 base = default
3673 default = None
Larry Hastingsc2047262014-01-25 20:43:29 -08003674
Larry Hastings31826802013-10-19 00:09:25 -07003675 module = None
3676 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003677 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003678 module = ast.parse(ast_input)
3679 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003680 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08003681 # the last = was probably inside a function call, like
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003682 # c: int(accept={str})
Larry Hastingsc2047262014-01-25 20:43:29 -08003683 # so assume there was no actual default value.
Larry Hastings2a727912014-01-16 11:32:01 -08003684 default = None
3685 ast_input = "def x({}): pass".format(line)
3686 module = ast.parse(ast_input)
3687 except SyntaxError:
3688 pass
Larry Hastings31826802013-10-19 00:09:25 -07003689 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003690 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003691
3692 function_args = module.body[0].args
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003693
3694 if len(function_args.args) > 1:
3695 fail("Function " + self.function.name + " has an invalid parameter declaration (comma?):\n\t" + line)
3696 if function_args.defaults or function_args.kw_defaults:
3697 fail("Function " + self.function.name + " has an invalid parameter declaration (default value?):\n\t" + line)
3698 if function_args.vararg or function_args.kwarg:
3699 fail("Function " + self.function.name + " has an invalid parameter declaration (*args? **kwargs?):\n\t" + line)
3700
Larry Hastings31826802013-10-19 00:09:25 -07003701 parameter = function_args.args[0]
3702
Larry Hastings16c51912014-01-07 11:53:01 -08003703 parameter_name = parameter.arg
3704 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3705
Larry Hastings2a727912014-01-16 11:32:01 -08003706 if not default:
Larry Hastingsc2047262014-01-25 20:43:29 -08003707 if self.parameter_state == self.ps_optional:
3708 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 -08003709 value = unspecified
3710 if 'py_default' in kwargs:
3711 fail("You can't specify py_default without specifying a default value!")
3712 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003713 if self.parameter_state == self.ps_required:
3714 self.parameter_state = self.ps_optional
Larry Hastings2a727912014-01-16 11:32:01 -08003715 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003716 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003717 ast_input = "x = {}".format(default)
Larry Hastingsc2047262014-01-25 20:43:29 -08003718 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003719 try:
3720 module = ast.parse(ast_input)
3721
Larry Hastings5c661892014-01-24 06:17:25 -08003722 if 'c_default' not in kwargs:
3723 # we can only represent very simple data values in C.
3724 # detect whether default is okay, via a blacklist
3725 # of disallowed ast nodes.
3726 class DetectBadNodes(ast.NodeVisitor):
3727 bad = False
3728 def bad_node(self, node):
3729 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003730
Larry Hastings5c661892014-01-24 06:17:25 -08003731 # inline function call
3732 visit_Call = bad_node
3733 # inline if statement ("x = 3 if y else z")
3734 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003735
Larry Hastings5c661892014-01-24 06:17:25 -08003736 # comprehensions and generator expressions
3737 visit_ListComp = visit_SetComp = bad_node
3738 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003739
Larry Hastings5c661892014-01-24 06:17:25 -08003740 # literals for advanced types
3741 visit_Dict = visit_Set = bad_node
3742 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003743
Larry Hastings5c661892014-01-24 06:17:25 -08003744 # "starred": "a = [1, 2, 3]; *a"
3745 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003746
Larry Hastings5c661892014-01-24 06:17:25 -08003747 # allow ellipsis, for now
3748 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003749
Larry Hastings5c661892014-01-24 06:17:25 -08003750 blacklist = DetectBadNodes()
3751 blacklist.visit(module)
3752 bad = blacklist.bad
3753 else:
3754 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003755 # but at least make an attempt at ensuring it's a valid expression.
3756 try:
3757 value = eval(default)
3758 if value == unspecified:
3759 fail("'unspecified' is not a legal default value!")
3760 except NameError:
3761 pass # probably a named constant
3762 except Exception as e:
3763 fail("Malformed expression given as default value\n"
3764 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003765 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003766 fail("Unsupported expression as default value: " + repr(default))
3767
3768 expr = module.body[0].value
3769 # mild hack: explicitly support NULL as a default value
3770 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3771 value = NULL
3772 py_default = 'None'
3773 c_default = "NULL"
3774 elif (isinstance(expr, ast.BinOp) or
3775 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3776 c_default = kwargs.get("c_default")
3777 if not (isinstance(c_default, str) and c_default):
3778 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3779 py_default = default
3780 value = unknown
3781 elif isinstance(expr, ast.Attribute):
3782 a = []
3783 n = expr
3784 while isinstance(n, ast.Attribute):
3785 a.append(n.attr)
3786 n = n.value
3787 if not isinstance(n, ast.Name):
3788 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3789 a.append(n.id)
3790 py_default = ".".join(reversed(a))
3791
3792 c_default = kwargs.get("c_default")
3793 if not (isinstance(c_default, str) and c_default):
3794 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3795
3796 try:
3797 value = eval(py_default)
3798 except NameError:
3799 value = unknown
3800 else:
3801 value = ast.literal_eval(expr)
3802 py_default = repr(value)
3803 if isinstance(value, (bool, None.__class__)):
3804 c_default = "Py_" + py_default
3805 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003806 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003807 else:
3808 c_default = py_default
3809
3810 except SyntaxError as e:
3811 fail("Syntax error: " + repr(e.text))
3812 except (ValueError, AttributeError):
3813 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003814 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003815 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003816 if not (isinstance(c_default, str) and c_default):
3817 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3818
Larry Hastings2a727912014-01-16 11:32:01 -08003819 kwargs.setdefault('c_default', c_default)
3820 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003821
Larry Hastings31826802013-10-19 00:09:25 -07003822 dict = legacy_converters if legacy else converters
3823 legacy_str = "legacy " if legacy else ""
3824 if name not in dict:
3825 fail('{} is not a valid {}converter'.format(name, legacy_str))
Larry Hastings7726ac92014-01-31 22:03:12 -08003826 # if you use a c_name for the parameter, we just give that name to the converter
3827 # but the parameter object gets the python name
3828 converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
Larry Hastings31826802013-10-19 00:09:25 -07003829
3830 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003831
3832 if isinstance(converter, self_converter):
3833 if len(self.function.parameters) == 1:
3834 if (self.parameter_state != self.ps_required):
3835 fail("A 'self' parameter cannot be marked optional.")
3836 if value is not unspecified:
3837 fail("A 'self' parameter cannot have a default value.")
3838 if self.group:
3839 fail("A 'self' parameter cannot be in an optional group.")
3840 kind = inspect.Parameter.POSITIONAL_ONLY
3841 self.parameter_state = self.ps_start
3842 self.function.parameters.clear()
3843 else:
3844 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3845
Larry Hastings31826802013-10-19 00:09:25 -07003846 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003847
3848 if parameter_name in self.function.parameters:
3849 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003850 self.function.parameters[parameter_name] = p
3851
3852 def parse_converter(self, annotation):
3853 if isinstance(annotation, ast.Str):
3854 return annotation.s, True, {}
3855
3856 if isinstance(annotation, ast.Name):
3857 return annotation.id, False, {}
3858
Larry Hastings4a55fc52014-01-12 11:09:57 -08003859 if not isinstance(annotation, ast.Call):
3860 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003861
3862 name = annotation.func.id
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003863 symbols = globals()
3864
3865 kwargs = {node.arg: eval_ast_expr(node.value, symbols) for node in annotation.keywords}
Larry Hastings31826802013-10-19 00:09:25 -07003866 return name, False, kwargs
3867
3868 def parse_special_symbol(self, symbol):
Larry Hastings31826802013-10-19 00:09:25 -07003869 if symbol == '*':
3870 if self.keyword_only:
3871 fail("Function " + self.function.name + " uses '*' more than once.")
3872 self.keyword_only = True
3873 elif symbol == '[':
3874 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3875 self.parameter_state = self.ps_left_square_before
3876 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3877 self.parameter_state = self.ps_group_after
3878 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003879 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
Larry Hastings31826802013-10-19 00:09:25 -07003880 self.group += 1
Larry Hastings2623c8c2014-02-08 22:15:29 -08003881 self.function.docstring_only = True
Larry Hastings31826802013-10-19 00:09:25 -07003882 elif symbol == ']':
3883 if not self.group:
3884 fail("Function " + self.function.name + " has a ] without a matching [.")
3885 if not any(p.group == self.group for p in self.function.parameters.values()):
3886 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3887 self.group -= 1
3888 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3889 self.parameter_state = self.ps_group_before
3890 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3891 self.parameter_state = self.ps_right_square_after
3892 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003893 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
Larry Hastings31826802013-10-19 00:09:25 -07003894 elif symbol == '/':
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03003895 if self.positional_only:
3896 fail("Function " + self.function.name + " uses '/' more than once.")
3897 self.positional_only = True
Larry Hastingsc2047262014-01-25 20:43:29 -08003898 # ps_required and ps_optional are allowed here, that allows positional-only without option groups
Larry Hastings31826802013-10-19 00:09:25 -07003899 # to work (and have default values!)
Larry Hastingsc2047262014-01-25 20:43:29 -08003900 if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
3901 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
Larry Hastings31826802013-10-19 00:09:25 -07003902 if self.keyword_only:
3903 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
Berker Peksagf23530f2014-10-19 18:04:38 +03003904 # fixup preceding parameters
Larry Hastings31826802013-10-19 00:09:25 -07003905 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003906 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003907 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3908 p.kind = inspect.Parameter.POSITIONAL_ONLY
3909
3910 def state_parameter_docstring_start(self, line):
3911 self.parameter_docstring_indent = len(self.indent.margin)
3912 assert self.indent.depth == 3
3913 return self.next(self.state_parameter_docstring, line)
3914
3915 # every line of the docstring must start with at least F spaces,
3916 # where F > P.
3917 # these F spaces will be stripped.
3918 def state_parameter_docstring(self, line):
3919 stripped = line.strip()
3920 if stripped.startswith('#'):
3921 return
3922
3923 indent = self.indent.measure(line)
3924 if indent < self.parameter_docstring_indent:
3925 self.indent.infer(line)
3926 assert self.indent.depth < 3
3927 if self.indent.depth == 2:
3928 # back to a parameter
3929 return self.next(self.state_parameter, line)
3930 assert self.indent.depth == 1
3931 return self.next(self.state_function_docstring, line)
3932
3933 assert self.function.parameters
3934 last_parameter = next(reversed(list(self.function.parameters.values())))
3935
3936 new_docstring = last_parameter.docstring
3937
3938 if new_docstring:
3939 new_docstring += '\n'
3940 if stripped:
3941 new_docstring += self.indent.dedent(line)
3942
3943 last_parameter.docstring = new_docstring
3944
3945 # the final stanza of the DSL is the docstring.
3946 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003947 if self.group:
3948 fail("Function " + self.function.name + " has a ] without a matching [.")
3949
3950 stripped = line.strip()
3951 if stripped.startswith('#'):
3952 return
3953
3954 new_docstring = self.function.docstring
3955 if new_docstring:
3956 new_docstring += "\n"
3957 if stripped:
3958 line = self.indent.dedent(line).rstrip()
3959 else:
3960 line = ''
3961 new_docstring += line
3962 self.function.docstring = new_docstring
3963
3964 def format_docstring(self):
3965 f = self.function
3966
Larry Hastings5c661892014-01-24 06:17:25 -08003967 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3968 if new_or_init and not f.docstring:
3969 # don't render a docstring at all, no signature, nothing.
3970 return f.docstring
3971
Larry Hastings2623c8c2014-02-08 22:15:29 -08003972 text, add, output = _text_accumulator()
Larry Hastings7726ac92014-01-31 22:03:12 -08003973 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07003974
3975 ##
3976 ## docstring first line
3977 ##
3978
Larry Hastings2623c8c2014-02-08 22:15:29 -08003979 if new_or_init:
3980 # classes get *just* the name of the class
3981 # not __new__, not __init__, and not module.classname
3982 assert f.cls
3983 add(f.cls.name)
Larry Hastings46258262014-01-22 03:05:49 -08003984 else:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003985 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003986 add('(')
3987
3988 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003989 assert parameters, "We should always have a self parameter. " + repr(f)
3990 assert isinstance(parameters[0].converter, self_converter)
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03003991 # self is always positional-only.
3992 assert parameters[0].is_positional_only()
Larry Hastings5c661892014-01-24 06:17:25 -08003993 parameters[0].right_bracket_count = 0
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03003994 positional_only = True
3995 for p in parameters[1:]:
3996 if not p.is_positional_only():
3997 positional_only = False
3998 else:
3999 assert positional_only
4000 if positional_only:
4001 p.right_bracket_count = abs(p.group)
Larry Hastings31826802013-10-19 00:09:25 -07004002 else:
4003 # don't put any right brackets around non-positional-only parameters, ever.
Serhiy Storchakaf41b82f2016-06-09 16:30:29 +03004004 p.right_bracket_count = 0
Larry Hastings31826802013-10-19 00:09:25 -07004005
4006 right_bracket_count = 0
4007
4008 def fix_right_bracket_count(desired):
4009 nonlocal right_bracket_count
4010 s = ''
4011 while right_bracket_count < desired:
4012 s += '['
4013 right_bracket_count += 1
4014 while right_bracket_count > desired:
4015 s += ']'
4016 right_bracket_count -= 1
4017 return s
4018
Larry Hastings2623c8c2014-02-08 22:15:29 -08004019 need_slash = False
4020 added_slash = False
4021 need_a_trailing_slash = False
4022
4023 # we only need a trailing slash:
4024 # * if this is not a "docstring_only" signature
4025 # * and if the last *shown* parameter is
4026 # positional only
4027 if not f.docstring_only:
4028 for p in reversed(parameters):
4029 if not p.converter.show_in_signature:
4030 continue
4031 if p.is_positional_only():
4032 need_a_trailing_slash = True
4033 break
4034
4035
Larry Hastings31826802013-10-19 00:09:25 -07004036 added_star = False
Larry Hastings2623c8c2014-02-08 22:15:29 -08004037
4038 first_parameter = True
4039 last_p = parameters[-1]
4040 line_length = len(''.join(text))
4041 indent = " " * line_length
4042 def add_parameter(text):
4043 nonlocal line_length
4044 nonlocal first_parameter
4045 if first_parameter:
4046 s = text
4047 first_parameter = False
4048 else:
4049 s = ' ' + text
4050 if line_length + len(s) >= 72:
4051 add('\n')
4052 add(indent)
4053 line_length = len(indent)
4054 s = text
4055 line_length += len(s)
4056 add(s)
Larry Hastings31826802013-10-19 00:09:25 -07004057
4058 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08004059 if not p.converter.show_in_signature:
4060 continue
Larry Hastings31826802013-10-19 00:09:25 -07004061 assert p.name
4062
Larry Hastings2623c8c2014-02-08 22:15:29 -08004063 is_self = isinstance(p.converter, self_converter)
4064 if is_self and f.docstring_only:
4065 # this isn't a real machine-parsable signature,
4066 # so let's not print the "self" parameter
4067 continue
4068
4069 if p.is_positional_only():
4070 need_slash = not f.docstring_only
4071 elif need_slash and not (added_slash or p.is_positional_only()):
4072 added_slash = True
4073 add_parameter('/,')
4074
Larry Hastings31826802013-10-19 00:09:25 -07004075 if p.is_keyword_only() and not added_star:
4076 added_star = True
Larry Hastings2623c8c2014-02-08 22:15:29 -08004077 add_parameter('*,')
4078
4079 p_add, p_output = text_accumulator()
4080 p_add(fix_right_bracket_count(p.right_bracket_count))
4081
4082 if isinstance(p.converter, self_converter):
4083 # annotate first parameter as being a "self".
4084 #
4085 # if inspect.Signature gets this function,
4086 # and it's already bound, the self parameter
4087 # will be stripped off.
4088 #
4089 # if it's not bound, it should be marked
4090 # as positional-only.
4091 #
4092 # note: we don't print "self" for __init__,
4093 # because this isn't actually the signature
4094 # for __init__. (it can't be, __init__ doesn't
4095 # have a docstring.) if this is an __init__
4096 # (or __new__), then this signature is for
Berker Peksagf23530f2014-10-19 18:04:38 +03004097 # calling the class to construct a new instance.
Larry Hastings2623c8c2014-02-08 22:15:29 -08004098 p_add('$')
Larry Hastings31826802013-10-19 00:09:25 -07004099
Larry Hastings5c661892014-01-24 06:17:25 -08004100 name = p.converter.signature_name or p.name
Larry Hastings2623c8c2014-02-08 22:15:29 -08004101 p_add(name)
Larry Hastings581ee362014-01-28 05:00:08 -08004102
Larry Hastings31826802013-10-19 00:09:25 -07004103 if p.converter.is_optional():
Larry Hastings2623c8c2014-02-08 22:15:29 -08004104 p_add('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08004105 value = p.converter.py_default
4106 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08004107 value = repr(p.converter.default)
Larry Hastings2623c8c2014-02-08 22:15:29 -08004108 p_add(value)
4109
4110 if (p != last_p) or need_a_trailing_slash:
4111 p_add(',')
4112
4113 add_parameter(p_output())
Larry Hastings31826802013-10-19 00:09:25 -07004114
4115 add(fix_right_bracket_count(0))
Larry Hastings2623c8c2014-02-08 22:15:29 -08004116 if need_a_trailing_slash:
4117 add_parameter('/')
Larry Hastings31826802013-10-19 00:09:25 -07004118 add(')')
4119
Larry Hastings2a727912014-01-16 11:32:01 -08004120 # PEP 8 says:
4121 #
4122 # The Python standard library will not use function annotations
4123 # as that would result in a premature commitment to a particular
4124 # annotation style. Instead, the annotations are left for users
4125 # to discover and experiment with useful annotation styles.
4126 #
4127 # therefore this is commented out:
4128 #
4129 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004130 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08004131 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07004132
Larry Hastings2623c8c2014-02-08 22:15:29 -08004133 if not f.docstring_only:
Zachary Ware8ef887c2015-04-13 18:22:35 -05004134 add("\n" + sig_end_marker + "\n")
Larry Hastings2623c8c2014-02-08 22:15:29 -08004135
Larry Hastings31826802013-10-19 00:09:25 -07004136 docstring_first_line = output()
4137
4138 # now fix up the places where the brackets look wrong
4139 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
4140
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004141 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07004142 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004143 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07004144 for p in parameters:
4145 if not p.docstring.strip():
4146 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004147 if spacer_line:
4148 add('\n')
4149 else:
4150 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07004151 add(" ")
4152 add(p.name)
4153 add('\n')
4154 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004155 parameters = output()
4156 if parameters:
4157 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07004158
4159 ##
4160 ## docstring body
4161 ##
4162
4163 docstring = f.docstring.rstrip()
4164 lines = [line.rstrip() for line in docstring.split('\n')]
4165
4166 # Enforce the summary line!
4167 # The first line of a docstring should be a summary of the function.
4168 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
4169 # by itself.
4170 #
4171 # Argument Clinic enforces the following rule:
4172 # * either the docstring is empty,
4173 # * or it must have a summary line.
4174 #
4175 # Guido said Clinic should enforce this:
4176 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
4177
4178 if len(lines) >= 2:
4179 if lines[1]:
4180 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
4181 "Every non-blank function docstring must start with\n" +
4182 "a single line summary followed by an empty line.")
4183 elif len(lines) == 1:
4184 # the docstring is only one line right now--the summary line.
4185 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004186 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07004187 lines.append('')
4188
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004189 parameters_marker_count = len(docstring.split('{parameters}')) - 1
4190 if parameters_marker_count > 1:
4191 fail('You may not specify {parameters} more than once in a docstring!')
4192
4193 if not parameters_marker_count:
4194 # insert after summary line
4195 lines.insert(2, '{parameters}')
4196
4197 # insert at front of docstring
4198 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07004199
4200 docstring = "\n".join(lines)
4201
4202 add(docstring)
4203 docstring = output()
4204
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004205 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07004206 docstring = docstring.rstrip()
4207
4208 return docstring
4209
4210 def state_terminal(self, line):
4211 """
4212 Called when processing the block is done.
4213 """
4214 assert not line
4215
4216 if not self.function:
4217 return
4218
4219 if self.keyword_only:
4220 values = self.function.parameters.values()
4221 if not values:
4222 no_parameter_after_star = True
4223 else:
4224 last_parameter = next(reversed(list(values)))
4225 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
4226 if no_parameter_after_star:
4227 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
4228
4229 # remove trailing whitespace from all parameter docstrings
4230 for name, value in self.function.parameters.items():
4231 if not value:
4232 continue
4233 value.docstring = value.docstring.rstrip()
4234
4235 self.function.docstring = self.format_docstring()
4236
4237
Larry Hastings5c661892014-01-24 06:17:25 -08004238
4239
Larry Hastings31826802013-10-19 00:09:25 -07004240# maps strings to callables.
4241# the callable should return an object
4242# that implements the clinic parser
4243# interface (__init__ and parse).
4244#
4245# example parsers:
4246# "clinic", handles the Clinic DSL
4247# "python", handles running Python code
4248#
4249parsers = {'clinic' : DSLParser, 'python': PythonParser}
4250
4251
4252clinic = None
4253
4254
4255def main(argv):
4256 import sys
4257
4258 if sys.version_info.major < 3 or sys.version_info.minor < 3:
4259 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
4260
4261 import argparse
4262 cmdline = argparse.ArgumentParser()
4263 cmdline.add_argument("-f", "--force", action='store_true')
4264 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08004265 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004266 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004267 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004268 cmdline.add_argument("filename", type=str, nargs="*")
4269 ns = cmdline.parse_args(argv)
4270
4271 if ns.converters:
4272 if ns.filename:
4273 print("Usage error: can't specify --converters and a filename at the same time.")
4274 print()
4275 cmdline.print_usage()
4276 sys.exit(-1)
4277 converters = []
4278 return_converters = []
4279 ignored = set("""
4280 add_c_converter
4281 add_c_return_converter
4282 add_default_legacy_c_converter
4283 add_legacy_c_converter
4284 """.strip().split())
4285 module = globals()
4286 for name in module:
4287 for suffix, ids in (
4288 ("_return_converter", return_converters),
4289 ("_converter", converters),
4290 ):
4291 if name in ignored:
4292 continue
4293 if name.endswith(suffix):
4294 ids.append((name, name[:-len(suffix)]))
4295 break
4296 print()
4297
4298 print("Legacy converters:")
4299 legacy = sorted(legacy_converters)
4300 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
4301 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
4302 print()
4303
4304 for title, attribute, ids in (
4305 ("Converters", 'converter_init', converters),
4306 ("Return converters", 'return_converter_init', return_converters),
4307 ):
4308 print(title + ":")
4309 longest = -1
4310 for name, short_name in ids:
4311 longest = max(longest, len(short_name))
4312 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
4313 cls = module[name]
4314 callable = getattr(cls, attribute, None)
4315 if not callable:
4316 continue
4317 signature = inspect.signature(callable)
4318 parameters = []
4319 for parameter_name, parameter in signature.parameters.items():
4320 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
4321 if parameter.default != inspect.Parameter.empty:
4322 s = '{}={!r}'.format(parameter_name, parameter.default)
4323 else:
4324 s = parameter_name
4325 parameters.append(s)
4326 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07004327 print()
Larry Hastings2a727912014-01-16 11:32:01 -08004328 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
4329 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07004330 sys.exit(0)
4331
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004332 if ns.make:
4333 if ns.output or ns.filename:
4334 print("Usage error: can't use -o or filenames with --make.")
4335 print()
4336 cmdline.print_usage()
4337 sys.exit(-1)
4338 for root, dirs, files in os.walk('.'):
Zachary Warebbbbe7e2015-04-13 18:33:41 -05004339 for rcs_dir in ('.svn', '.git', '.hg', 'build', 'externals'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004340 if rcs_dir in dirs:
4341 dirs.remove(rcs_dir)
4342 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08004343 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004344 continue
4345 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08004346 if ns.verbose:
4347 print(path)
Larry Hastings581ee362014-01-28 05:00:08 -08004348 parse_file(path, force=ns.force, verify=not ns.force)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004349 return
4350
Larry Hastings31826802013-10-19 00:09:25 -07004351 if not ns.filename:
4352 cmdline.print_usage()
4353 sys.exit(-1)
4354
4355 if ns.output and len(ns.filename) > 1:
4356 print("Usage error: can't use -o with multiple filenames.")
4357 print()
4358 cmdline.print_usage()
4359 sys.exit(-1)
4360
4361 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08004362 if ns.verbose:
4363 print(filename)
Larry Hastings581ee362014-01-28 05:00:08 -08004364 parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
Larry Hastings31826802013-10-19 00:09:25 -07004365
4366
4367if __name__ == "__main__":
4368 sys.exit(main(sys.argv[1:]))