blob: 3ce3587db51bd5d57c433dd7a8ab429c535d6d53 [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
179def linear_format(s, **kwargs):
180 """
181 Perform str.format-like substitution, except:
182 * The strings substituted must be on lines by
183 themselves. (This line is the "source line".)
184 * If the substitution text is empty, the source line
185 is removed in the output.
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800186 * If the field is not recognized, the original line
187 is passed unmodified through to the output.
Larry Hastings31826802013-10-19 00:09:25 -0700188 * If the substitution text is not empty:
189 * Each line of the substituted text is indented
190 by the indent of the source line.
191 * A newline will be added to the end.
192 """
193
194 add, output = text_accumulator()
195 for line in s.split('\n'):
196 indent, curly, trailing = line.partition('{')
197 if not curly:
198 add(line)
199 add('\n')
200 continue
201
202 name, curl, trailing = trailing.partition('}')
203 if not curly or name not in kwargs:
204 add(line)
205 add('\n')
206 continue
207
208 if trailing:
209 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
210 if indent.strip():
211 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
212
213 value = kwargs[name]
214 if not value:
215 continue
216
217 value = textwrap.indent(rstrip_lines(value), indent)
218 add(value)
219 add('\n')
220
221 return output()[:-1]
222
Larry Hastingsbebf7352014-01-17 17:47:17 -0800223def indent_all_lines(s, prefix):
224 """
225 Returns 's', with 'prefix' prepended to all lines.
226
227 If the last line is empty, prefix is not prepended
228 to it. (If s is blank, returns s unchanged.)
229
230 (textwrap.indent only adds to non-blank lines.)
231 """
232 split = s.split('\n')
233 last = split.pop()
234 final = []
235 for line in split:
236 final.append(prefix)
237 final.append(line)
238 final.append('\n')
239 if last:
240 final.append(prefix)
241 final.append(last)
242 return ''.join(final)
243
244def suffix_all_lines(s, suffix):
245 """
246 Returns 's', with 'suffix' appended to all lines.
247
248 If the last line is empty, suffix is not appended
249 to it. (If s is blank, returns s unchanged.)
250 """
251 split = s.split('\n')
252 last = split.pop()
253 final = []
254 for line in split:
255 final.append(line)
256 final.append(suffix)
257 final.append('\n')
258 if last:
259 final.append(last)
260 final.append(suffix)
261 return ''.join(final)
262
263
Larry Hastingsebdcb502013-11-23 14:54:00 -0800264def version_splitter(s):
265 """Splits a version string into a tuple of integers.
266
267 The following ASCII characters are allowed, and employ
268 the following conversions:
269 a -> -3
270 b -> -2
271 c -> -1
272 (This permits Python-style version strings such as "1.4b3".)
273 """
274 version = []
275 accumulator = []
276 def flush():
277 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800278 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800279 version.append(int(''.join(accumulator)))
280 accumulator.clear()
281
282 for c in s:
283 if c.isdigit():
284 accumulator.append(c)
285 elif c == '.':
286 flush()
287 elif c in 'abc':
288 flush()
289 version.append('abc'.index(c) - 3)
290 else:
291 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
292 flush()
293 return tuple(version)
294
295def version_comparitor(version1, version2):
296 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
297 for i, (a, b) in enumerate(iterator):
298 if a < b:
299 return -1
300 if a > b:
301 return 1
302 return 0
303
Larry Hastings31826802013-10-19 00:09:25 -0700304
305class CRenderData:
306 def __init__(self):
307
308 # The C statements to declare variables.
309 # Should be full lines with \n eol characters.
310 self.declarations = []
311
312 # The C statements required to initialize the variables before the parse call.
313 # Should be full lines with \n eol characters.
314 self.initializers = []
315
Larry Hastingsc2047262014-01-25 20:43:29 -0800316 # The C statements needed to dynamically modify the values
317 # parsed by the parse call, before calling the impl.
318 self.modifications = []
319
Larry Hastings31826802013-10-19 00:09:25 -0700320 # The entries for the "keywords" array for PyArg_ParseTuple.
321 # Should be individual strings representing the names.
322 self.keywords = []
323
324 # The "format units" for PyArg_ParseTuple.
325 # Should be individual strings that will get
326 self.format_units = []
327
328 # The varargs arguments for PyArg_ParseTuple.
329 self.parse_arguments = []
330
331 # The parameter declarations for the impl function.
332 self.impl_parameters = []
333
334 # The arguments to the impl function at the time it's called.
335 self.impl_arguments = []
336
337 # For return converters: the name of the variable that
338 # should receive the value returned by the impl.
339 self.return_value = "return_value"
340
341 # For return converters: the code to convert the return
342 # value from the parse function. This is also where
343 # you should check the _return_value for errors, and
344 # "goto exit" if there are any.
345 self.return_conversion = []
346
347 # The C statements required to clean up after the impl call.
348 self.cleanup = []
349
350
Larry Hastings581ee362014-01-28 05:00:08 -0800351class FormatCounterFormatter(string.Formatter):
352 """
353 This counts how many instances of each formatter
354 "replacement string" appear in the format string.
355
356 e.g. after evaluating "string {a}, {b}, {c}, {a}"
357 the counts dict would now look like
358 {'a': 2, 'b': 1, 'c': 1}
359 """
360 def __init__(self):
361 self.counts = collections.Counter()
362
363 def get_value(self, key, args, kwargs):
364 self.counts[key] += 1
365 return ''
366
Larry Hastings31826802013-10-19 00:09:25 -0700367class Language(metaclass=abc.ABCMeta):
368
369 start_line = ""
370 body_prefix = ""
371 stop_line = ""
372 checksum_line = ""
373
Larry Hastings7726ac92014-01-31 22:03:12 -0800374 def __init__(self, filename):
375 pass
376
Larry Hastings31826802013-10-19 00:09:25 -0700377 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800378 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700379 pass
380
Larry Hastings7726ac92014-01-31 22:03:12 -0800381 def parse_line(self, line):
382 pass
383
Larry Hastings31826802013-10-19 00:09:25 -0700384 def validate(self):
Larry Hastings581ee362014-01-28 05:00:08 -0800385 def assert_only_one(attr, *additional_fields):
386 """
387 Ensures that the string found at getattr(self, attr)
388 contains exactly one formatter replacement string for
389 each valid field. The list of valid fields is
390 ['dsl_name'] extended by additional_fields.
391
392 e.g.
393 self.fmt = "{dsl_name} {a} {b}"
394
395 # this passes
396 self.assert_only_one('fmt', 'a', 'b')
397
398 # this fails, the format string has a {b} in it
399 self.assert_only_one('fmt', 'a')
400
401 # this fails, the format string doesn't have a {c} in it
402 self.assert_only_one('fmt', 'a', 'b', 'c')
403
404 # this fails, the format string has two {a}s in it,
405 # it must contain exactly one
406 self.fmt2 = '{dsl_name} {a} {a}'
407 self.assert_only_one('fmt2', 'a')
408
409 """
410 fields = ['dsl_name']
411 fields.extend(additional_fields)
412 line = getattr(self, attr)
413 fcf = FormatCounterFormatter()
414 fcf.format(line)
415 def local_fail(should_be_there_but_isnt):
416 if should_be_there_but_isnt:
417 fail("{} {} must contain {{{}}} exactly once!".format(
418 self.__class__.__name__, attr, name))
419 else:
420 fail("{} {} must not contain {{{}}}!".format(
421 self.__class__.__name__, attr, name))
422
423 for name, count in fcf.counts.items():
424 if name in fields:
425 if count > 1:
426 local_fail(True)
427 else:
428 local_fail(False)
429 for name in fields:
430 if fcf.counts.get(name) != 1:
431 local_fail(True)
432
Larry Hastings31826802013-10-19 00:09:25 -0700433 assert_only_one('start_line')
434 assert_only_one('stop_line')
Larry Hastings31826802013-10-19 00:09:25 -0700435
Larry Hastings581ee362014-01-28 05:00:08 -0800436 field = "arguments" if "{arguments}" in self.checksum_line else "checksum"
437 assert_only_one('checksum_line', field)
Larry Hastings31826802013-10-19 00:09:25 -0700438
439
440
441class PythonLanguage(Language):
442
443 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800444 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700445 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800446 stop_line = "#[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800447 checksum_line = "#/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700448
449
450def permute_left_option_groups(l):
451 """
452 Given [1, 2, 3], should yield:
453 ()
454 (3,)
455 (2, 3)
456 (1, 2, 3)
457 """
458 yield tuple()
459 accumulator = []
460 for group in reversed(l):
461 accumulator = list(group) + accumulator
462 yield tuple(accumulator)
463
464
465def permute_right_option_groups(l):
466 """
467 Given [1, 2, 3], should yield:
468 ()
469 (1,)
470 (1, 2)
471 (1, 2, 3)
472 """
473 yield tuple()
474 accumulator = []
475 for group in l:
476 accumulator.extend(group)
477 yield tuple(accumulator)
478
479
480def permute_optional_groups(left, required, right):
481 """
482 Generator function that computes the set of acceptable
483 argument lists for the provided iterables of
484 argument groups. (Actually it generates a tuple of tuples.)
485
486 Algorithm: prefer left options over right options.
487
488 If required is empty, left must also be empty.
489 """
490 required = tuple(required)
491 result = []
492
493 if not required:
494 assert not left
495
496 accumulator = []
497 counts = set()
498 for r in permute_right_option_groups(right):
499 for l in permute_left_option_groups(left):
500 t = l + required + r
501 if len(t) in counts:
502 continue
503 counts.add(len(t))
504 accumulator.append(t)
505
506 accumulator.sort(key=len)
507 return tuple(accumulator)
508
509
Larry Hastings7726ac92014-01-31 22:03:12 -0800510def strip_leading_and_trailing_blank_lines(s):
511 lines = s.rstrip().split('\n')
512 while lines:
513 line = lines[0]
514 if line.strip():
515 break
516 del lines[0]
517 return '\n'.join(lines)
518
519@functools.lru_cache()
520def normalize_snippet(s, *, indent=0):
521 """
522 Reformats s:
523 * removes leading and trailing blank lines
524 * ensures that it does not end with a newline
525 * dedents so the first nonwhite character on any line is at column "indent"
526 """
527 s = strip_leading_and_trailing_blank_lines(s)
528 s = textwrap.dedent(s)
529 if indent:
530 s = textwrap.indent(s, ' ' * indent)
531 return s
532
533
Larry Hastings89964c42015-04-14 18:07:59 -0400534def wrap_declarations(text, length=78):
535 """
536 A simple-minded text wrapper for C function declarations.
537
538 It views a declaration line as looking like this:
539 xxxxxxxx(xxxxxxxxx,xxxxxxxxx)
540 If called with length=30, it would wrap that line into
541 xxxxxxxx(xxxxxxxxx,
542 xxxxxxxxx)
543 (If the declaration has zero or one parameters, this
544 function won't wrap it.)
545
546 If this doesn't work properly, it's probably better to
547 start from scratch with a more sophisticated algorithm,
548 rather than try and improve/debug this dumb little function.
549 """
550 lines = []
551 for line in text.split('\n'):
552 prefix, _, after_l_paren = line.partition('(')
553 if not after_l_paren:
554 lines.append(line)
555 continue
556 parameters, _, after_r_paren = after_l_paren.partition(')')
557 if not _:
558 lines.append(line)
559 continue
560 if ',' not in parameters:
561 lines.append(line)
562 continue
563 parameters = [x.strip() + ", " for x in parameters.split(',')]
564 prefix += "("
565 if len(prefix) < length:
566 spaces = " " * len(prefix)
567 else:
568 spaces = " " * 4
569
570 while parameters:
571 line = prefix
572 first = True
573 while parameters:
574 if (not first and
575 (len(line) + len(parameters[0]) > length)):
576 break
577 line += parameters.pop(0)
578 first = False
579 if not parameters:
580 line = line.rstrip(", ") + ")" + after_r_paren
581 lines.append(line.rstrip())
582 prefix = spaces
583 return "\n".join(lines)
584
585
Larry Hastings31826802013-10-19 00:09:25 -0700586class CLanguage(Language):
587
Larry Hastings61272b72014-01-07 12:41:53 -0800588 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700589 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800590 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700591 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800592 stop_line = "[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800593 checksum_line = "/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700594
Larry Hastings7726ac92014-01-31 22:03:12 -0800595 def __init__(self, filename):
596 super().__init__(filename)
597 self.cpp = cpp.Monitor(filename)
598 self.cpp.fail = fail
599
600 def parse_line(self, line):
601 self.cpp.writeline(line)
602
Larry Hastingsbebf7352014-01-17 17:47:17 -0800603 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700604 function = None
605 for o in signatures:
606 if isinstance(o, Function):
607 if function:
608 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
609 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800610 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700611
612 def docstring_for_c_string(self, f):
613 text, add, output = _text_accumulator()
614 # turn docstring into a properly quoted C string
615 for line in f.docstring.split('\n'):
616 add('"')
617 add(quoted_for_c_string(line))
618 add('\\n"\n')
619
Zachary Ware8ef887c2015-04-13 18:22:35 -0500620 if text[-2] == sig_end_marker:
621 # If we only have a signature, add the blank line that the
622 # __text_signature__ getter expects to be there.
623 add('"\\n"')
624 else:
625 text.pop()
626 add('"')
Larry Hastings31826802013-10-19 00:09:25 -0700627 return ''.join(text)
628
Larry Hastingsbebf7352014-01-17 17:47:17 -0800629 def output_templates(self, f):
630 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800631 assert parameters
632 assert isinstance(parameters[0].converter, self_converter)
633 del parameters[0]
Larry Hastingsbebf7352014-01-17 17:47:17 -0800634 converters = [p.converter for p in parameters]
635
636 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
637 default_return_converter = (not f.return_converter or
638 f.return_converter.type == 'PyObject *')
639
640 positional = parameters and (parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY)
641 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
642 first_optional = len(parameters)
643 for i, p in enumerate(parameters):
644 c = p.converter
645 if type(c) != object_converter:
646 break
647 if c.format_unit != 'O':
648 break
649 if p.default is not unspecified:
650 first_optional = min(first_optional, i)
651 else:
652 all_boring_objects = True
653
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800654 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
655
Larry Hastingsbebf7352014-01-17 17:47:17 -0800656 meth_o = (len(parameters) == 1 and
657 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
658 not converters[0].is_optional() and
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800659 not new_or_init)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800660
Larry Hastings7726ac92014-01-31 22:03:12 -0800661 # we have to set these things before we're done:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800662 #
663 # docstring_prototype
664 # docstring_definition
665 # impl_prototype
666 # methoddef_define
667 # parser_prototype
668 # parser_definition
669 # impl_definition
Larry Hastings7726ac92014-01-31 22:03:12 -0800670 # cpp_if
671 # cpp_endif
672 # methoddef_ifndef
Larry Hastingsbebf7352014-01-17 17:47:17 -0800673
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800674 return_value_declaration = "PyObject *return_value = NULL;"
Larry Hastings31826802013-10-19 00:09:25 -0700675
Larry Hastings7726ac92014-01-31 22:03:12 -0800676 methoddef_define = normalize_snippet("""
677 #define {methoddef_name} \\
678 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
679 """)
Larry Hastings5c661892014-01-24 06:17:25 -0800680 if new_or_init and not f.docstring:
681 docstring_prototype = docstring_definition = ''
682 else:
Larry Hastings7726ac92014-01-31 22:03:12 -0800683 docstring_prototype = normalize_snippet("""
684 PyDoc_VAR({c_basename}__doc__);
685 """)
686 docstring_definition = normalize_snippet("""
687 PyDoc_STRVAR({c_basename}__doc__,
688 {docstring});
689 """)
690 impl_definition = normalize_snippet("""
691 static {impl_return_type}
692 {c_basename}_impl({impl_parameters})
693 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800694 impl_prototype = parser_prototype = parser_definition = None
695
Larry Hastings7726ac92014-01-31 22:03:12 -0800696 parser_prototype_keyword = normalize_snippet("""
697 static PyObject *
698 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
699 """)
700
701 parser_prototype_varargs = normalize_snippet("""
702 static PyObject *
703 {c_basename}({self_type}{self_name}, PyObject *args)
704 """)
705
706 # parser_body_fields remembers the fields passed in to the
707 # previous call to parser_body. this is used for an awful hack.
Larry Hastingsc2047262014-01-25 20:43:29 -0800708 parser_body_fields = ()
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800709 def parser_body(prototype, *fields):
710 nonlocal parser_body_fields
711 add, output = text_accumulator()
712 add(prototype)
713 parser_body_fields = fields
Larry Hastings7726ac92014-01-31 22:03:12 -0800714
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800715 fields = list(fields)
Larry Hastings7726ac92014-01-31 22:03:12 -0800716 fields.insert(0, normalize_snippet("""
717 {{
718 {return_value_declaration}
719 {declarations}
720 {initializers}
721 """) + "\n")
722 # just imagine--your code is here in the middle
723 fields.append(normalize_snippet("""
724 {modifications}
725 {return_value} = {c_basename}_impl({impl_arguments});
726 {return_conversion}
727
728 {exit_label}
729 {cleanup}
730 return return_value;
731 }}
732 """))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800733 for field in fields:
734 add('\n')
Larry Hastings7726ac92014-01-31 22:03:12 -0800735 add(field)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800736 return output()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800737
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800738 def insert_keywords(s):
739 return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
Larry Hastingsbebf7352014-01-17 17:47:17 -0800740
741 if not parameters:
742 # no parameters, METH_NOARGS
743
744 flags = "METH_NOARGS"
745
Larry Hastings7726ac92014-01-31 22:03:12 -0800746 parser_prototype = normalize_snippet("""
747 static PyObject *
748 {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
749 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800750 parser_definition = parser_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800751
752 if default_return_converter:
Larry Hastings7726ac92014-01-31 22:03:12 -0800753 parser_definition = parser_prototype + '\n' + normalize_snippet("""
754 {{
755 return {c_basename}_impl({impl_arguments});
756 }}
757 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800758 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800759 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700760
Larry Hastingsbebf7352014-01-17 17:47:17 -0800761 elif meth_o:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800762 flags = "METH_O"
Larry Hastings7726ac92014-01-31 22:03:12 -0800763
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300764 if (isinstance(converters[0], object_converter) and
765 converters[0].format_unit == 'O'):
766 meth_o_prototype = normalize_snippet("""
767 static PyObject *
768 {c_basename}({impl_parameters})
769 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800770
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300771 if default_return_converter:
772 # maps perfectly to METH_O, doesn't need a return converter.
773 # so we skip making a parse function
774 # and call directly into the impl function.
775 impl_prototype = parser_prototype = parser_definition = ''
776 impl_definition = meth_o_prototype
777 else:
778 # SLIGHT HACK
779 # use impl_parameters for the parser here!
780 parser_prototype = meth_o_prototype
781 parser_definition = parser_body(parser_prototype)
782
Larry Hastingsbebf7352014-01-17 17:47:17 -0800783 else:
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300784 argname = 'arg'
785 if parameters[0].name == argname:
786 argname += '_'
787 parser_prototype = normalize_snippet("""
788 static PyObject *
789 {c_basename}({self_type}{self_name}, PyObject *%s)
790 """ % argname)
791
792 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300793 if (!PyArg_Parse(%s, "{format_units}:{name}", {parse_arguments}))
Serhiy Storchaka92e8af62015-04-04 00:12:11 +0300794 goto exit;
795 """ % argname, indent=4))
Larry Hastings31826802013-10-19 00:09:25 -0700796
Larry Hastingsbebf7352014-01-17 17:47:17 -0800797 elif has_option_groups:
798 # positional parameters with option groups
799 # (we have to generate lots of PyArg_ParseTuple calls
800 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700801
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800802 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800803 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700804
Larry Hastings7726ac92014-01-31 22:03:12 -0800805 parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')
Larry Hastings31826802013-10-19 00:09:25 -0700806
Larry Hastingsbebf7352014-01-17 17:47:17 -0800807 elif positional and all_boring_objects:
808 # positional-only, but no option groups,
809 # and nothing but normal objects:
810 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700811
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800812 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800813 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700814
Larry Hastings7726ac92014-01-31 22:03:12 -0800815 parser_definition = parser_body(parser_prototype, normalize_snippet("""
816 if (!PyArg_UnpackTuple(args, "{name}",
817 {unpack_min}, {unpack_max},
818 {parse_arguments}))
819 goto exit;
820 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800821
822 elif positional:
823 # positional-only, but no option groups
824 # we only need one call to PyArg_ParseTuple
825
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800826 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800827 parser_prototype = parser_prototype_varargs
Larry Hastingsbebf7352014-01-17 17:47:17 -0800828
Larry Hastings7726ac92014-01-31 22:03:12 -0800829 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300830 if (!PyArg_ParseTuple(args, "{format_units}:{name}",
Larry Hastings7726ac92014-01-31 22:03:12 -0800831 {parse_arguments}))
832 goto exit;
833 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800834
835 else:
836 # positional-or-keyword arguments
837 flags = "METH_VARARGS|METH_KEYWORDS"
838
Larry Hastings7726ac92014-01-31 22:03:12 -0800839 parser_prototype = parser_prototype_keyword
Larry Hastingsbebf7352014-01-17 17:47:17 -0800840
Larry Hastings7726ac92014-01-31 22:03:12 -0800841 body = normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300842 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords,
Larry Hastings7726ac92014-01-31 22:03:12 -0800843 {parse_arguments}))
844 goto exit;
845 """, indent=4)
846 parser_definition = parser_body(parser_prototype, normalize_snippet("""
Serhiy Storchaka247789c2015-04-24 00:40:51 +0300847 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords,
Larry Hastings7726ac92014-01-31 22:03:12 -0800848 {parse_arguments}))
849 goto exit;
850 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800851 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700852
Larry Hastings31826802013-10-19 00:09:25 -0700853
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800854 if new_or_init:
855 methoddef_define = ''
856
857 if f.kind == METHOD_NEW:
Larry Hastings7726ac92014-01-31 22:03:12 -0800858 parser_prototype = parser_prototype_keyword
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800859 else:
860 return_value_declaration = "int return_value = -1;"
Larry Hastings7726ac92014-01-31 22:03:12 -0800861 parser_prototype = normalize_snippet("""
862 static int
863 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
864 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800865
866 fields = list(parser_body_fields)
867 parses_positional = 'METH_NOARGS' not in flags
868 parses_keywords = 'METH_KEYWORDS' in flags
869 if parses_keywords:
870 assert parses_positional
871
872 if not parses_keywords:
Larry Hastings7726ac92014-01-31 22:03:12 -0800873 fields.insert(0, normalize_snippet("""
874 if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs))
875 goto exit;
876 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800877 if not parses_positional:
Larry Hastings7726ac92014-01-31 22:03:12 -0800878 fields.insert(0, normalize_snippet("""
879 if ({self_type_check}!_PyArg_NoPositional("{name}", args))
880 goto exit;
881 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800882
883 parser_definition = parser_body(parser_prototype, *fields)
884 if parses_keywords:
885 parser_definition = insert_keywords(parser_definition)
886
Larry Hastings31826802013-10-19 00:09:25 -0700887
Larry Hastingsbebf7352014-01-17 17:47:17 -0800888 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800889 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700890
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800891 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700892
Larry Hastings7726ac92014-01-31 22:03:12 -0800893 methoddef_ifndef = ''
894 conditional = self.cpp.condition()
895 if not conditional:
896 cpp_if = cpp_endif = ''
897 else:
898 cpp_if = "#if " + conditional
899 cpp_endif = "#endif /* " + conditional + " */"
900
Larry Hastings0759f842015-04-03 13:09:02 -0700901 if methoddef_define and f.name not in clinic.ifndef_symbols:
902 clinic.ifndef_symbols.add(f.name)
Larry Hastings7726ac92014-01-31 22:03:12 -0800903 methoddef_ifndef = normalize_snippet("""
904 #ifndef {methoddef_name}
905 #define {methoddef_name}
906 #endif /* !defined({methoddef_name}) */
907 """)
908
909
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800910 # add ';' to the end of parser_prototype and impl_prototype
911 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800912 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800913 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800914 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800915 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700916
Larry Hastingsbebf7352014-01-17 17:47:17 -0800917 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800918 impl_prototype = impl_definition
919 if impl_prototype:
920 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700921
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800922 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800923
924 d = {
925 "docstring_prototype" : docstring_prototype,
926 "docstring_definition" : docstring_definition,
927 "impl_prototype" : impl_prototype,
928 "methoddef_define" : methoddef_define,
929 "parser_prototype" : parser_prototype,
930 "parser_definition" : parser_definition,
931 "impl_definition" : impl_definition,
Larry Hastings7726ac92014-01-31 22:03:12 -0800932 "cpp_if" : cpp_if,
933 "cpp_endif" : cpp_endif,
934 "methoddef_ifndef" : methoddef_ifndef,
Larry Hastingsbebf7352014-01-17 17:47:17 -0800935 }
936
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800937 # make sure we didn't forget to assign something,
938 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -0800939 d2 = {}
940 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800941 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800942 if value:
943 value = '\n' + value + '\n'
944 d2[name] = value
945 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700946
947 @staticmethod
948 def group_to_variable_name(group):
949 adjective = "left_" if group < 0 else "right_"
950 return "group_" + adjective + str(abs(group))
951
952 def render_option_group_parsing(self, f, template_dict):
953 # positional only, grouped, optional arguments!
954 # can be optional on the left or right.
955 # here's an example:
956 #
957 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
958 #
959 # Here group D are required, and all other groups are optional.
960 # (Group D's "group" is actually None.)
961 # We can figure out which sets of arguments we have based on
962 # how many arguments are in the tuple.
963 #
964 # Note that you need to count up on both sides. For example,
965 # you could have groups C+D, or C+D+E, or C+D+E+F.
966 #
967 # What if the number of arguments leads us to an ambiguous result?
968 # Clinic prefers groups on the left. So in the above example,
969 # five arguments would map to B+C, not C+D.
970
971 add, output = text_accumulator()
972 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800973 if isinstance(parameters[0].converter, self_converter):
974 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -0700975
976 groups = []
977 group = None
978 left = []
979 right = []
980 required = []
981 last = unspecified
982
983 for p in parameters:
984 group_id = p.group
985 if group_id != last:
986 last = group_id
987 group = []
988 if group_id < 0:
989 left.append(group)
990 elif group_id == 0:
991 group = required
992 else:
993 right.append(group)
994 group.append(p)
995
996 count_min = sys.maxsize
997 count_max = -1
998
Larry Hastings2a727912014-01-16 11:32:01 -0800999 add("switch (PyTuple_GET_SIZE(args)) {{\n")
Larry Hastings31826802013-10-19 00:09:25 -07001000 for subset in permute_optional_groups(left, required, right):
1001 count = len(subset)
1002 count_min = min(count_min, count)
1003 count_max = max(count_max, count)
1004
Larry Hastings583baa82014-01-12 08:49:30 -08001005 if count == 0:
1006 add(""" case 0:
1007 break;
1008""")
1009 continue
1010
Larry Hastings31826802013-10-19 00:09:25 -07001011 group_ids = {p.group for p in subset} # eliminate duplicates
1012 d = {}
1013 d['count'] = count
1014 d['name'] = f.name
1015 d['groups'] = sorted(group_ids)
1016 d['format_units'] = "".join(p.converter.format_unit for p in subset)
1017
1018 parse_arguments = []
1019 for p in subset:
1020 p.converter.parse_argument(parse_arguments)
1021 d['parse_arguments'] = ", ".join(parse_arguments)
1022
1023 group_ids.discard(0)
1024 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
1025 lines = "\n".join(lines)
1026
1027 s = """
1028 case {count}:
1029 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
Larry Hastings46258262014-01-22 03:05:49 -08001030 goto exit;
Larry Hastings31826802013-10-19 00:09:25 -07001031 {group_booleans}
1032 break;
1033"""[1:]
1034 s = linear_format(s, group_booleans=lines)
1035 s = s.format_map(d)
1036 add(s)
1037
1038 add(" default:\n")
1039 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
1040 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -08001041 add(' goto exit;\n')
Larry Hastings31826802013-10-19 00:09:25 -07001042 add("}}")
1043 template_dict['option_group_parsing'] = output()
1044
Larry Hastingsbebf7352014-01-17 17:47:17 -08001045 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -07001046 if not f:
1047 return ""
1048
1049 add, output = text_accumulator()
1050 data = CRenderData()
1051
Larry Hastings7726ac92014-01-31 22:03:12 -08001052 assert f.parameters, "We should always have a 'self' at this point!"
1053 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07001054 converters = [p.converter for p in parameters]
1055
Larry Hastings5c661892014-01-24 06:17:25 -08001056 templates = self.output_templates(f)
1057
1058 f_self = parameters[0]
1059 selfless = parameters[1:]
1060 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
1061
1062 last_group = 0
1063 first_optional = len(selfless)
1064 positional = selfless and selfless[-1].kind == inspect.Parameter.POSITIONAL_ONLY
1065 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
1066 default_return_converter = (not f.return_converter or
1067 f.return_converter.type == 'PyObject *')
1068 has_option_groups = False
1069
1070 # offset i by -1 because first_optional needs to ignore self
1071 for i, p in enumerate(parameters, -1):
1072 c = p.converter
1073
1074 if (i != -1) and (p.default is not unspecified):
1075 first_optional = min(first_optional, i)
1076
1077 # insert group variable
1078 group = p.group
1079 if last_group != group:
1080 last_group = group
1081 if group:
1082 group_name = self.group_to_variable_name(group)
1083 data.impl_arguments.append(group_name)
1084 data.declarations.append("int " + group_name + " = 0;")
1085 data.impl_parameters.append("int " + group_name)
1086 has_option_groups = True
1087
1088 c.render(p, data)
1089
1090 if has_option_groups and (not positional):
1091 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
1092
1093 # HACK
1094 # when we're METH_O, but have a custom return converter,
1095 # we use "impl_parameters" for the parsing function
1096 # because that works better. but that means we must
Berker Peksagf23530f2014-10-19 18:04:38 +03001097 # suppress actually declaring the impl's parameters
Larry Hastings5c661892014-01-24 06:17:25 -08001098 # as variables in the parsing function. but since it's
1099 # METH_O, we have exactly one anyway, so we know exactly
1100 # where it is.
1101 if ("METH_O" in templates['methoddef_define'] and
Serhiy Storchaka92e8af62015-04-04 00:12:11 +03001102 '{impl_parameters}' in templates['parser_prototype']):
Larry Hastings5c661892014-01-24 06:17:25 -08001103 data.declarations.pop(0)
1104
Larry Hastings31826802013-10-19 00:09:25 -07001105 template_dict = {}
1106
1107 full_name = f.full_name
1108 template_dict['full_name'] = full_name
1109
Larry Hastings5c661892014-01-24 06:17:25 -08001110 if new_or_init:
1111 name = f.cls.name
1112 else:
1113 name = f.name
1114
Larry Hastings31826802013-10-19 00:09:25 -07001115 template_dict['name'] = name
1116
Larry Hastings8666e652014-01-12 14:12:59 -08001117 if f.c_basename:
1118 c_basename = f.c_basename
1119 else:
1120 fields = full_name.split(".")
1121 if fields[-1] == '__new__':
1122 fields.pop()
1123 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001124
Larry Hastings31826802013-10-19 00:09:25 -07001125 template_dict['c_basename'] = c_basename
1126
1127 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1128 template_dict['methoddef_name'] = methoddef_name
1129
1130 template_dict['docstring'] = self.docstring_for_c_string(f)
1131
Larry Hastingsc2047262014-01-25 20:43:29 -08001132 template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
Larry Hastings5c661892014-01-24 06:17:25 -08001133 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001134
Larry Hastings31826802013-10-19 00:09:25 -07001135 f.return_converter.render(f, data)
1136 template_dict['impl_return_type'] = f.return_converter.type
1137
1138 template_dict['declarations'] = "\n".join(data.declarations)
1139 template_dict['initializers'] = "\n\n".join(data.initializers)
Larry Hastingsc2047262014-01-25 20:43:29 -08001140 template_dict['modifications'] = '\n\n'.join(data.modifications)
Larry Hastings31826802013-10-19 00:09:25 -07001141 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1142 template_dict['format_units'] = ''.join(data.format_units)
1143 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1144 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1145 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
1146 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
1147 template_dict['cleanup'] = "".join(data.cleanup)
1148 template_dict['return_value'] = data.return_value
1149
Larry Hastings5c661892014-01-24 06:17:25 -08001150 # used by unpack tuple code generator
1151 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1152 unpack_min = first_optional
1153 unpack_max = len(selfless)
1154 template_dict['unpack_min'] = str(unpack_min)
1155 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001156
Larry Hastingsbebf7352014-01-17 17:47:17 -08001157 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001158 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001159
Larry Hastings0759f842015-04-03 13:09:02 -07001160 # buffers, not destination
1161 for name, destination in clinic.destination_buffers.items():
Larry Hastingsbebf7352014-01-17 17:47:17 -08001162 template = templates[name]
1163 if has_option_groups:
1164 template = linear_format(template,
1165 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001166 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001167 declarations=template_dict['declarations'],
1168 return_conversion=template_dict['return_conversion'],
1169 initializers=template_dict['initializers'],
Larry Hastingsc2047262014-01-25 20:43:29 -08001170 modifications=template_dict['modifications'],
Larry Hastingsbebf7352014-01-17 17:47:17 -08001171 cleanup=template_dict['cleanup'],
1172 )
Larry Hastings31826802013-10-19 00:09:25 -07001173
Larry Hastingsbebf7352014-01-17 17:47:17 -08001174 # Only generate the "exit:" label
1175 # if we have any gotos
1176 need_exit_label = "goto exit;" in template
1177 template = linear_format(template,
1178 exit_label="exit:" if need_exit_label else ''
1179 )
Larry Hastings31826802013-10-19 00:09:25 -07001180
Larry Hastingsbebf7352014-01-17 17:47:17 -08001181 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001182
Larry Hastings89964c42015-04-14 18:07:59 -04001183 # mild hack:
1184 # reflow long impl declarations
1185 if name in {"impl_prototype", "impl_definition"}:
1186 s = wrap_declarations(s)
1187
Larry Hastingsbebf7352014-01-17 17:47:17 -08001188 if clinic.line_prefix:
1189 s = indent_all_lines(s, clinic.line_prefix)
1190 if clinic.line_suffix:
1191 s = suffix_all_lines(s, clinic.line_suffix)
1192
1193 destination.append(s)
1194
1195 return clinic.get_destination('block').dump()
1196
Larry Hastings31826802013-10-19 00:09:25 -07001197
1198
Larry Hastings5c661892014-01-24 06:17:25 -08001199
Larry Hastings31826802013-10-19 00:09:25 -07001200@contextlib.contextmanager
1201def OverrideStdioWith(stdout):
1202 saved_stdout = sys.stdout
1203 sys.stdout = stdout
1204 try:
1205 yield
1206 finally:
1207 assert sys.stdout is stdout
1208 sys.stdout = saved_stdout
1209
1210
Larry Hastings2623c8c2014-02-08 22:15:29 -08001211def create_regex(before, after, word=True, whole_line=True):
Larry Hastings31826802013-10-19 00:09:25 -07001212 """Create an re object for matching marker lines."""
Larry Hastings581ee362014-01-28 05:00:08 -08001213 group_re = "\w+" if word else ".+"
Larry Hastings2623c8c2014-02-08 22:15:29 -08001214 pattern = r'{}({}){}'
1215 if whole_line:
1216 pattern = '^' + pattern + '$'
Larry Hastings581ee362014-01-28 05:00:08 -08001217 pattern = pattern.format(re.escape(before), group_re, re.escape(after))
1218 return re.compile(pattern)
Larry Hastings31826802013-10-19 00:09:25 -07001219
1220
1221class Block:
1222 r"""
1223 Represents a single block of text embedded in
1224 another file. If dsl_name is None, the block represents
1225 verbatim text, raw original text from the file, in
1226 which case "input" will be the only non-false member.
1227 If dsl_name is not None, the block represents a Clinic
1228 block.
1229
1230 input is always str, with embedded \n characters.
1231 input represents the original text from the file;
1232 if it's a Clinic block, it is the original text with
1233 the body_prefix and redundant leading whitespace removed.
1234
1235 dsl_name is either str or None. If str, it's the text
1236 found on the start line of the block between the square
1237 brackets.
1238
1239 signatures is either list or None. If it's a list,
1240 it may only contain clinic.Module, clinic.Class, and
1241 clinic.Function objects. At the moment it should
1242 contain at most one of each.
1243
1244 output is either str or None. If str, it's the output
1245 from this block, with embedded '\n' characters.
1246
1247 indent is either str or None. It's the leading whitespace
1248 that was found on every line of input. (If body_prefix is
1249 not empty, this is the indent *after* removing the
1250 body_prefix.)
1251
1252 preindent is either str or None. It's the whitespace that
1253 was found in front of every line of input *before* the
1254 "body_prefix" (see the Language object). If body_prefix
1255 is empty, preindent must always be empty too.
1256
1257 To illustrate indent and preindent: Assume that '_'
1258 represents whitespace. If the block processed was in a
1259 Python file, and looked like this:
1260 ____#/*[python]
1261 ____#__for a in range(20):
1262 ____#____print(a)
1263 ____#[python]*/
1264 "preindent" would be "____" and "indent" would be "__".
1265
1266 """
1267 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1268 assert isinstance(input, str)
1269 self.input = input
1270 self.dsl_name = dsl_name
1271 self.signatures = signatures or []
1272 self.output = output
1273 self.indent = indent
1274 self.preindent = preindent
1275
Larry Hastings581ee362014-01-28 05:00:08 -08001276 def __repr__(self):
1277 dsl_name = self.dsl_name or "text"
1278 def summarize(s):
1279 s = repr(s)
1280 if len(s) > 30:
1281 return s[:26] + "..." + s[0]
1282 return s
1283 return "".join((
1284 "<Block ", dsl_name, " input=", summarize(self.input), " output=", summarize(self.output), ">"))
1285
Larry Hastings31826802013-10-19 00:09:25 -07001286
1287class BlockParser:
1288 """
1289 Block-oriented parser for Argument Clinic.
1290 Iterator, yields Block objects.
1291 """
1292
1293 def __init__(self, input, language, *, verify=True):
1294 """
1295 "input" should be a str object
1296 with embedded \n characters.
1297
1298 "language" should be a Language object.
1299 """
1300 language.validate()
1301
1302 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1303 self.block_start_line_number = self.line_number = 0
1304
1305 self.language = language
1306 before, _, after = language.start_line.partition('{dsl_name}')
1307 assert _ == '{dsl_name}'
Larry Hastings2623c8c2014-02-08 22:15:29 -08001308 self.find_start_re = create_regex(before, after, whole_line=False)
Larry Hastings31826802013-10-19 00:09:25 -07001309 self.start_re = create_regex(before, after)
1310 self.verify = verify
1311 self.last_checksum_re = None
1312 self.last_dsl_name = None
1313 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001314 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001315
1316 def __iter__(self):
1317 return self
1318
1319 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001320 while True:
1321 if not self.input:
1322 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001323
Larry Hastingsbebf7352014-01-17 17:47:17 -08001324 if self.dsl_name:
1325 return_value = self.parse_clinic_block(self.dsl_name)
1326 self.dsl_name = None
1327 self.first_block = False
1328 return return_value
1329 block = self.parse_verbatim_block()
1330 if self.first_block and not block.input:
1331 continue
1332 self.first_block = False
1333 return block
1334
Larry Hastings31826802013-10-19 00:09:25 -07001335
1336 def is_start_line(self, line):
1337 match = self.start_re.match(line.lstrip())
1338 return match.group(1) if match else None
1339
Larry Hastingse1b82532014-07-27 16:22:20 +02001340 def _line(self, lookahead=False):
Larry Hastings31826802013-10-19 00:09:25 -07001341 self.line_number += 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001342 line = self.input.pop()
Larry Hastingse1b82532014-07-27 16:22:20 +02001343 if not lookahead:
1344 self.language.parse_line(line)
Larry Hastings7726ac92014-01-31 22:03:12 -08001345 return line
Larry Hastings31826802013-10-19 00:09:25 -07001346
1347 def parse_verbatim_block(self):
1348 add, output = text_accumulator()
1349 self.block_start_line_number = self.line_number
1350
1351 while self.input:
1352 line = self._line()
1353 dsl_name = self.is_start_line(line)
1354 if dsl_name:
1355 self.dsl_name = dsl_name
1356 break
1357 add(line)
1358
1359 return Block(output())
1360
1361 def parse_clinic_block(self, dsl_name):
1362 input_add, input_output = text_accumulator()
1363 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001364 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001365 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1366
Larry Hastings90261132014-01-07 12:21:08 -08001367 def is_stop_line(line):
1368 # make sure to recognize stop line even if it
1369 # doesn't end with EOL (it could be the very end of the file)
1370 if not line.startswith(stop_line):
1371 return False
1372 remainder = line[len(stop_line):]
1373 return (not remainder) or remainder.isspace()
1374
Larry Hastings31826802013-10-19 00:09:25 -07001375 # consume body of program
1376 while self.input:
1377 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001378 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001379 break
1380 if body_prefix:
1381 line = line.lstrip()
1382 assert line.startswith(body_prefix)
1383 line = line[len(body_prefix):]
1384 input_add(line)
1385
1386 # consume output and checksum line, if present.
1387 if self.last_dsl_name == dsl_name:
1388 checksum_re = self.last_checksum_re
1389 else:
Larry Hastings581ee362014-01-28 05:00:08 -08001390 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, arguments='{arguments}').partition('{arguments}')
1391 assert _ == '{arguments}'
1392 checksum_re = create_regex(before, after, word=False)
Larry Hastings31826802013-10-19 00:09:25 -07001393 self.last_dsl_name = dsl_name
1394 self.last_checksum_re = checksum_re
1395
1396 # scan forward for checksum line
1397 output_add, output_output = text_accumulator()
Larry Hastings581ee362014-01-28 05:00:08 -08001398 arguments = None
Larry Hastings31826802013-10-19 00:09:25 -07001399 while self.input:
Larry Hastingse1b82532014-07-27 16:22:20 +02001400 line = self._line(lookahead=True)
Larry Hastings31826802013-10-19 00:09:25 -07001401 match = checksum_re.match(line.lstrip())
Larry Hastings581ee362014-01-28 05:00:08 -08001402 arguments = match.group(1) if match else None
1403 if arguments:
Larry Hastings31826802013-10-19 00:09:25 -07001404 break
1405 output_add(line)
1406 if self.is_start_line(line):
1407 break
1408
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001409 output = output_output()
Larry Hastings581ee362014-01-28 05:00:08 -08001410 if arguments:
1411 d = {}
1412 for field in shlex.split(arguments):
1413 name, equals, value = field.partition('=')
1414 if not equals:
1415 fail("Mangled Argument Clinic marker line: {!r}".format(line))
1416 d[name.strip()] = value.strip()
1417
Larry Hastings31826802013-10-19 00:09:25 -07001418 if self.verify:
Larry Hastings581ee362014-01-28 05:00:08 -08001419 if 'input' in d:
1420 checksum = d['output']
1421 input_checksum = d['input']
1422 else:
1423 checksum = d['checksum']
1424 input_checksum = None
1425
1426 computed = compute_checksum(output, len(checksum))
Larry Hastings31826802013-10-19 00:09:25 -07001427 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001428 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1429 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001430 "the end marker,\n"
1431 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001432 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001433 else:
1434 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001435 output_lines = output.splitlines(keepends=True)
1436 self.line_number -= len(output_lines)
1437 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001438 output = None
1439
1440 return Block(input_output(), dsl_name, output=output)
1441
1442
1443class BlockPrinter:
1444
1445 def __init__(self, language, f=None):
1446 self.language = language
1447 self.f = f or io.StringIO()
1448
1449 def print_block(self, block):
1450 input = block.input
1451 output = block.output
1452 dsl_name = block.dsl_name
1453 write = self.f.write
1454
Larry Hastings31826802013-10-19 00:09:25 -07001455 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1456
1457 if not dsl_name:
1458 write(input)
1459 return
1460
1461 write(self.language.start_line.format(dsl_name=dsl_name))
1462 write("\n")
1463
1464 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1465 if not body_prefix:
1466 write(input)
1467 else:
1468 for line in input.split('\n'):
1469 write(body_prefix)
1470 write(line)
1471 write("\n")
1472
1473 write(self.language.stop_line.format(dsl_name=dsl_name))
1474 write("\n")
1475
Larry Hastings581ee362014-01-28 05:00:08 -08001476 input = ''.join(block.input)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001477 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001478 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001479 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001480 output += '\n'
1481 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001482
Larry Hastings581ee362014-01-28 05:00:08 -08001483 arguments="output={} input={}".format(compute_checksum(output, 16), compute_checksum(input, 16))
1484 write(self.language.checksum_line.format(dsl_name=dsl_name, arguments=arguments))
Larry Hastings31826802013-10-19 00:09:25 -07001485 write("\n")
1486
Larry Hastingsbebf7352014-01-17 17:47:17 -08001487 def write(self, text):
1488 self.f.write(text)
1489
1490
Larry Hastings0759f842015-04-03 13:09:02 -07001491class BufferSeries:
1492 """
1493 Behaves like a "defaultlist".
1494 When you ask for an index that doesn't exist yet,
1495 the object grows the list until that item exists.
1496 So o[n] will always work.
1497
1498 Supports negative indices for actual items.
1499 e.g. o[-1] is an element immediately preceding o[0].
1500 """
1501
1502 def __init__(self):
1503 self._start = 0
1504 self._array = []
1505 self._constructor = _text_accumulator
1506
1507 def __getitem__(self, i):
1508 i -= self._start
1509 if i < 0:
1510 self._start += i
1511 prefix = [self._constructor() for x in range(-i)]
1512 self._array = prefix + self._array
1513 i = 0
1514 while i >= len(self._array):
1515 self._array.append(self._constructor())
1516 return self._array[i]
1517
1518 def clear(self):
1519 for ta in self._array:
1520 ta._text.clear()
1521
1522 def dump(self):
1523 texts = [ta.output() for ta in self._array]
1524 return "".join(texts)
1525
1526
Larry Hastingsbebf7352014-01-17 17:47:17 -08001527class Destination:
1528 def __init__(self, name, type, clinic, *args):
1529 self.name = name
1530 self.type = type
1531 self.clinic = clinic
Larry Hastings0759f842015-04-03 13:09:02 -07001532 valid_types = ('buffer', 'file', 'suppress')
Larry Hastingsbebf7352014-01-17 17:47:17 -08001533 if type not in valid_types:
1534 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1535 extra_arguments = 1 if type == "file" else 0
1536 if len(args) < extra_arguments:
1537 fail("Not enough arguments for destination " + name + " new " + type)
1538 if len(args) > extra_arguments:
1539 fail("Too many arguments for destination " + name + " new " + type)
1540 if type =='file':
1541 d = {}
Larry Hastingsc2047262014-01-25 20:43:29 -08001542 filename = clinic.filename
1543 d['path'] = filename
1544 dirname, basename = os.path.split(filename)
1545 if not dirname:
1546 dirname = '.'
1547 d['dirname'] = dirname
1548 d['basename'] = basename
1549 d['basename_root'], d['basename_extension'] = os.path.splitext(filename)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001550 self.filename = args[0].format_map(d)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001551
Larry Hastings0759f842015-04-03 13:09:02 -07001552 self.buffers = BufferSeries()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001553
1554 def __repr__(self):
1555 if self.type == 'file':
1556 file_repr = " " + repr(self.filename)
1557 else:
1558 file_repr = ''
1559 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1560
1561 def clear(self):
1562 if self.type != 'buffer':
1563 fail("Can't clear destination" + self.name + " , it's not of type buffer")
Larry Hastings0759f842015-04-03 13:09:02 -07001564 self.buffers.clear()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001565
1566 def dump(self):
Larry Hastings0759f842015-04-03 13:09:02 -07001567 return self.buffers.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001568
Larry Hastings31826802013-10-19 00:09:25 -07001569
1570# maps strings to Language objects.
1571# "languages" maps the name of the language ("C", "Python").
1572# "extensions" maps the file extension ("c", "py").
1573languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001574extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1575extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001576
1577
1578# maps strings to callables.
1579# these callables must be of the form:
1580# def foo(name, default, *, ...)
1581# The callable may have any number of keyword-only parameters.
1582# The callable must return a CConverter object.
1583# The callable should not call builtins.print.
1584converters = {}
1585
1586# maps strings to callables.
1587# these callables follow the same rules as those for "converters" above.
1588# note however that they will never be called with keyword-only parameters.
1589legacy_converters = {}
1590
1591
1592# maps strings to callables.
1593# these callables must be of the form:
1594# def foo(*, ...)
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.
1598return_converters = {}
1599
Larry Hastings7726ac92014-01-31 22:03:12 -08001600clinic = None
Larry Hastings31826802013-10-19 00:09:25 -07001601class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001602
1603 presets_text = """
Larry Hastings7726ac92014-01-31 22:03:12 -08001604preset block
1605everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001606methoddef_ifndef buffer 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001607docstring_prototype suppress
1608parser_prototype suppress
1609cpp_if suppress
1610cpp_endif suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001611
Larry Hastingsbebf7352014-01-17 17:47:17 -08001612preset original
1613everything block
Larry Hastings0759f842015-04-03 13:09:02 -07001614methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001615docstring_prototype suppress
1616parser_prototype suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001617cpp_if suppress
1618cpp_endif suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001619
1620preset file
1621everything file
Larry Hastings0759f842015-04-03 13:09:02 -07001622methoddef_ifndef file 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001623docstring_prototype suppress
1624parser_prototype suppress
1625impl_definition block
1626
1627preset buffer
1628everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001629methoddef_ifndef buffer 1
1630impl_definition block
Larry Hastingsbebf7352014-01-17 17:47:17 -08001631docstring_prototype suppress
1632impl_prototype suppress
1633parser_prototype suppress
Larry Hastingsbebf7352014-01-17 17:47:17 -08001634
1635preset partial-buffer
1636everything buffer
Larry Hastings0759f842015-04-03 13:09:02 -07001637methoddef_ifndef buffer 1
Larry Hastingsbebf7352014-01-17 17:47:17 -08001638docstring_prototype block
1639impl_prototype suppress
1640methoddef_define block
1641parser_prototype block
1642impl_definition block
1643
Larry Hastingsbebf7352014-01-17 17:47:17 -08001644"""
1645
Larry Hastings581ee362014-01-28 05:00:08 -08001646 def __init__(self, language, printer=None, *, force=False, verify=True, filename=None):
Larry Hastings31826802013-10-19 00:09:25 -07001647 # maps strings to Parser objects.
1648 # (instantiated from the "parsers" global.)
1649 self.parsers = {}
1650 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001651 if printer:
1652 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001653 self.printer = printer or BlockPrinter(language)
1654 self.verify = verify
Larry Hastings581ee362014-01-28 05:00:08 -08001655 self.force = force
Larry Hastings31826802013-10-19 00:09:25 -07001656 self.filename = filename
1657 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001658 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001659 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001660
Larry Hastingsbebf7352014-01-17 17:47:17 -08001661 self.line_prefix = self.line_suffix = ''
1662
1663 self.destinations = {}
1664 self.add_destination("block", "buffer")
1665 self.add_destination("suppress", "suppress")
1666 self.add_destination("buffer", "buffer")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001667 if filename:
Larry Hastingsc2047262014-01-25 20:43:29 -08001668 self.add_destination("file", "file", "{dirname}/clinic/{basename}.h")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001669
Larry Hastings0759f842015-04-03 13:09:02 -07001670 d = self.get_destination_buffer
1671 self.destination_buffers = collections.OrderedDict((
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001672 ('cpp_if', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001673 ('docstring_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001674 ('docstring_definition', d('file')),
1675 ('methoddef_define', d('file')),
1676 ('impl_prototype', d('file')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001677 ('parser_prototype', d('suppress')),
Serhiy Storchaka1009bf12015-04-03 23:53:51 +03001678 ('parser_definition', d('file')),
1679 ('cpp_endif', d('file')),
1680 ('methoddef_ifndef', d('file', 1)),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001681 ('impl_definition', d('block')),
1682 ))
1683
Larry Hastings0759f842015-04-03 13:09:02 -07001684 self.destination_buffers_stack = []
1685 self.ifndef_symbols = set()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001686
1687 self.presets = {}
1688 preset = None
1689 for line in self.presets_text.strip().split('\n'):
1690 line = line.strip()
1691 if not line:
1692 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001693 name, value, *options = line.split()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001694 if name == 'preset':
1695 self.presets[value] = preset = collections.OrderedDict()
1696 continue
1697
Larry Hastings0759f842015-04-03 13:09:02 -07001698 if len(options):
1699 index = int(options[0])
1700 else:
1701 index = 0
1702 buffer = self.get_destination_buffer(value, index)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001703
1704 if name == 'everything':
Larry Hastings0759f842015-04-03 13:09:02 -07001705 for name in self.destination_buffers:
1706 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001707 continue
1708
Larry Hastings0759f842015-04-03 13:09:02 -07001709 assert name in self.destination_buffers
1710 preset[name] = buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001711
Larry Hastings31826802013-10-19 00:09:25 -07001712 global clinic
1713 clinic = self
1714
Larry Hastingsbebf7352014-01-17 17:47:17 -08001715 def add_destination(self, name, type, *args):
1716 if name in self.destinations:
1717 fail("Destination already exists: " + repr(name))
1718 self.destinations[name] = Destination(name, type, self, *args)
1719
Larry Hastings0759f842015-04-03 13:09:02 -07001720 def get_destination(self, name):
1721 d = self.destinations.get(name)
1722 if not d:
1723 fail("Destination does not exist: " + repr(name))
1724 return d
1725
1726 def get_destination_buffer(self, name, item=0):
1727 d = self.get_destination(name)
1728 return d.buffers[item]
1729
Larry Hastings31826802013-10-19 00:09:25 -07001730 def parse(self, input):
1731 printer = self.printer
1732 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1733 for block in self.block_parser:
1734 dsl_name = block.dsl_name
1735 if dsl_name:
1736 if dsl_name not in self.parsers:
1737 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1738 self.parsers[dsl_name] = parsers[dsl_name](self)
1739 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001740 try:
1741 parser.parse(block)
1742 except Exception:
1743 fail('Exception raised during parsing:\n' +
1744 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001745 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001746
1747 second_pass_replacements = {}
1748
Larry Hastings0759f842015-04-03 13:09:02 -07001749 # these are destinations not buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08001750 for name, destination in self.destinations.items():
1751 if destination.type == 'suppress':
1752 continue
Larry Hastings0759f842015-04-03 13:09:02 -07001753 output = destination.dump()
Larry Hastingsbebf7352014-01-17 17:47:17 -08001754
1755 if output:
1756
1757 block = Block("", dsl_name="clinic", output=output)
1758
1759 if destination.type == 'buffer':
1760 block.input = "dump " + name + "\n"
1761 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1762 printer.write("\n")
1763 printer.print_block(block)
1764 continue
1765
1766 if destination.type == 'file':
1767 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08001768 dirname = os.path.dirname(destination.filename)
1769 try:
1770 os.makedirs(dirname)
1771 except FileExistsError:
1772 if not os.path.isdir(dirname):
1773 fail("Can't write to destination {}, "
1774 "can't make directory {}!".format(
1775 destination.filename, dirname))
Larry Hastings581ee362014-01-28 05:00:08 -08001776 if self.verify:
1777 with open(destination.filename, "rt") as f:
1778 parser_2 = BlockParser(f.read(), language=self.language)
1779 blocks = list(parser_2)
1780 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1781 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001782 except FileNotFoundError:
1783 pass
1784
1785 block.input = 'preserve\n'
1786 printer_2 = BlockPrinter(self.language)
1787 printer_2.print_block(block)
1788 with open(destination.filename, "wt") as f:
1789 f.write(printer_2.f.getvalue())
1790 continue
1791 text = printer.f.getvalue()
1792
1793 if second_pass_replacements:
1794 printer_2 = BlockPrinter(self.language)
1795 parser_2 = BlockParser(text, self.language)
1796 changed = False
1797 for block in parser_2:
1798 if block.dsl_name:
1799 for id, replacement in second_pass_replacements.items():
1800 if id in block.output:
1801 changed = True
1802 block.output = block.output.replace(id, replacement)
1803 printer_2.print_block(block)
1804 if changed:
1805 text = printer_2.f.getvalue()
1806
1807 return text
1808
Larry Hastings31826802013-10-19 00:09:25 -07001809
1810 def _module_and_class(self, fields):
1811 """
1812 fields should be an iterable of field names.
1813 returns a tuple of (module, class).
1814 the module object could actually be self (a clinic object).
1815 this function is only ever used to find the parent of where
1816 a new class/module should go.
1817 """
1818 in_classes = False
1819 parent = module = self
1820 cls = None
1821 so_far = []
1822
1823 for field in fields:
1824 so_far.append(field)
1825 if not in_classes:
1826 child = parent.modules.get(field)
1827 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001828 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001829 continue
1830 in_classes = True
1831 if not hasattr(parent, 'classes'):
1832 return module, cls
1833 child = parent.classes.get(field)
1834 if not child:
1835 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1836 cls = parent = child
1837
1838 return module, cls
1839
1840
Larry Hastings581ee362014-01-28 05:00:08 -08001841def parse_file(filename, *, force=False, verify=True, output=None, encoding='utf-8'):
Larry Hastings31826802013-10-19 00:09:25 -07001842 extension = os.path.splitext(filename)[1][1:]
1843 if not extension:
1844 fail("Can't extract file type for file " + repr(filename))
1845
1846 try:
Larry Hastings7726ac92014-01-31 22:03:12 -08001847 language = extensions[extension](filename)
Larry Hastings31826802013-10-19 00:09:25 -07001848 except KeyError:
1849 fail("Can't identify file type for file " + repr(filename))
1850
Larry Hastings31826802013-10-19 00:09:25 -07001851 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001852 raw = f.read()
1853
Larry Hastings2623c8c2014-02-08 22:15:29 -08001854 # exit quickly if there are no clinic markers in the file
1855 find_start_re = BlockParser("", language).find_start_re
1856 if not find_start_re.search(raw):
1857 return
1858
1859 clinic = Clinic(language, force=force, verify=verify, filename=filename)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001860 cooked = clinic.parse(raw)
Larry Hastings581ee362014-01-28 05:00:08 -08001861 if (cooked == raw) and not force:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001862 return
Larry Hastings31826802013-10-19 00:09:25 -07001863
1864 directory = os.path.dirname(filename) or '.'
1865
1866 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001867 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001868 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1869 with open(tmpfilename, "wb") as f:
1870 f.write(bytes)
1871 os.replace(tmpfilename, output or filename)
1872
1873
Larry Hastings581ee362014-01-28 05:00:08 -08001874def compute_checksum(input, length=None):
Larry Hastings31826802013-10-19 00:09:25 -07001875 input = input or ''
Larry Hastings581ee362014-01-28 05:00:08 -08001876 s = hashlib.sha1(input.encode('utf-8')).hexdigest()
1877 if length:
1878 s = s[:length]
1879 return s
Larry Hastings31826802013-10-19 00:09:25 -07001880
1881
1882
1883
1884class PythonParser:
1885 def __init__(self, clinic):
1886 pass
1887
1888 def parse(self, block):
1889 s = io.StringIO()
1890 with OverrideStdioWith(s):
1891 exec(block.input)
1892 block.output = s.getvalue()
1893
1894
1895class Module:
1896 def __init__(self, name, module=None):
1897 self.name = name
1898 self.module = self.parent = module
1899
1900 self.modules = collections.OrderedDict()
1901 self.classes = collections.OrderedDict()
1902 self.functions = []
1903
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001904 def __repr__(self):
1905 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1906
Larry Hastings31826802013-10-19 00:09:25 -07001907class Class:
Larry Hastingsc2047262014-01-25 20:43:29 -08001908 def __init__(self, name, module=None, cls=None, typedef=None, type_object=None):
Larry Hastings31826802013-10-19 00:09:25 -07001909 self.name = name
1910 self.module = module
1911 self.cls = cls
Larry Hastingsc2047262014-01-25 20:43:29 -08001912 self.typedef = typedef
1913 self.type_object = type_object
Larry Hastings31826802013-10-19 00:09:25 -07001914 self.parent = cls or module
1915
1916 self.classes = collections.OrderedDict()
1917 self.functions = []
1918
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001919 def __repr__(self):
1920 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1921
Larry Hastings8666e652014-01-12 14:12:59 -08001922unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001923
Larry Hastings8666e652014-01-12 14:12:59 -08001924__abs__
1925__add__
1926__and__
1927__bytes__
1928__call__
1929__complex__
1930__delitem__
1931__divmod__
1932__eq__
1933__float__
1934__floordiv__
1935__ge__
1936__getattr__
1937__getattribute__
1938__getitem__
1939__gt__
1940__hash__
1941__iadd__
1942__iand__
Larry Hastings8666e652014-01-12 14:12:59 -08001943__ifloordiv__
1944__ilshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001945__imatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001946__imod__
1947__imul__
1948__index__
1949__int__
1950__invert__
1951__ior__
1952__ipow__
1953__irshift__
1954__isub__
1955__iter__
1956__itruediv__
1957__ixor__
1958__le__
1959__len__
1960__lshift__
1961__lt__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001962__matmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001963__mod__
1964__mul__
1965__neg__
1966__new__
1967__next__
1968__or__
1969__pos__
1970__pow__
1971__radd__
1972__rand__
1973__rdivmod__
1974__repr__
1975__rfloordiv__
1976__rlshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001977__rmatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001978__rmod__
1979__rmul__
1980__ror__
1981__round__
1982__rpow__
1983__rrshift__
1984__rshift__
1985__rsub__
1986__rtruediv__
1987__rxor__
1988__setattr__
1989__setitem__
1990__str__
1991__sub__
1992__truediv__
1993__xor__
1994
1995""".strip().split())
1996
1997
Larry Hastings5c661892014-01-24 06:17:25 -08001998INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
1999INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
2000""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07002001
2002class Function:
2003 """
2004 Mutable duck type for inspect.Function.
2005
2006 docstring - a str containing
2007 * embedded line breaks
2008 * text outdented to the left margin
2009 * no trailing whitespace.
2010 It will always be true that
2011 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
2012 """
2013
2014 def __init__(self, parameters=None, *, name,
2015 module, cls=None, c_basename=None,
2016 full_name=None,
2017 return_converter, return_annotation=_empty,
Larry Hastings581ee362014-01-28 05:00:08 -08002018 docstring=None, kind=CALLABLE, coexist=False,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002019 docstring_only=False):
Larry Hastings31826802013-10-19 00:09:25 -07002020 self.parameters = parameters or collections.OrderedDict()
2021 self.return_annotation = return_annotation
2022 self.name = name
2023 self.full_name = full_name
2024 self.module = module
2025 self.cls = cls
2026 self.parent = cls or module
2027 self.c_basename = c_basename
2028 self.return_converter = return_converter
2029 self.docstring = docstring or ''
2030 self.kind = kind
2031 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08002032 self.self_converter = None
Larry Hastings2623c8c2014-02-08 22:15:29 -08002033 # docstring_only means "don't generate a machine-readable
2034 # signature, just a normal docstring". it's True for
2035 # functions with optional groups because we can't represent
2036 # those accurately with inspect.Signature in 3.4.
2037 self.docstring_only = docstring_only
Larry Hastingsebdcb502013-11-23 14:54:00 -08002038
Larry Hastings7726ac92014-01-31 22:03:12 -08002039 self.rendered_parameters = None
2040
2041 __render_parameters__ = None
2042 @property
2043 def render_parameters(self):
2044 if not self.__render_parameters__:
2045 self.__render_parameters__ = l = []
2046 for p in self.parameters.values():
2047 p = p.copy()
2048 p.converter.pre_render()
2049 l.append(p)
2050 return self.__render_parameters__
2051
Larry Hastingsebdcb502013-11-23 14:54:00 -08002052 @property
2053 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08002054 if self.kind in (METHOD_INIT, METHOD_NEW):
2055 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002056 flags = []
2057 if self.kind == CLASS_METHOD:
2058 flags.append('METH_CLASS')
2059 elif self.kind == STATIC_METHOD:
2060 flags.append('METH_STATIC')
2061 else:
2062 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
2063 if self.coexist:
2064 flags.append('METH_COEXIST')
2065 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07002066
2067 def __repr__(self):
2068 return '<clinic.Function ' + self.name + '>'
2069
Larry Hastings7726ac92014-01-31 22:03:12 -08002070 def copy(self, **overrides):
2071 kwargs = {
2072 'name': self.name, 'module': self.module, 'parameters': self.parameters,
2073 'cls': self.cls, 'c_basename': self.c_basename,
2074 'full_name': self.full_name,
2075 'return_converter': self.return_converter, 'return_annotation': self.return_annotation,
2076 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist,
Larry Hastings2623c8c2014-02-08 22:15:29 -08002077 'docstring_only': self.docstring_only,
Larry Hastings7726ac92014-01-31 22:03:12 -08002078 }
2079 kwargs.update(overrides)
2080 f = Function(**kwargs)
2081
2082 parameters = collections.OrderedDict()
2083 for name, value in f.parameters.items():
2084 value = value.copy(function=f)
2085 parameters[name] = value
2086 f.parameters = parameters
2087 return f
2088
Larry Hastings31826802013-10-19 00:09:25 -07002089
2090class Parameter:
2091 """
2092 Mutable duck type of inspect.Parameter.
2093 """
2094
2095 def __init__(self, name, kind, *, default=_empty,
2096 function, converter, annotation=_empty,
2097 docstring=None, group=0):
2098 self.name = name
2099 self.kind = kind
2100 self.default = default
2101 self.function = function
2102 self.converter = converter
2103 self.annotation = annotation
2104 self.docstring = docstring or ''
2105 self.group = group
2106
2107 def __repr__(self):
2108 return '<clinic.Parameter ' + self.name + '>'
2109
2110 def is_keyword_only(self):
2111 return self.kind == inspect.Parameter.KEYWORD_ONLY
2112
Larry Hastings2623c8c2014-02-08 22:15:29 -08002113 def is_positional_only(self):
2114 return self.kind == inspect.Parameter.POSITIONAL_ONLY
2115
Larry Hastings7726ac92014-01-31 22:03:12 -08002116 def copy(self, **overrides):
2117 kwargs = {
2118 'name': self.name, 'kind': self.kind, 'default':self.default,
2119 'function': self.function, 'converter': self.converter, 'annotation': self.annotation,
2120 'docstring': self.docstring, 'group': self.group,
2121 }
2122 kwargs.update(overrides)
2123 if 'converter' not in overrides:
2124 converter = copy.copy(self.converter)
2125 converter.function = kwargs['function']
2126 kwargs['converter'] = converter
2127 return Parameter(**kwargs)
2128
2129
2130
2131class LandMine:
2132 # try to access any
2133 def __init__(self, message):
2134 self.__message__ = message
2135
2136 def __repr__(self):
2137 return '<LandMine ' + repr(self.__message__) + ">"
2138
2139 def __getattribute__(self, name):
2140 if name in ('__repr__', '__message__'):
2141 return super().__getattribute__(name)
2142 # raise RuntimeError(repr(name))
2143 fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__)
Larry Hastings31826802013-10-19 00:09:25 -07002144
Larry Hastings31826802013-10-19 00:09:25 -07002145
2146def add_c_converter(f, name=None):
2147 if not name:
2148 name = f.__name__
2149 if not name.endswith('_converter'):
2150 return f
2151 name = name[:-len('_converter')]
2152 converters[name] = f
2153 return f
2154
2155def add_default_legacy_c_converter(cls):
2156 # automatically add converter for default format unit
2157 # (but without stomping on the existing one if it's already
2158 # set, in case you subclass)
Larry Hastingsf1503782014-06-11 04:31:29 -07002159 if ((cls.format_unit not in ('O&', '')) and
Larry Hastings31826802013-10-19 00:09:25 -07002160 (cls.format_unit not in legacy_converters)):
2161 legacy_converters[cls.format_unit] = cls
2162 return cls
2163
2164def add_legacy_c_converter(format_unit, **kwargs):
2165 """
2166 Adds a legacy converter.
2167 """
2168 def closure(f):
2169 if not kwargs:
2170 added_f = f
2171 else:
2172 added_f = functools.partial(f, **kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002173 if format_unit:
2174 legacy_converters[format_unit] = added_f
Larry Hastings31826802013-10-19 00:09:25 -07002175 return f
2176 return closure
2177
2178class CConverterAutoRegister(type):
2179 def __init__(cls, name, bases, classdict):
2180 add_c_converter(cls)
2181 add_default_legacy_c_converter(cls)
2182
2183class CConverter(metaclass=CConverterAutoRegister):
2184 """
2185 For the init function, self, name, function, and default
2186 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08002187 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07002188 """
2189
Larry Hastings7726ac92014-01-31 22:03:12 -08002190 # The C name to use for this variable.
2191 name = None
2192
2193 # The Python name to use for this variable.
2194 py_name = None
2195
Larry Hastings78cf85c2014-01-04 12:44:57 -08002196 # The C type to use for this variable.
2197 # 'type' should be a Python string specifying the type, e.g. "int".
2198 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002199 type = None
Larry Hastings31826802013-10-19 00:09:25 -07002200
2201 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08002202 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08002203 # Or the magic value "unknown" if this value is a cannot be evaluated
2204 # at Argument-Clinic-preprocessing time (but is presumed to be valid
2205 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07002206 default = unspecified
2207
Larry Hastings4a55fc52014-01-12 11:09:57 -08002208 # If not None, default must be isinstance() of this type.
2209 # (You can also specify a tuple of types.)
2210 default_type = None
2211
Larry Hastings31826802013-10-19 00:09:25 -07002212 # "default" converted into a C value, as a string.
2213 # Or None if there is no default.
2214 c_default = None
2215
Larry Hastings2a727912014-01-16 11:32:01 -08002216 # "default" converted into a Python value, as a string.
2217 # Or None if there is no default.
2218 py_default = None
2219
Larry Hastingsabc716b2013-11-20 09:13:52 -08002220 # The default value used to initialize the C variable when
2221 # there is no default, but not specifying a default may
2222 # result in an "uninitialized variable" warning. This can
2223 # easily happen when using option groups--although
2224 # properly-written code won't actually use the variable,
2225 # the variable does get passed in to the _impl. (Ah, if
2226 # only dataflow analysis could inline the static function!)
2227 #
2228 # This value is specified as a string.
2229 # Every non-abstract subclass should supply a valid value.
2230 c_ignored_default = 'NULL'
2231
Larry Hastings31826802013-10-19 00:09:25 -07002232 # The C converter *function* to be used, if any.
2233 # (If this is not None, format_unit must be 'O&'.)
2234 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002235
Larry Hastings78cf85c2014-01-04 12:44:57 -08002236 # Should Argument Clinic add a '&' before the name of
2237 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07002238 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08002239
2240 # Should Argument Clinic add a '&' before the name of
2241 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07002242 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08002243
2244 #############################################################
2245 #############################################################
2246 ## You shouldn't need to read anything below this point to ##
2247 ## write your own converter functions. ##
2248 #############################################################
2249 #############################################################
2250
2251 # The "format unit" to specify for this variable when
2252 # parsing arguments using PyArg_ParseTuple (AndKeywords).
2253 # Custom converters should always use the default value of 'O&'.
2254 format_unit = 'O&'
2255
2256 # What encoding do we want for this variable? Only used
2257 # by format units starting with 'e'.
2258 encoding = None
2259
Larry Hastings77561cc2014-01-07 12:13:13 -08002260 # Should this object be required to be a subclass of a specific type?
2261 # If not None, should be a string representing a pointer to a
2262 # PyTypeObject (e.g. "&PyUnicode_Type").
2263 # Only used by the 'O!' format unit (and the "object" converter).
2264 subclass_of = None
2265
Larry Hastings78cf85c2014-01-04 12:44:57 -08002266 # Do we want an adjacent '_length' variable for this variable?
2267 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07002268 length = False
2269
Larry Hastings5c661892014-01-24 06:17:25 -08002270 # Should we show this parameter in the generated
2271 # __text_signature__? This is *almost* always True.
Larry Hastingsc2047262014-01-25 20:43:29 -08002272 # (It's only False for __new__, __init__, and METH_STATIC functions.)
Larry Hastings5c661892014-01-24 06:17:25 -08002273 show_in_signature = True
2274
2275 # Overrides the name used in a text signature.
2276 # The name used for a "self" parameter must be one of
2277 # self, type, or module; however users can set their own.
2278 # This lets the self_converter overrule the user-settable
2279 # name, *just* for the text signature.
2280 # Only set by self_converter.
2281 signature_name = None
2282
2283 # keep in sync with self_converter.__init__!
Larry Hastings7726ac92014-01-31 22:03:12 -08002284 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 -07002285 self.name = name
Larry Hastings7726ac92014-01-31 22:03:12 -08002286 self.py_name = py_name
Larry Hastings31826802013-10-19 00:09:25 -07002287
2288 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08002289 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002290 if isinstance(self.default_type, type):
2291 types_str = self.default_type.__name__
2292 else:
2293 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2294 fail("{}: default value {!r} for field {} is not of type {}".format(
2295 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002296 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002297
Larry Hastingsb4705752014-01-18 21:54:15 -08002298 if c_default:
2299 self.c_default = c_default
2300 if py_default:
2301 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002302
Larry Hastings31826802013-10-19 00:09:25 -07002303 if annotation != unspecified:
2304 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings7726ac92014-01-31 22:03:12 -08002305
2306 # this is deliberate, to prevent you from caching information
2307 # about the function in the init.
2308 # (that breaks if we get cloned.)
2309 # so after this change we will noisily fail.
2310 self.function = LandMine("Don't access members of self.function inside converter_init!")
Larry Hastings31826802013-10-19 00:09:25 -07002311 self.converter_init(**kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002312 self.function = function
Larry Hastings31826802013-10-19 00:09:25 -07002313
2314 def converter_init(self):
2315 pass
2316
2317 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002318 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002319
Larry Hastings5c661892014-01-24 06:17:25 -08002320 def _render_self(self, parameter, data):
2321 self.parameter = parameter
2322 original_name = self.name
2323 name = ensure_legal_c_identifier(original_name)
2324
2325 # impl_arguments
2326 s = ("&" if self.impl_by_reference else "") + name
2327 data.impl_arguments.append(s)
2328 if self.length:
2329 data.impl_arguments.append(self.length_name())
2330
2331 # impl_parameters
2332 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2333 if self.length:
2334 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2335
2336 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002337 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002338 original_name = self.name
2339 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002340
2341 # declarations
2342 d = self.declaration()
2343 data.declarations.append(d)
2344
2345 # initializers
2346 initializers = self.initialize()
2347 if initializers:
2348 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2349
Larry Hastingsc2047262014-01-25 20:43:29 -08002350 # modifications
2351 modifications = self.modify()
2352 if modifications:
2353 data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2354
Larry Hastings31826802013-10-19 00:09:25 -07002355 # keywords
Larry Hastings7726ac92014-01-31 22:03:12 -08002356 data.keywords.append(parameter.name)
Larry Hastings31826802013-10-19 00:09:25 -07002357
2358 # format_units
2359 if self.is_optional() and '|' not in data.format_units:
2360 data.format_units.append('|')
2361 if parameter.is_keyword_only() and '$' not in data.format_units:
2362 data.format_units.append('$')
2363 data.format_units.append(self.format_unit)
2364
2365 # parse_arguments
2366 self.parse_argument(data.parse_arguments)
2367
Larry Hastings31826802013-10-19 00:09:25 -07002368 # cleanup
2369 cleanup = self.cleanup()
2370 if cleanup:
2371 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2372
Larry Hastings5c661892014-01-24 06:17:25 -08002373 def render(self, parameter, data):
2374 """
2375 parameter is a clinic.Parameter instance.
2376 data is a CRenderData instance.
2377 """
2378 self._render_self(parameter, data)
2379 self._render_non_self(parameter, data)
2380
Larry Hastingsebdcb502013-11-23 14:54:00 -08002381 def length_name(self):
2382 """Computes the name of the associated "length" variable."""
2383 if not self.length:
2384 return None
2385 return ensure_legal_c_identifier(self.name) + "_length"
2386
Larry Hastings31826802013-10-19 00:09:25 -07002387 # Why is this one broken out separately?
2388 # For "positional-only" function parsing,
2389 # which generates a bunch of PyArg_ParseTuple calls.
2390 def parse_argument(self, list):
2391 assert not (self.converter and self.encoding)
2392 if self.format_unit == 'O&':
2393 assert self.converter
2394 list.append(self.converter)
2395
2396 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002397 list.append(c_repr(self.encoding))
2398 elif self.subclass_of:
2399 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002400
Larry Hastingsebdcb502013-11-23 14:54:00 -08002401 legal_name = ensure_legal_c_identifier(self.name)
2402 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002403 list.append(s)
2404
Larry Hastingsebdcb502013-11-23 14:54:00 -08002405 if self.length:
2406 list.append("&" + self.length_name())
2407
Larry Hastings31826802013-10-19 00:09:25 -07002408 #
2409 # All the functions after here are intended as extension points.
2410 #
2411
2412 def simple_declaration(self, by_reference=False):
2413 """
2414 Computes the basic declaration of the variable.
2415 Used in computing the prototype declaration and the
2416 variable declaration.
2417 """
2418 prototype = [self.type]
2419 if by_reference or not self.type.endswith('*'):
2420 prototype.append(" ")
2421 if by_reference:
2422 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002423 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002424 return "".join(prototype)
2425
2426 def declaration(self):
2427 """
2428 The C statement to declare this variable.
2429 """
2430 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002431 default = self.c_default
2432 if not default and self.parameter.group:
2433 default = self.c_ignored_default
2434 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002435 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002436 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002437 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002438 if self.length:
2439 declaration.append('\nPy_ssize_clean_t ')
2440 declaration.append(self.length_name())
2441 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002442 s = "".join(declaration)
2443 # double up curly-braces, this string will be used
2444 # as part of a format_map() template later
2445 s = s.replace("{", "{{")
2446 s = s.replace("}", "}}")
2447 return s
Larry Hastings31826802013-10-19 00:09:25 -07002448
2449 def initialize(self):
2450 """
2451 The C statements required to set up this variable before parsing.
2452 Returns a string containing this code indented at column 0.
2453 If no initialization is necessary, returns an empty string.
2454 """
2455 return ""
2456
Larry Hastingsc2047262014-01-25 20:43:29 -08002457 def modify(self):
2458 """
2459 The C statements required to modify this variable after parsing.
2460 Returns a string containing this code indented at column 0.
2461 If no initialization is necessary, returns an empty string.
2462 """
2463 return ""
2464
Larry Hastings31826802013-10-19 00:09:25 -07002465 def cleanup(self):
2466 """
2467 The C statements required to clean up after this variable.
2468 Returns a string containing this code indented at column 0.
2469 If no cleanup is necessary, returns an empty string.
2470 """
2471 return ""
2472
Larry Hastings7726ac92014-01-31 22:03:12 -08002473 def pre_render(self):
2474 """
2475 A second initialization function, like converter_init,
2476 called just before rendering.
2477 You are permitted to examine self.function here.
2478 """
2479 pass
2480
Larry Hastings31826802013-10-19 00:09:25 -07002481
2482class bool_converter(CConverter):
2483 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002484 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002485 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002486 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002487
2488 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002489 if self.default is not unspecified:
2490 self.default = bool(self.default)
2491 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002492
2493class char_converter(CConverter):
2494 type = 'char'
Larry Hastings7f90cba2015-04-15 23:02:12 -04002495 default_type = (bytes, bytearray)
Larry Hastings31826802013-10-19 00:09:25 -07002496 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002497 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002498
Larry Hastings4a55fc52014-01-12 11:09:57 -08002499 def converter_init(self):
Larry Hastings7f90cba2015-04-15 23:02:12 -04002500 if isinstance(self.default, self.default_type) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002501 fail("char_converter: illegal default value " + repr(self.default))
2502
2503
Larry Hastings31826802013-10-19 00:09:25 -07002504@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002505class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002506 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002507 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002508 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002509 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002510
2511 def converter_init(self, *, bitwise=False):
2512 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002513 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002514
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002515class byte_converter(unsigned_char_converter): pass
2516
Larry Hastings31826802013-10-19 00:09:25 -07002517class short_converter(CConverter):
2518 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002519 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002520 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002521 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002522
2523class unsigned_short_converter(CConverter):
2524 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002525 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002526 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002527 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002528
2529 def converter_init(self, *, bitwise=False):
2530 if not bitwise:
2531 fail("Unsigned shorts must be bitwise (for now).")
2532
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002533@add_legacy_c_converter('C', accept={str})
Larry Hastings31826802013-10-19 00:09:25 -07002534class int_converter(CConverter):
2535 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002536 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002537 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002538 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002539
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002540 def converter_init(self, *, accept={int}, type=None):
2541 if accept == {str}:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002542 self.format_unit = 'C'
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002543 elif accept != {int}:
2544 fail("int_converter: illegal 'accept' argument " + repr(accept))
Larry Hastingsdfbeb162014-10-13 10:39:41 +01002545 if type != None:
2546 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002547
2548class unsigned_int_converter(CConverter):
2549 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002550 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002551 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002552 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002553
2554 def converter_init(self, *, bitwise=False):
2555 if not bitwise:
2556 fail("Unsigned ints must be bitwise (for now).")
2557
2558class long_converter(CConverter):
2559 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002560 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002561 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002562 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002563
2564class unsigned_long_converter(CConverter):
2565 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002566 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002567 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002568 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002569
2570 def converter_init(self, *, bitwise=False):
2571 if not bitwise:
2572 fail("Unsigned longs must be bitwise (for now).")
2573
2574class PY_LONG_LONG_converter(CConverter):
2575 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002576 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002577 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002578 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002579
2580class unsigned_PY_LONG_LONG_converter(CConverter):
2581 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002582 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002583 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002584 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002585
2586 def converter_init(self, *, bitwise=False):
2587 if not bitwise:
2588 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2589
2590class Py_ssize_t_converter(CConverter):
2591 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002592 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002593 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002594 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002595
2596
2597class float_converter(CConverter):
2598 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002599 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002600 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002601 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002602
2603class double_converter(CConverter):
2604 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002605 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002606 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002607 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002608
2609
2610class Py_complex_converter(CConverter):
2611 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002612 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002613 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002614 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002615
2616
2617class object_converter(CConverter):
2618 type = 'PyObject *'
2619 format_unit = 'O'
2620
Larry Hastings4a55fc52014-01-12 11:09:57 -08002621 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2622 if converter:
2623 if subclass_of:
2624 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2625 self.format_unit = 'O&'
2626 self.converter = converter
2627 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002628 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002629 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002630
Larry Hastings77561cc2014-01-07 12:13:13 -08002631 if type is not None:
2632 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002633
2634
Larry Hastings7f90cba2015-04-15 23:02:12 -04002635#
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002636# We define three conventions for buffer types in the 'accept' argument:
2637#
2638# buffer : any object supporting the buffer interface
2639# rwbuffer: any object supporting the buffer interface, but must be writeable
2640# robuffer: any object supporting the buffer interface, but must not be writeable
Larry Hastings7f90cba2015-04-15 23:02:12 -04002641#
2642
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002643class buffer: pass
2644class rwbuffer: pass
2645class robuffer: pass
2646
Larry Hastings38337d12015-05-07 23:30:09 -07002647def str_converter_key(types, encoding, zeroes):
2648 return (frozenset(types), bool(encoding), bool(zeroes))
2649
2650str_converter_argument_map = {}
2651
Larry Hastings31826802013-10-19 00:09:25 -07002652class str_converter(CConverter):
2653 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002654 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002655 format_unit = 's'
2656
Larry Hastings38337d12015-05-07 23:30:09 -07002657 def converter_init(self, *, accept={str}, encoding=None, zeroes=False):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002658
Larry Hastings38337d12015-05-07 23:30:09 -07002659 key = str_converter_key(accept, encoding, zeroes)
2660 format_unit = str_converter_argument_map.get(key)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002661 if not format_unit:
Larry Hastings38337d12015-05-07 23:30:09 -07002662 fail("str_converter: illegal combination of arguments", key)
2663
Larry Hastingsebdcb502013-11-23 14:54:00 -08002664 self.format_unit = format_unit
Larry Hastings38337d12015-05-07 23:30:09 -07002665 self.length = bool(zeroes)
2666 if encoding:
2667 if self.default not in (Null, None, unspecified):
2668 fail("str_converter: Argument Clinic doesn't support default values for encoded strings")
2669 self.encoding = encoding
2670 self.type = 'char *'
2671 # sorry, clinic can't support preallocated buffers
2672 # for es# and et#
2673 self.c_default = "NULL"
2674
2675 def cleanup(self):
2676 if self.encoding:
2677 name = ensure_legal_c_identifier(self.name)
2678 return "".join(["if (", name, ")\n PyMem_FREE(", name, ");\n"])
2679
2680#
2681# This is the fourth or fifth rewrite of registering all the
2682# crazy string converter format units. Previous approaches hid
2683# bugs--generally mismatches between the semantics of the format
2684# unit and the arguments necessary to represent those semantics
2685# properly. Hopefully with this approach we'll get it 100% right.
2686#
2687# The r() function (short for "register") both registers the
2688# mapping from arguments to format unit *and* registers the
2689# legacy C converter for that format unit.
2690#
2691def r(format_unit, *, accept, encoding=False, zeroes=False):
2692 if not encoding and format_unit != 's':
2693 # add the legacy c converters here too.
2694 #
2695 # note: add_legacy_c_converter can't work for
2696 # es, es#, et, or et#
2697 # because of their extra encoding argument
2698 #
2699 # also don't add the converter for 's' because
2700 # the metaclass for CConverter adds it for us.
2701 kwargs = {}
2702 if accept != {str}:
2703 kwargs['accept'] = accept
2704 if zeroes:
2705 kwargs['zeroes'] = True
2706 added_f = functools.partial(str_converter, **kwargs)
2707 legacy_converters[format_unit] = added_f
2708
2709 d = str_converter_argument_map
2710 key = str_converter_key(accept, encoding, zeroes)
2711 if key in d:
2712 sys.exit("Duplicate keys specified for str_converter_argument_map!")
2713 d[key] = format_unit
2714
2715r('es', encoding=True, accept={str})
2716r('es#', encoding=True, zeroes=True, accept={str})
2717r('et', encoding=True, accept={bytes, bytearray, str})
2718r('et#', encoding=True, zeroes=True, accept={bytes, bytearray, str})
2719r('s', accept={str})
2720r('s#', zeroes=True, accept={robuffer, str})
2721r('y', accept={robuffer})
2722r('y#', zeroes=True, accept={robuffer})
2723r('z', accept={str, NoneType})
2724r('z#', zeroes=True, accept={robuffer, str, NoneType})
2725del r
Larry Hastings31826802013-10-19 00:09:25 -07002726
2727
2728class PyBytesObject_converter(CConverter):
2729 type = 'PyBytesObject *'
2730 format_unit = 'S'
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002731 # accept = {bytes}
Larry Hastings31826802013-10-19 00:09:25 -07002732
2733class PyByteArrayObject_converter(CConverter):
2734 type = 'PyByteArrayObject *'
2735 format_unit = 'Y'
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002736 # accept = {bytearray}
Larry Hastings31826802013-10-19 00:09:25 -07002737
2738class unicode_converter(CConverter):
2739 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002740 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002741 format_unit = 'U'
2742
Larry Hastings38337d12015-05-07 23:30:09 -07002743@add_legacy_c_converter('u#', zeroes=True)
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002744@add_legacy_c_converter('Z', accept={str, NoneType})
Larry Hastings38337d12015-05-07 23:30:09 -07002745@add_legacy_c_converter('Z#', accept={str, NoneType}, zeroes=True)
Larry Hastings31826802013-10-19 00:09:25 -07002746class Py_UNICODE_converter(CConverter):
2747 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002748 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002749 format_unit = 'u'
2750
Larry Hastings38337d12015-05-07 23:30:09 -07002751 def converter_init(self, *, accept={str}, zeroes=False):
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002752 format_unit = 'Z' if accept=={str, NoneType} else 'u'
Larry Hastings38337d12015-05-07 23:30:09 -07002753 if zeroes:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002754 format_unit += '#'
2755 self.length = True
2756 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002757
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002758@add_legacy_c_converter('s*', accept={str, buffer})
2759@add_legacy_c_converter('z*', accept={str, buffer, NoneType})
2760@add_legacy_c_converter('w*', accept={rwbuffer})
Larry Hastings31826802013-10-19 00:09:25 -07002761class Py_buffer_converter(CConverter):
2762 type = 'Py_buffer'
2763 format_unit = 'y*'
2764 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002765 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002766
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002767 def converter_init(self, *, accept={buffer}):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002768 if self.default not in (unspecified, None):
2769 fail("The only legal default value for Py_buffer is None.")
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002770
Larry Hastings3f144c22014-01-06 10:34:00 -08002771 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002772
Larry Hastingsdbfdc382015-05-04 06:59:46 -07002773 if accept == {str, buffer, NoneType}:
2774 format_unit = 'z*'
2775 elif accept == {str, buffer}:
2776 format_unit = 's*'
2777 elif accept == {buffer}:
2778 format_unit = 'y*'
2779 elif accept == {rwbuffer}:
2780 format_unit = 'w*'
Larry Hastings31826802013-10-19 00:09:25 -07002781 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002782 fail("Py_buffer_converter: illegal combination of arguments")
2783
2784 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002785
2786 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002787 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002788 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002789
2790
Larry Hastings5c661892014-01-24 06:17:25 -08002791def correct_name_for_self(f):
2792 if f.kind in (CALLABLE, METHOD_INIT):
2793 if f.cls:
2794 return "PyObject *", "self"
2795 return "PyModuleDef *", "module"
2796 if f.kind == STATIC_METHOD:
2797 return "void *", "null"
2798 if f.kind in (CLASS_METHOD, METHOD_NEW):
2799 return "PyTypeObject *", "type"
2800 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2801
Larry Hastingsc2047262014-01-25 20:43:29 -08002802def required_type_for_self_for_parser(f):
2803 type, _ = correct_name_for_self(f)
2804 if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2805 return type
2806 return None
2807
Larry Hastings5c661892014-01-24 06:17:25 -08002808
Larry Hastingsebdcb502013-11-23 14:54:00 -08002809class self_converter(CConverter):
2810 """
2811 A special-case converter:
2812 this is the default converter used for "self".
2813 """
Larry Hastings5c661892014-01-24 06:17:25 -08002814 type = None
2815 format_unit = ''
2816
Larry Hastings78cf85c2014-01-04 12:44:57 -08002817 def converter_init(self, *, type=None):
Larry Hastings7726ac92014-01-31 22:03:12 -08002818 self.specified_type = type
2819
2820 def pre_render(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002821 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002822 default_type, default_name = correct_name_for_self(f)
2823 self.signature_name = default_name
Larry Hastings7726ac92014-01-31 22:03:12 -08002824 self.type = self.specified_type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002825
Larry Hastings5c661892014-01-24 06:17:25 -08002826 kind = self.function.kind
2827 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2828
2829 if (kind == STATIC_METHOD) or new_or_init:
2830 self.show_in_signature = False
2831
2832 # tp_new (METHOD_NEW) functions are of type newfunc:
2833 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2834 # PyTypeObject is a typedef for struct _typeobject.
2835 #
2836 # tp_init (METHOD_INIT) functions are of type initproc:
2837 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2838 #
2839 # All other functions generated by Argument Clinic are stored in
2840 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2841 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2842 # However! We habitually cast these functions to PyCFunction,
2843 # since functions that accept keyword arguments don't fit this signature
2844 # but are stored there anyway. So strict type equality isn't important
2845 # for these functions.
2846 #
2847 # So:
2848 #
2849 # * The name of the first parameter to the impl and the parsing function will always
2850 # be self.name.
2851 #
2852 # * The type of the first parameter to the impl will always be of self.type.
2853 #
2854 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2855 # * The type of the first parameter to the parsing function is also self.type.
2856 # This means that if you step into the parsing function, your "self" parameter
2857 # is of the correct type, which may make debugging more pleasant.
2858 #
2859 # * Else if the function is tp_new (METHOD_NEW):
2860 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2861 # so the type signature of the function call is an exact match.
2862 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2863 # in the impl call.
2864 #
2865 # * Else if the function is tp_init (METHOD_INIT):
2866 # * The type of the first parameter to the parsing function is "PyObject *",
2867 # so the type signature of the function call is an exact match.
2868 # * If self.type != "PyObject *", we cast the first parameter to self.type
2869 # in the impl call.
2870
2871 @property
2872 def parser_type(self):
Larry Hastingsc2047262014-01-25 20:43:29 -08002873 return required_type_for_self_for_parser(self.function) or self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002874
Larry Hastingsebdcb502013-11-23 14:54:00 -08002875 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002876 """
2877 parameter is a clinic.Parameter instance.
2878 data is a CRenderData instance.
2879 """
2880 if self.function.kind == STATIC_METHOD:
2881 return
2882
2883 self._render_self(parameter, data)
2884
2885 if self.type != self.parser_type:
2886 # insert cast to impl_argument[0], aka self.
2887 # we know we're in the first slot in all the CRenderData lists,
2888 # because we render parameters in order, and self is always first.
2889 assert len(data.impl_arguments) == 1
2890 assert data.impl_arguments[0] == self.name
2891 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2892
2893 def set_template_dict(self, template_dict):
2894 template_dict['self_name'] = self.name
2895 template_dict['self_type'] = self.parser_type
Larry Hastingsf0537e82014-01-25 22:01:12 -08002896 kind = self.function.kind
2897 cls = self.function.cls
2898
2899 if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef):
2900 if kind == METHOD_NEW:
2901 passed_in_type = self.name
2902 else:
2903 passed_in_type = 'Py_TYPE({})'.format(self.name)
2904
2905 line = '({passed_in_type} == {type_object}) &&\n '
2906 d = {
2907 'type_object': self.function.cls.type_object,
2908 'passed_in_type': passed_in_type
2909 }
2910 template_dict['self_type_check'] = line.format_map(d)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002911
Larry Hastings31826802013-10-19 00:09:25 -07002912
2913
2914def add_c_return_converter(f, name=None):
2915 if not name:
2916 name = f.__name__
2917 if not name.endswith('_return_converter'):
2918 return f
2919 name = name[:-len('_return_converter')]
2920 return_converters[name] = f
2921 return f
2922
2923
2924class CReturnConverterAutoRegister(type):
2925 def __init__(cls, name, bases, classdict):
2926 add_c_return_converter(cls)
2927
2928class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2929
Larry Hastings78cf85c2014-01-04 12:44:57 -08002930 # The C type to use for this variable.
2931 # 'type' should be a Python string specifying the type, e.g. "int".
2932 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002933 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002934
2935 # The Python default value for this parameter, as a Python value.
2936 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002937 default = None
2938
Larry Hastings2a727912014-01-16 11:32:01 -08002939 def __init__(self, *, py_default=None, **kwargs):
2940 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002941 try:
2942 self.return_converter_init(**kwargs)
2943 except TypeError as e:
2944 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2945 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2946
2947 def return_converter_init(self):
2948 pass
2949
2950 def declare(self, data, name="_return_value"):
2951 line = []
2952 add = line.append
2953 add(self.type)
2954 if not self.type.endswith('*'):
2955 add(' ')
2956 add(name + ';')
2957 data.declarations.append(''.join(line))
2958 data.return_value = name
2959
2960 def err_occurred_if(self, expr, data):
2961 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2962
2963 def err_occurred_if_null_pointer(self, variable, data):
2964 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2965
2966 def render(self, function, data):
2967 """
2968 function is a clinic.Function instance.
2969 data is a CRenderData instance.
2970 """
2971 pass
2972
2973add_c_return_converter(CReturnConverter, 'object')
2974
Larry Hastings78cf85c2014-01-04 12:44:57 -08002975class NoneType_return_converter(CReturnConverter):
2976 def render(self, function, data):
2977 self.declare(data)
2978 data.return_conversion.append('''
2979if (_return_value != Py_None)
2980 goto exit;
2981return_value = Py_None;
2982Py_INCREF(Py_None);
2983'''.strip())
2984
Larry Hastings4a55fc52014-01-12 11:09:57 -08002985class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002986 type = 'int'
2987
2988 def render(self, function, data):
2989 self.declare(data)
2990 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002991 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002992
2993class long_return_converter(CReturnConverter):
2994 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002995 conversion_fn = 'PyLong_FromLong'
2996 cast = ''
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002997 unsigned_cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002998
2999 def render(self, function, data):
3000 self.declare(data)
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003001 self.err_occurred_if("_return_value == {}-1".format(self.unsigned_cast), data)
Larry Hastings31826802013-10-19 00:09:25 -07003002 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08003003 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07003004
Larry Hastings4a55fc52014-01-12 11:09:57 -08003005class int_return_converter(long_return_converter):
3006 type = 'int'
3007 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07003008
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003009class init_return_converter(long_return_converter):
3010 """
3011 Special return converter for __init__ functions.
3012 """
3013 type = 'int'
3014 cast = '(long)'
3015
3016 def render(self, function, data):
3017 pass
3018
Larry Hastings4a55fc52014-01-12 11:09:57 -08003019class unsigned_long_return_converter(long_return_converter):
3020 type = 'unsigned long'
3021 conversion_fn = 'PyLong_FromUnsignedLong'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003022 unsigned_cast = '(unsigned long)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003023
3024class unsigned_int_return_converter(unsigned_long_return_converter):
3025 type = 'unsigned int'
3026 cast = '(unsigned long)'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003027 unsigned_cast = '(unsigned int)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003028
3029class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07003030 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003031 conversion_fn = 'PyLong_FromSsize_t'
3032
3033class size_t_return_converter(long_return_converter):
3034 type = 'size_t'
3035 conversion_fn = 'PyLong_FromSize_t'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10003036 unsigned_cast = '(size_t)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08003037
3038
3039class double_return_converter(CReturnConverter):
3040 type = 'double'
3041 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07003042
3043 def render(self, function, data):
3044 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08003045 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07003046 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08003047 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
3048
3049class float_return_converter(double_return_converter):
3050 type = 'float'
3051 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07003052
3053
3054class DecodeFSDefault_return_converter(CReturnConverter):
3055 type = 'char *'
3056
3057 def render(self, function, data):
3058 self.declare(data)
3059 self.err_occurred_if_null_pointer("_return_value", data)
3060 data.return_conversion.append(
3061 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
3062
3063
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003064def eval_ast_expr(node, globals, *, filename='-'):
3065 """
3066 Takes an ast.Expr node. Compiles and evaluates it.
3067 Returns the result of the expression.
3068
3069 globals represents the globals dict the expression
3070 should see. (There's no equivalent for "locals" here.)
3071 """
3072
3073 if isinstance(node, ast.Expr):
3074 node = node.value
3075
3076 node = ast.Expression(node)
3077 co = compile(node, filename, 'eval')
3078 fn = types.FunctionType(co, globals)
3079 return fn()
3080
3081
Larry Hastings31826802013-10-19 00:09:25 -07003082class IndentStack:
3083 def __init__(self):
3084 self.indents = []
3085 self.margin = None
3086
3087 def _ensure(self):
3088 if not self.indents:
3089 fail('IndentStack expected indents, but none are defined.')
3090
3091 def measure(self, line):
3092 """
3093 Returns the length of the line's margin.
3094 """
3095 if '\t' in line:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003096 fail('Tab characters are illegal in the Argument Clinic DSL.')
Larry Hastings31826802013-10-19 00:09:25 -07003097 stripped = line.lstrip()
3098 if not len(stripped):
3099 # we can't tell anything from an empty line
3100 # so just pretend it's indented like our current indent
3101 self._ensure()
3102 return self.indents[-1]
3103 return len(line) - len(stripped)
3104
3105 def infer(self, line):
3106 """
3107 Infer what is now the current margin based on this line.
3108 Returns:
3109 1 if we have indented (or this is the first margin)
3110 0 if the margin has not changed
3111 -N if we have dedented N times
3112 """
3113 indent = self.measure(line)
3114 margin = ' ' * indent
3115 if not self.indents:
3116 self.indents.append(indent)
3117 self.margin = margin
3118 return 1
3119 current = self.indents[-1]
3120 if indent == current:
3121 return 0
3122 if indent > current:
3123 self.indents.append(indent)
3124 self.margin = margin
3125 return 1
3126 # indent < current
3127 if indent not in self.indents:
3128 fail("Illegal outdent.")
3129 outdent_count = 0
3130 while indent != current:
3131 self.indents.pop()
3132 current = self.indents[-1]
3133 outdent_count -= 1
3134 self.margin = margin
3135 return outdent_count
3136
3137 @property
3138 def depth(self):
3139 """
3140 Returns how many margins are currently defined.
3141 """
3142 return len(self.indents)
3143
3144 def indent(self, line):
3145 """
3146 Indents a line by the currently defined margin.
3147 """
3148 return self.margin + line
3149
3150 def dedent(self, line):
3151 """
3152 Dedents a line by the currently defined margin.
3153 (The inverse of 'indent'.)
3154 """
3155 margin = self.margin
3156 indent = self.indents[-1]
3157 if not line.startswith(margin):
3158 fail('Cannot dedent, line does not start with the previous margin:')
3159 return line[indent:]
3160
3161
3162class DSLParser:
3163 def __init__(self, clinic):
3164 self.clinic = clinic
3165
3166 self.directives = {}
3167 for name in dir(self):
3168 # functions that start with directive_ are added to directives
3169 _, s, key = name.partition("directive_")
3170 if s:
3171 self.directives[key] = getattr(self, name)
3172
3173 # functions that start with at_ are too, with an @ in front
3174 _, s, key = name.partition("at_")
3175 if s:
3176 self.directives['@' + key] = getattr(self, name)
3177
3178 self.reset()
3179
3180 def reset(self):
3181 self.function = None
3182 self.state = self.state_dsl_start
3183 self.parameter_indent = None
3184 self.keyword_only = False
3185 self.group = 0
3186 self.parameter_state = self.ps_start
Larry Hastingsc2047262014-01-25 20:43:29 -08003187 self.seen_positional_with_default = False
Larry Hastings31826802013-10-19 00:09:25 -07003188 self.indent = IndentStack()
3189 self.kind = CALLABLE
3190 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08003191 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08003192 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07003193
Larry Hastingsebdcb502013-11-23 14:54:00 -08003194 def directive_version(self, required):
3195 global version
3196 if version_comparitor(version, required) < 0:
3197 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
3198
Larry Hastings31826802013-10-19 00:09:25 -07003199 def directive_module(self, name):
3200 fields = name.split('.')
3201 new = fields.pop()
3202 module, cls = self.clinic._module_and_class(fields)
3203 if cls:
3204 fail("Can't nest a module inside a class!")
Larry Hastingsc2047262014-01-25 20:43:29 -08003205
3206 if name in module.classes:
3207 fail("Already defined module " + repr(name) + "!")
3208
Larry Hastings31826802013-10-19 00:09:25 -07003209 m = Module(name, module)
3210 module.modules[name] = m
3211 self.block.signatures.append(m)
3212
Larry Hastingsc2047262014-01-25 20:43:29 -08003213 def directive_class(self, name, typedef, type_object):
Larry Hastings31826802013-10-19 00:09:25 -07003214 fields = name.split('.')
3215 in_classes = False
3216 parent = self
3217 name = fields.pop()
3218 so_far = []
3219 module, cls = self.clinic._module_and_class(fields)
3220
Larry Hastingsc2047262014-01-25 20:43:29 -08003221 parent = cls or module
3222 if name in parent.classes:
3223 fail("Already defined class " + repr(name) + "!")
3224
3225 c = Class(name, module, cls, typedef, type_object)
3226 parent.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07003227 self.block.signatures.append(c)
3228
Larry Hastingsbebf7352014-01-17 17:47:17 -08003229 def directive_set(self, name, value):
3230 if name not in ("line_prefix", "line_suffix"):
3231 fail("unknown variable", repr(name))
3232
3233 value = value.format_map({
3234 'block comment start': '/*',
3235 'block comment end': '*/',
3236 })
3237
3238 self.clinic.__dict__[name] = value
3239
3240 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06003241 if command == 'new':
3242 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003243 return
3244
Zachary Ware071baa62014-01-21 23:07:12 -06003245 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08003246 self.clinic.get_destination(name).clear()
3247 fail("unknown destination command", repr(command))
3248
3249
Larry Hastings0759f842015-04-03 13:09:02 -07003250 def directive_output(self, command_or_name, destination=''):
3251 fd = self.clinic.destination_buffers
Larry Hastingsbebf7352014-01-17 17:47:17 -08003252
Larry Hastings0759f842015-04-03 13:09:02 -07003253 if command_or_name == "preset":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003254 preset = self.clinic.presets.get(destination)
3255 if not preset:
3256 fail("Unknown preset " + repr(destination) + "!")
3257 fd.update(preset)
3258 return
3259
Larry Hastings0759f842015-04-03 13:09:02 -07003260 if command_or_name == "push":
3261 self.clinic.destination_buffers_stack.append(fd.copy())
Larry Hastingsbebf7352014-01-17 17:47:17 -08003262 return
3263
Larry Hastings0759f842015-04-03 13:09:02 -07003264 if command_or_name == "pop":
3265 if not self.clinic.destination_buffers_stack:
Larry Hastingsbebf7352014-01-17 17:47:17 -08003266 fail("Can't 'output pop', stack is empty!")
Larry Hastings0759f842015-04-03 13:09:02 -07003267 previous_fd = self.clinic.destination_buffers_stack.pop()
Larry Hastingsbebf7352014-01-17 17:47:17 -08003268 fd.update(previous_fd)
3269 return
3270
3271 # secret command for debugging!
Larry Hastings0759f842015-04-03 13:09:02 -07003272 if command_or_name == "print":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003273 self.block.output.append(pprint.pformat(fd))
3274 self.block.output.append('\n')
3275 return
3276
3277 d = self.clinic.get_destination(destination)
3278
Larry Hastings0759f842015-04-03 13:09:02 -07003279 if command_or_name == "everything":
Larry Hastingsbebf7352014-01-17 17:47:17 -08003280 for name in list(fd):
3281 fd[name] = d
3282 return
3283
Larry Hastings0759f842015-04-03 13:09:02 -07003284 if command_or_name not in fd:
3285 fail("Invalid command / destination name " + repr(command_or_name) + ", must be one of:\n preset push pop print everything " + " ".join(fd))
3286 fd[command_or_name] = d
Larry Hastingsbebf7352014-01-17 17:47:17 -08003287
3288 def directive_dump(self, name):
3289 self.block.output.append(self.clinic.get_destination(name).dump())
3290
3291 def directive_print(self, *args):
3292 self.block.output.append(' '.join(args))
3293 self.block.output.append('\n')
3294
3295 def directive_preserve(self):
3296 if self.preserve_output:
3297 fail("Can't have preserve twice in one block!")
3298 self.preserve_output = True
3299
Larry Hastings31826802013-10-19 00:09:25 -07003300 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003301 if self.kind is not CALLABLE:
3302 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003303 self.kind = CLASS_METHOD
3304
3305 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003306 if self.kind is not CALLABLE:
3307 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003308 self.kind = STATIC_METHOD
3309
3310 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003311 if self.coexist:
3312 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07003313 self.coexist = True
3314
3315 def parse(self, block):
3316 self.reset()
3317 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08003318 self.saved_output = self.block.output
3319 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07003320 block_start = self.clinic.block_parser.line_number
3321 lines = block.input.split('\n')
3322 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
3323 if '\t' in line:
3324 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
3325 self.state(line)
3326
3327 self.next(self.state_terminal)
3328 self.state(None)
3329
Larry Hastingsbebf7352014-01-17 17:47:17 -08003330 block.output.extend(self.clinic.language.render(clinic, block.signatures))
3331
3332 if self.preserve_output:
3333 if block.output:
3334 fail("'preserve' only works for blocks that don't produce any output!")
3335 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07003336
3337 @staticmethod
3338 def ignore_line(line):
3339 # ignore comment-only lines
3340 if line.lstrip().startswith('#'):
3341 return True
3342
3343 # Ignore empty lines too
3344 # (but not in docstring sections!)
3345 if not line.strip():
3346 return True
3347
3348 return False
3349
3350 @staticmethod
3351 def calculate_indent(line):
3352 return len(line) - len(line.strip())
3353
3354 def next(self, state, line=None):
3355 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3356 self.state = state
3357 if line is not None:
3358 self.state(line)
3359
3360 def state_dsl_start(self, line):
3361 # self.block = self.ClinicOutputBlock(self)
3362 if self.ignore_line(line):
3363 return
Larry Hastings7726ac92014-01-31 22:03:12 -08003364
3365 # is it a directive?
3366 fields = shlex.split(line)
3367 directive_name = fields[0]
3368 directive = self.directives.get(directive_name, None)
3369 if directive:
3370 try:
3371 directive(*fields[1:])
3372 except TypeError as e:
3373 fail(str(e))
3374 return
3375
Larry Hastings31826802013-10-19 00:09:25 -07003376 self.next(self.state_modulename_name, line)
3377
3378 def state_modulename_name(self, line):
3379 # looking for declaration, which establishes the leftmost column
3380 # line should be
3381 # modulename.fnname [as c_basename] [-> return annotation]
3382 # square brackets denote optional syntax.
3383 #
Larry Hastings4a714d42014-01-14 22:22:41 -08003384 # alternatively:
3385 # modulename.fnname [as c_basename] = modulename.existing_fn_name
3386 # clones the parameters and return converter from that
3387 # function. you can't modify them. you must enter a
3388 # new docstring.
3389 #
Larry Hastings31826802013-10-19 00:09:25 -07003390 # (but we might find a directive first!)
3391 #
3392 # this line is permitted to start with whitespace.
3393 # we'll call this number of spaces F (for "function").
3394
3395 if not line.strip():
3396 return
3397
3398 self.indent.infer(line)
3399
Larry Hastings4a714d42014-01-14 22:22:41 -08003400 # are we cloning?
3401 before, equals, existing = line.rpartition('=')
3402 if equals:
3403 full_name, _, c_basename = before.partition(' as ')
3404 full_name = full_name.strip()
3405 c_basename = c_basename.strip()
3406 existing = existing.strip()
3407 if (is_legal_py_identifier(full_name) and
3408 (not c_basename or is_legal_c_identifier(c_basename)) and
3409 is_legal_py_identifier(existing)):
3410 # we're cloning!
3411 fields = [x.strip() for x in existing.split('.')]
3412 function_name = fields.pop()
3413 module, cls = self.clinic._module_and_class(fields)
3414
3415 for existing_function in (cls or module).functions:
3416 if existing_function.name == function_name:
3417 break
3418 else:
3419 existing_function = None
3420 if not existing_function:
Larry Hastings7726ac92014-01-31 22:03:12 -08003421 print("class", cls, "module", module, "existing", existing)
Larry Hastingsc2047262014-01-25 20:43:29 -08003422 print("cls. functions", cls.functions)
Larry Hastings4a714d42014-01-14 22:22:41 -08003423 fail("Couldn't find existing function " + repr(existing) + "!")
3424
3425 fields = [x.strip() for x in full_name.split('.')]
3426 function_name = fields.pop()
3427 module, cls = self.clinic._module_and_class(fields)
3428
3429 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3430 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
Larry Hastings7726ac92014-01-31 22:03:12 -08003431 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 -08003432
3433 self.block.signatures.append(self.function)
3434 (cls or module).functions.append(self.function)
3435 self.next(self.state_function_docstring)
3436 return
3437
Larry Hastings31826802013-10-19 00:09:25 -07003438 line, _, returns = line.partition('->')
3439
3440 full_name, _, c_basename = line.partition(' as ')
3441 full_name = full_name.strip()
3442 c_basename = c_basename.strip() or None
3443
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003444 if not is_legal_py_identifier(full_name):
3445 fail("Illegal function name: {}".format(full_name))
3446 if c_basename and not is_legal_c_identifier(c_basename):
3447 fail("Illegal C basename: {}".format(c_basename))
3448
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003449 return_converter = None
3450 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003451 ast_input = "def x() -> {}: pass".format(returns)
3452 module = None
3453 try:
3454 module = ast.parse(ast_input)
3455 except SyntaxError:
3456 pass
3457 if not module:
3458 fail("Badly-formed annotation for " + full_name + ": " + returns)
3459 try:
3460 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003461 if legacy:
3462 fail("Legacy converter {!r} not allowed as a return converter"
3463 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003464 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003465 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003466 return_converter = return_converters[name](**kwargs)
3467 except ValueError:
3468 fail("Badly-formed annotation for " + full_name + ": " + returns)
3469
3470 fields = [x.strip() for x in full_name.split('.')]
3471 function_name = fields.pop()
3472 module, cls = self.clinic._module_and_class(fields)
3473
Larry Hastings8666e652014-01-12 14:12:59 -08003474 fields = full_name.split('.')
3475 if fields[-1] == '__new__':
3476 if (self.kind != CLASS_METHOD) or (not cls):
3477 fail("__new__ must be a class method!")
3478 self.kind = METHOD_NEW
3479 elif fields[-1] == '__init__':
3480 if (self.kind != CALLABLE) or (not cls):
3481 fail("__init__ must be a normal method, not a class or static method!")
3482 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003483 if not return_converter:
3484 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003485 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003486 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003487
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003488 if not return_converter:
3489 return_converter = CReturnConverter()
3490
Larry Hastings31826802013-10-19 00:09:25 -07003491 if not module:
3492 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3493 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3494 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3495 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003496
3497 # insert a self converter automatically
Larry Hastingsc2047262014-01-25 20:43:29 -08003498 type, name = correct_name_for_self(self.function)
3499 kwargs = {}
3500 if cls and type == "PyObject *":
3501 kwargs['type'] = cls.typedef
Larry Hastings7726ac92014-01-31 22:03:12 -08003502 sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs)
Larry Hastings5c661892014-01-24 06:17:25 -08003503 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3504 self.function.parameters[sc.name] = p_self
3505
Larry Hastings4a714d42014-01-14 22:22:41 -08003506 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003507 self.next(self.state_parameters_start)
3508
3509 # Now entering the parameters section. The rules, formally stated:
3510 #
3511 # * All lines must be indented with spaces only.
3512 # * The first line must be a parameter declaration.
3513 # * The first line must be indented.
3514 # * This first line establishes the indent for parameters.
3515 # * We'll call this number of spaces P (for "parameter").
3516 # * Thenceforth:
3517 # * Lines indented with P spaces specify a parameter.
3518 # * Lines indented with > P spaces are docstrings for the previous
3519 # parameter.
3520 # * We'll call this number of spaces D (for "docstring").
3521 # * All subsequent lines indented with >= D spaces are stored as
3522 # part of the per-parameter docstring.
3523 # * All lines will have the first D spaces of the indent stripped
3524 # before they are stored.
3525 # * It's illegal to have a line starting with a number of spaces X
3526 # such that P < X < D.
3527 # * A line with < P spaces is the first line of the function
3528 # docstring, which ends processing for parameters and per-parameter
3529 # docstrings.
3530 # * The first line of the function docstring must be at the same
3531 # indent as the function declaration.
3532 # * It's illegal to have any line in the parameters section starting
3533 # with X spaces such that F < X < P. (As before, F is the indent
3534 # of the function declaration.)
3535 #
Larry Hastings31826802013-10-19 00:09:25 -07003536 # Also, currently Argument Clinic places the following restrictions on groups:
3537 # * Each group must contain at least one parameter.
3538 # * Each group may contain at most one group, which must be the furthest
3539 # thing in the group from the required parameters. (The nested group
3540 # must be the first in the group when it's before the required
3541 # parameters, and the last thing in the group when after the required
3542 # parameters.)
3543 # * There may be at most one (top-level) group to the left or right of
3544 # the required parameters.
3545 # * You must specify a slash, and it must be after all parameters.
3546 # (In other words: either all parameters are positional-only,
3547 # or none are.)
3548 #
3549 # Said another way:
3550 # * Each group must contain at least one parameter.
3551 # * All left square brackets before the required parameters must be
3552 # consecutive. (You can't have a left square bracket followed
3553 # by a parameter, then another left square bracket. You can't
3554 # have a left square bracket, a parameter, a right square bracket,
3555 # and then a left square bracket.)
3556 # * All right square brackets after the required parameters must be
3557 # consecutive.
3558 #
3559 # These rules are enforced with a single state variable:
3560 # "parameter_state". (Previously the code was a miasma of ifs and
3561 # separate boolean state variables.) The states are:
3562 #
Larry Hastingsc2047262014-01-25 20:43:29 -08003563 # [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ] / <- line
3564 # 01 2 3 4 5 6 7 <- state transitions
Larry Hastings31826802013-10-19 00:09:25 -07003565 #
3566 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3567 # 1: ps_left_square_before. left square brackets before required parameters.
3568 # 2: ps_group_before. in a group, before required parameters.
Larry Hastingsc2047262014-01-25 20:43:29 -08003569 # 3: ps_required. required parameters, positional-or-keyword or positional-only
3570 # (we don't know yet). (renumber left groups!)
3571 # 4: ps_optional. positional-or-keyword or positional-only parameters that
3572 # now must have default values.
3573 # 5: ps_group_after. in a group, after required parameters.
3574 # 6: ps_right_square_after. right square brackets after required parameters.
3575 # 7: ps_seen_slash. seen slash.
Larry Hastings31826802013-10-19 00:09:25 -07003576 ps_start, ps_left_square_before, ps_group_before, ps_required, \
Larry Hastingsc2047262014-01-25 20:43:29 -08003577 ps_optional, ps_group_after, ps_right_square_after, ps_seen_slash = range(8)
Larry Hastings31826802013-10-19 00:09:25 -07003578
3579 def state_parameters_start(self, line):
3580 if self.ignore_line(line):
3581 return
3582
3583 # if this line is not indented, we have no parameters
3584 if not self.indent.infer(line):
3585 return self.next(self.state_function_docstring, line)
3586
Larry Hastings2a727912014-01-16 11:32:01 -08003587 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003588 return self.next(self.state_parameter, line)
3589
3590
3591 def to_required(self):
3592 """
3593 Transition to the "required" parameter state.
3594 """
3595 if self.parameter_state != self.ps_required:
3596 self.parameter_state = self.ps_required
3597 for p in self.function.parameters.values():
3598 p.group = -p.group
3599
3600 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003601 if self.parameter_continuation:
3602 line = self.parameter_continuation + ' ' + line.lstrip()
3603 self.parameter_continuation = ''
3604
Larry Hastings31826802013-10-19 00:09:25 -07003605 if self.ignore_line(line):
3606 return
3607
3608 assert self.indent.depth == 2
3609 indent = self.indent.infer(line)
3610 if indent == -1:
3611 # we outdented, must be to definition column
3612 return self.next(self.state_function_docstring, line)
3613
3614 if indent == 1:
3615 # we indented, must be to new parameter docstring column
3616 return self.next(self.state_parameter_docstring_start, line)
3617
Larry Hastings2a727912014-01-16 11:32:01 -08003618 line = line.rstrip()
3619 if line.endswith('\\'):
3620 self.parameter_continuation = line[:-1]
3621 return
3622
Larry Hastings31826802013-10-19 00:09:25 -07003623 line = line.lstrip()
3624
3625 if line in ('*', '/', '[', ']'):
3626 self.parse_special_symbol(line)
3627 return
3628
3629 if self.parameter_state in (self.ps_start, self.ps_required):
3630 self.to_required()
3631 elif self.parameter_state == self.ps_left_square_before:
3632 self.parameter_state = self.ps_group_before
3633 elif self.parameter_state == self.ps_group_before:
3634 if not self.group:
3635 self.to_required()
Larry Hastingsc2047262014-01-25 20:43:29 -08003636 elif self.parameter_state in (self.ps_group_after, self.ps_optional):
Larry Hastings31826802013-10-19 00:09:25 -07003637 pass
3638 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003639 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
Larry Hastings31826802013-10-19 00:09:25 -07003640
Larry Hastings7726ac92014-01-31 22:03:12 -08003641 # handle "as" for parameters too
3642 c_name = None
3643 name, have_as_token, trailing = line.partition(' as ')
3644 if have_as_token:
3645 name = name.strip()
3646 if ' ' not in name:
3647 fields = trailing.strip().split(' ')
3648 if not fields:
3649 fail("Invalid 'as' clause!")
3650 c_name = fields[0]
3651 if c_name.endswith(':'):
3652 name += ':'
3653 c_name = c_name[:-1]
3654 fields[0] = name
3655 line = ' '.join(fields)
3656
Larry Hastings2a727912014-01-16 11:32:01 -08003657 base, equals, default = line.rpartition('=')
3658 if not equals:
3659 base = default
3660 default = None
Larry Hastingsc2047262014-01-25 20:43:29 -08003661
Larry Hastings31826802013-10-19 00:09:25 -07003662 module = None
3663 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003664 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003665 module = ast.parse(ast_input)
3666 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003667 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08003668 # the last = was probably inside a function call, like
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003669 # c: int(accept={str})
Larry Hastingsc2047262014-01-25 20:43:29 -08003670 # so assume there was no actual default value.
Larry Hastings2a727912014-01-16 11:32:01 -08003671 default = None
3672 ast_input = "def x({}): pass".format(line)
3673 module = ast.parse(ast_input)
3674 except SyntaxError:
3675 pass
Larry Hastings31826802013-10-19 00:09:25 -07003676 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003677 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003678
3679 function_args = module.body[0].args
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003680
3681 if len(function_args.args) > 1:
3682 fail("Function " + self.function.name + " has an invalid parameter declaration (comma?):\n\t" + line)
3683 if function_args.defaults or function_args.kw_defaults:
3684 fail("Function " + self.function.name + " has an invalid parameter declaration (default value?):\n\t" + line)
3685 if function_args.vararg or function_args.kwarg:
3686 fail("Function " + self.function.name + " has an invalid parameter declaration (*args? **kwargs?):\n\t" + line)
3687
Larry Hastings31826802013-10-19 00:09:25 -07003688 parameter = function_args.args[0]
3689
Larry Hastings16c51912014-01-07 11:53:01 -08003690 parameter_name = parameter.arg
3691 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3692
Larry Hastings2a727912014-01-16 11:32:01 -08003693 if not default:
Larry Hastingsc2047262014-01-25 20:43:29 -08003694 if self.parameter_state == self.ps_optional:
3695 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 -08003696 value = unspecified
3697 if 'py_default' in kwargs:
3698 fail("You can't specify py_default without specifying a default value!")
3699 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003700 if self.parameter_state == self.ps_required:
3701 self.parameter_state = self.ps_optional
Larry Hastings2a727912014-01-16 11:32:01 -08003702 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003703 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003704 ast_input = "x = {}".format(default)
Larry Hastingsc2047262014-01-25 20:43:29 -08003705 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003706 try:
3707 module = ast.parse(ast_input)
3708
Larry Hastings5c661892014-01-24 06:17:25 -08003709 if 'c_default' not in kwargs:
3710 # we can only represent very simple data values in C.
3711 # detect whether default is okay, via a blacklist
3712 # of disallowed ast nodes.
3713 class DetectBadNodes(ast.NodeVisitor):
3714 bad = False
3715 def bad_node(self, node):
3716 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003717
Larry Hastings5c661892014-01-24 06:17:25 -08003718 # inline function call
3719 visit_Call = bad_node
3720 # inline if statement ("x = 3 if y else z")
3721 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003722
Larry Hastings5c661892014-01-24 06:17:25 -08003723 # comprehensions and generator expressions
3724 visit_ListComp = visit_SetComp = bad_node
3725 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003726
Larry Hastings5c661892014-01-24 06:17:25 -08003727 # literals for advanced types
3728 visit_Dict = visit_Set = bad_node
3729 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003730
Larry Hastings5c661892014-01-24 06:17:25 -08003731 # "starred": "a = [1, 2, 3]; *a"
3732 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003733
Larry Hastings5c661892014-01-24 06:17:25 -08003734 # allow ellipsis, for now
3735 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003736
Larry Hastings5c661892014-01-24 06:17:25 -08003737 blacklist = DetectBadNodes()
3738 blacklist.visit(module)
3739 bad = blacklist.bad
3740 else:
3741 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003742 # but at least make an attempt at ensuring it's a valid expression.
3743 try:
3744 value = eval(default)
3745 if value == unspecified:
3746 fail("'unspecified' is not a legal default value!")
3747 except NameError:
3748 pass # probably a named constant
3749 except Exception as e:
3750 fail("Malformed expression given as default value\n"
3751 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003752 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003753 fail("Unsupported expression as default value: " + repr(default))
3754
3755 expr = module.body[0].value
3756 # mild hack: explicitly support NULL as a default value
3757 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3758 value = NULL
3759 py_default = 'None'
3760 c_default = "NULL"
3761 elif (isinstance(expr, ast.BinOp) or
3762 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3763 c_default = kwargs.get("c_default")
3764 if not (isinstance(c_default, str) and c_default):
3765 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3766 py_default = default
3767 value = unknown
3768 elif isinstance(expr, ast.Attribute):
3769 a = []
3770 n = expr
3771 while isinstance(n, ast.Attribute):
3772 a.append(n.attr)
3773 n = n.value
3774 if not isinstance(n, ast.Name):
3775 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3776 a.append(n.id)
3777 py_default = ".".join(reversed(a))
3778
3779 c_default = kwargs.get("c_default")
3780 if not (isinstance(c_default, str) and c_default):
3781 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3782
3783 try:
3784 value = eval(py_default)
3785 except NameError:
3786 value = unknown
3787 else:
3788 value = ast.literal_eval(expr)
3789 py_default = repr(value)
3790 if isinstance(value, (bool, None.__class__)):
3791 c_default = "Py_" + py_default
3792 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003793 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003794 else:
3795 c_default = py_default
3796
3797 except SyntaxError as e:
3798 fail("Syntax error: " + repr(e.text))
3799 except (ValueError, AttributeError):
3800 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003801 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003802 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003803 if not (isinstance(c_default, str) and c_default):
3804 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3805
Larry Hastings2a727912014-01-16 11:32:01 -08003806 kwargs.setdefault('c_default', c_default)
3807 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003808
Larry Hastings31826802013-10-19 00:09:25 -07003809 dict = legacy_converters if legacy else converters
3810 legacy_str = "legacy " if legacy else ""
3811 if name not in dict:
3812 fail('{} is not a valid {}converter'.format(name, legacy_str))
Larry Hastings7726ac92014-01-31 22:03:12 -08003813 # if you use a c_name for the parameter, we just give that name to the converter
3814 # but the parameter object gets the python name
3815 converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
Larry Hastings31826802013-10-19 00:09:25 -07003816
3817 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003818
3819 if isinstance(converter, self_converter):
3820 if len(self.function.parameters) == 1:
3821 if (self.parameter_state != self.ps_required):
3822 fail("A 'self' parameter cannot be marked optional.")
3823 if value is not unspecified:
3824 fail("A 'self' parameter cannot have a default value.")
3825 if self.group:
3826 fail("A 'self' parameter cannot be in an optional group.")
3827 kind = inspect.Parameter.POSITIONAL_ONLY
3828 self.parameter_state = self.ps_start
3829 self.function.parameters.clear()
3830 else:
3831 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3832
Larry Hastings31826802013-10-19 00:09:25 -07003833 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003834
3835 if parameter_name in self.function.parameters:
3836 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003837 self.function.parameters[parameter_name] = p
3838
3839 def parse_converter(self, annotation):
3840 if isinstance(annotation, ast.Str):
3841 return annotation.s, True, {}
3842
3843 if isinstance(annotation, ast.Name):
3844 return annotation.id, False, {}
3845
Larry Hastings4a55fc52014-01-12 11:09:57 -08003846 if not isinstance(annotation, ast.Call):
3847 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003848
3849 name = annotation.func.id
Larry Hastingsdbfdc382015-05-04 06:59:46 -07003850 symbols = globals()
3851
3852 kwargs = {node.arg: eval_ast_expr(node.value, symbols) for node in annotation.keywords}
Larry Hastings31826802013-10-19 00:09:25 -07003853 return name, False, kwargs
3854
3855 def parse_special_symbol(self, symbol):
3856 if self.parameter_state == self.ps_seen_slash:
3857 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3858
3859 if symbol == '*':
3860 if self.keyword_only:
3861 fail("Function " + self.function.name + " uses '*' more than once.")
3862 self.keyword_only = True
3863 elif symbol == '[':
3864 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3865 self.parameter_state = self.ps_left_square_before
3866 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3867 self.parameter_state = self.ps_group_after
3868 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003869 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
Larry Hastings31826802013-10-19 00:09:25 -07003870 self.group += 1
Larry Hastings2623c8c2014-02-08 22:15:29 -08003871 self.function.docstring_only = True
Larry Hastings31826802013-10-19 00:09:25 -07003872 elif symbol == ']':
3873 if not self.group:
3874 fail("Function " + self.function.name + " has a ] without a matching [.")
3875 if not any(p.group == self.group for p in self.function.parameters.values()):
3876 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3877 self.group -= 1
3878 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3879 self.parameter_state = self.ps_group_before
3880 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3881 self.parameter_state = self.ps_right_square_after
3882 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003883 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
Larry Hastings31826802013-10-19 00:09:25 -07003884 elif symbol == '/':
Larry Hastingsc2047262014-01-25 20:43:29 -08003885 # ps_required and ps_optional are allowed here, that allows positional-only without option groups
Larry Hastings31826802013-10-19 00:09:25 -07003886 # to work (and have default values!)
Larry Hastingsc2047262014-01-25 20:43:29 -08003887 if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
3888 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
Larry Hastings31826802013-10-19 00:09:25 -07003889 if self.keyword_only:
3890 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3891 self.parameter_state = self.ps_seen_slash
Berker Peksagf23530f2014-10-19 18:04:38 +03003892 # fixup preceding parameters
Larry Hastings31826802013-10-19 00:09:25 -07003893 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003894 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003895 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3896 p.kind = inspect.Parameter.POSITIONAL_ONLY
3897
3898 def state_parameter_docstring_start(self, line):
3899 self.parameter_docstring_indent = len(self.indent.margin)
3900 assert self.indent.depth == 3
3901 return self.next(self.state_parameter_docstring, line)
3902
3903 # every line of the docstring must start with at least F spaces,
3904 # where F > P.
3905 # these F spaces will be stripped.
3906 def state_parameter_docstring(self, line):
3907 stripped = line.strip()
3908 if stripped.startswith('#'):
3909 return
3910
3911 indent = self.indent.measure(line)
3912 if indent < self.parameter_docstring_indent:
3913 self.indent.infer(line)
3914 assert self.indent.depth < 3
3915 if self.indent.depth == 2:
3916 # back to a parameter
3917 return self.next(self.state_parameter, line)
3918 assert self.indent.depth == 1
3919 return self.next(self.state_function_docstring, line)
3920
3921 assert self.function.parameters
3922 last_parameter = next(reversed(list(self.function.parameters.values())))
3923
3924 new_docstring = last_parameter.docstring
3925
3926 if new_docstring:
3927 new_docstring += '\n'
3928 if stripped:
3929 new_docstring += self.indent.dedent(line)
3930
3931 last_parameter.docstring = new_docstring
3932
3933 # the final stanza of the DSL is the docstring.
3934 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003935 if self.group:
3936 fail("Function " + self.function.name + " has a ] without a matching [.")
3937
3938 stripped = line.strip()
3939 if stripped.startswith('#'):
3940 return
3941
3942 new_docstring = self.function.docstring
3943 if new_docstring:
3944 new_docstring += "\n"
3945 if stripped:
3946 line = self.indent.dedent(line).rstrip()
3947 else:
3948 line = ''
3949 new_docstring += line
3950 self.function.docstring = new_docstring
3951
3952 def format_docstring(self):
3953 f = self.function
3954
Larry Hastings5c661892014-01-24 06:17:25 -08003955 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3956 if new_or_init and not f.docstring:
3957 # don't render a docstring at all, no signature, nothing.
3958 return f.docstring
3959
Larry Hastings2623c8c2014-02-08 22:15:29 -08003960 text, add, output = _text_accumulator()
Larry Hastings7726ac92014-01-31 22:03:12 -08003961 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07003962
3963 ##
3964 ## docstring first line
3965 ##
3966
Larry Hastings2623c8c2014-02-08 22:15:29 -08003967 if new_or_init:
3968 # classes get *just* the name of the class
3969 # not __new__, not __init__, and not module.classname
3970 assert f.cls
3971 add(f.cls.name)
Larry Hastings46258262014-01-22 03:05:49 -08003972 else:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003973 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003974 add('(')
3975
3976 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003977 assert parameters, "We should always have a self parameter. " + repr(f)
3978 assert isinstance(parameters[0].converter, self_converter)
3979 parameters[0].right_bracket_count = 0
3980 parameters_after_self = parameters[1:]
3981 if parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003982 # for now, the only way Clinic supports positional-only parameters
Larry Hastings5c661892014-01-24 06:17:25 -08003983 # is if all of them are positional-only...
3984 #
3985 # ... except for self! self is always positional-only.
3986
3987 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters_after_self]
3988 if parameters_after_self[0].kind == inspect.Parameter.POSITIONAL_ONLY:
Larry Hastings31826802013-10-19 00:09:25 -07003989 assert all(positional_only_parameters)
3990 for p in parameters:
3991 p.right_bracket_count = abs(p.group)
3992 else:
3993 # don't put any right brackets around non-positional-only parameters, ever.
Larry Hastings5c661892014-01-24 06:17:25 -08003994 for p in parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003995 p.right_bracket_count = 0
3996
3997 right_bracket_count = 0
3998
3999 def fix_right_bracket_count(desired):
4000 nonlocal right_bracket_count
4001 s = ''
4002 while right_bracket_count < desired:
4003 s += '['
4004 right_bracket_count += 1
4005 while right_bracket_count > desired:
4006 s += ']'
4007 right_bracket_count -= 1
4008 return s
4009
Larry Hastings2623c8c2014-02-08 22:15:29 -08004010 need_slash = False
4011 added_slash = False
4012 need_a_trailing_slash = False
4013
4014 # we only need a trailing slash:
4015 # * if this is not a "docstring_only" signature
4016 # * and if the last *shown* parameter is
4017 # positional only
4018 if not f.docstring_only:
4019 for p in reversed(parameters):
4020 if not p.converter.show_in_signature:
4021 continue
4022 if p.is_positional_only():
4023 need_a_trailing_slash = True
4024 break
4025
4026
Larry Hastings31826802013-10-19 00:09:25 -07004027 added_star = False
Larry Hastings2623c8c2014-02-08 22:15:29 -08004028
4029 first_parameter = True
4030 last_p = parameters[-1]
4031 line_length = len(''.join(text))
4032 indent = " " * line_length
4033 def add_parameter(text):
4034 nonlocal line_length
4035 nonlocal first_parameter
4036 if first_parameter:
4037 s = text
4038 first_parameter = False
4039 else:
4040 s = ' ' + text
4041 if line_length + len(s) >= 72:
4042 add('\n')
4043 add(indent)
4044 line_length = len(indent)
4045 s = text
4046 line_length += len(s)
4047 add(s)
Larry Hastings31826802013-10-19 00:09:25 -07004048
4049 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08004050 if not p.converter.show_in_signature:
4051 continue
Larry Hastings31826802013-10-19 00:09:25 -07004052 assert p.name
4053
Larry Hastings2623c8c2014-02-08 22:15:29 -08004054 is_self = isinstance(p.converter, self_converter)
4055 if is_self and f.docstring_only:
4056 # this isn't a real machine-parsable signature,
4057 # so let's not print the "self" parameter
4058 continue
4059
4060 if p.is_positional_only():
4061 need_slash = not f.docstring_only
4062 elif need_slash and not (added_slash or p.is_positional_only()):
4063 added_slash = True
4064 add_parameter('/,')
4065
Larry Hastings31826802013-10-19 00:09:25 -07004066 if p.is_keyword_only() and not added_star:
4067 added_star = True
Larry Hastings2623c8c2014-02-08 22:15:29 -08004068 add_parameter('*,')
4069
4070 p_add, p_output = text_accumulator()
4071 p_add(fix_right_bracket_count(p.right_bracket_count))
4072
4073 if isinstance(p.converter, self_converter):
4074 # annotate first parameter as being a "self".
4075 #
4076 # if inspect.Signature gets this function,
4077 # and it's already bound, the self parameter
4078 # will be stripped off.
4079 #
4080 # if it's not bound, it should be marked
4081 # as positional-only.
4082 #
4083 # note: we don't print "self" for __init__,
4084 # because this isn't actually the signature
4085 # for __init__. (it can't be, __init__ doesn't
4086 # have a docstring.) if this is an __init__
4087 # (or __new__), then this signature is for
Berker Peksagf23530f2014-10-19 18:04:38 +03004088 # calling the class to construct a new instance.
Larry Hastings2623c8c2014-02-08 22:15:29 -08004089 p_add('$')
Larry Hastings31826802013-10-19 00:09:25 -07004090
Larry Hastings5c661892014-01-24 06:17:25 -08004091 name = p.converter.signature_name or p.name
Larry Hastings2623c8c2014-02-08 22:15:29 -08004092 p_add(name)
Larry Hastings581ee362014-01-28 05:00:08 -08004093
Larry Hastings31826802013-10-19 00:09:25 -07004094 if p.converter.is_optional():
Larry Hastings2623c8c2014-02-08 22:15:29 -08004095 p_add('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08004096 value = p.converter.py_default
4097 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08004098 value = repr(p.converter.default)
Larry Hastings2623c8c2014-02-08 22:15:29 -08004099 p_add(value)
4100
4101 if (p != last_p) or need_a_trailing_slash:
4102 p_add(',')
4103
4104 add_parameter(p_output())
Larry Hastings31826802013-10-19 00:09:25 -07004105
4106 add(fix_right_bracket_count(0))
Larry Hastings2623c8c2014-02-08 22:15:29 -08004107 if need_a_trailing_slash:
4108 add_parameter('/')
Larry Hastings31826802013-10-19 00:09:25 -07004109 add(')')
4110
Larry Hastings2a727912014-01-16 11:32:01 -08004111 # PEP 8 says:
4112 #
4113 # The Python standard library will not use function annotations
4114 # as that would result in a premature commitment to a particular
4115 # annotation style. Instead, the annotations are left for users
4116 # to discover and experiment with useful annotation styles.
4117 #
4118 # therefore this is commented out:
4119 #
4120 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004121 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08004122 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07004123
Larry Hastings2623c8c2014-02-08 22:15:29 -08004124 if not f.docstring_only:
Zachary Ware8ef887c2015-04-13 18:22:35 -05004125 add("\n" + sig_end_marker + "\n")
Larry Hastings2623c8c2014-02-08 22:15:29 -08004126
Larry Hastings31826802013-10-19 00:09:25 -07004127 docstring_first_line = output()
4128
4129 # now fix up the places where the brackets look wrong
4130 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
4131
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004132 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07004133 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004134 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07004135 for p in parameters:
4136 if not p.docstring.strip():
4137 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004138 if spacer_line:
4139 add('\n')
4140 else:
4141 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07004142 add(" ")
4143 add(p.name)
4144 add('\n')
4145 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004146 parameters = output()
4147 if parameters:
4148 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07004149
4150 ##
4151 ## docstring body
4152 ##
4153
4154 docstring = f.docstring.rstrip()
4155 lines = [line.rstrip() for line in docstring.split('\n')]
4156
4157 # Enforce the summary line!
4158 # The first line of a docstring should be a summary of the function.
4159 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
4160 # by itself.
4161 #
4162 # Argument Clinic enforces the following rule:
4163 # * either the docstring is empty,
4164 # * or it must have a summary line.
4165 #
4166 # Guido said Clinic should enforce this:
4167 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
4168
4169 if len(lines) >= 2:
4170 if lines[1]:
4171 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
4172 "Every non-blank function docstring must start with\n" +
4173 "a single line summary followed by an empty line.")
4174 elif len(lines) == 1:
4175 # the docstring is only one line right now--the summary line.
4176 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004177 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07004178 lines.append('')
4179
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004180 parameters_marker_count = len(docstring.split('{parameters}')) - 1
4181 if parameters_marker_count > 1:
4182 fail('You may not specify {parameters} more than once in a docstring!')
4183
4184 if not parameters_marker_count:
4185 # insert after summary line
4186 lines.insert(2, '{parameters}')
4187
4188 # insert at front of docstring
4189 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07004190
4191 docstring = "\n".join(lines)
4192
4193 add(docstring)
4194 docstring = output()
4195
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004196 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07004197 docstring = docstring.rstrip()
4198
4199 return docstring
4200
4201 def state_terminal(self, line):
4202 """
4203 Called when processing the block is done.
4204 """
4205 assert not line
4206
4207 if not self.function:
4208 return
4209
4210 if self.keyword_only:
4211 values = self.function.parameters.values()
4212 if not values:
4213 no_parameter_after_star = True
4214 else:
4215 last_parameter = next(reversed(list(values)))
4216 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
4217 if no_parameter_after_star:
4218 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
4219
4220 # remove trailing whitespace from all parameter docstrings
4221 for name, value in self.function.parameters.items():
4222 if not value:
4223 continue
4224 value.docstring = value.docstring.rstrip()
4225
4226 self.function.docstring = self.format_docstring()
4227
4228
Larry Hastings5c661892014-01-24 06:17:25 -08004229
4230
Larry Hastings31826802013-10-19 00:09:25 -07004231# maps strings to callables.
4232# the callable should return an object
4233# that implements the clinic parser
4234# interface (__init__ and parse).
4235#
4236# example parsers:
4237# "clinic", handles the Clinic DSL
4238# "python", handles running Python code
4239#
4240parsers = {'clinic' : DSLParser, 'python': PythonParser}
4241
4242
4243clinic = None
4244
4245
4246def main(argv):
4247 import sys
4248
4249 if sys.version_info.major < 3 or sys.version_info.minor < 3:
4250 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
4251
4252 import argparse
4253 cmdline = argparse.ArgumentParser()
4254 cmdline.add_argument("-f", "--force", action='store_true')
4255 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08004256 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004257 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004258 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004259 cmdline.add_argument("filename", type=str, nargs="*")
4260 ns = cmdline.parse_args(argv)
4261
4262 if ns.converters:
4263 if ns.filename:
4264 print("Usage error: can't specify --converters and a filename at the same time.")
4265 print()
4266 cmdline.print_usage()
4267 sys.exit(-1)
4268 converters = []
4269 return_converters = []
4270 ignored = set("""
4271 add_c_converter
4272 add_c_return_converter
4273 add_default_legacy_c_converter
4274 add_legacy_c_converter
4275 """.strip().split())
4276 module = globals()
4277 for name in module:
4278 for suffix, ids in (
4279 ("_return_converter", return_converters),
4280 ("_converter", converters),
4281 ):
4282 if name in ignored:
4283 continue
4284 if name.endswith(suffix):
4285 ids.append((name, name[:-len(suffix)]))
4286 break
4287 print()
4288
4289 print("Legacy converters:")
4290 legacy = sorted(legacy_converters)
4291 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
4292 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
4293 print()
4294
4295 for title, attribute, ids in (
4296 ("Converters", 'converter_init', converters),
4297 ("Return converters", 'return_converter_init', return_converters),
4298 ):
4299 print(title + ":")
4300 longest = -1
4301 for name, short_name in ids:
4302 longest = max(longest, len(short_name))
4303 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
4304 cls = module[name]
4305 callable = getattr(cls, attribute, None)
4306 if not callable:
4307 continue
4308 signature = inspect.signature(callable)
4309 parameters = []
4310 for parameter_name, parameter in signature.parameters.items():
4311 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
4312 if parameter.default != inspect.Parameter.empty:
4313 s = '{}={!r}'.format(parameter_name, parameter.default)
4314 else:
4315 s = parameter_name
4316 parameters.append(s)
4317 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07004318 print()
Larry Hastings2a727912014-01-16 11:32:01 -08004319 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
4320 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07004321 sys.exit(0)
4322
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004323 if ns.make:
4324 if ns.output or ns.filename:
4325 print("Usage error: can't use -o or filenames with --make.")
4326 print()
4327 cmdline.print_usage()
4328 sys.exit(-1)
4329 for root, dirs, files in os.walk('.'):
Zachary Warebbbbe7e2015-04-13 18:33:41 -05004330 for rcs_dir in ('.svn', '.git', '.hg', 'build', 'externals'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004331 if rcs_dir in dirs:
4332 dirs.remove(rcs_dir)
4333 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08004334 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004335 continue
4336 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08004337 if ns.verbose:
4338 print(path)
Larry Hastings581ee362014-01-28 05:00:08 -08004339 parse_file(path, force=ns.force, verify=not ns.force)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004340 return
4341
Larry Hastings31826802013-10-19 00:09:25 -07004342 if not ns.filename:
4343 cmdline.print_usage()
4344 sys.exit(-1)
4345
4346 if ns.output and len(ns.filename) > 1:
4347 print("Usage error: can't use -o with multiple filenames.")
4348 print()
4349 cmdline.print_usage()
4350 sys.exit(-1)
4351
4352 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08004353 if ns.verbose:
4354 print(filename)
Larry Hastings581ee362014-01-28 05:00:08 -08004355 parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
Larry Hastings31826802013-10-19 00:09:25 -07004356
4357
4358if __name__ == "__main__":
4359 sys.exit(main(sys.argv[1:]))