blob: ee663e88d3fb0748ee92bf63238ed4a6c5ab8e62 [file] [log] [blame]
Larry Hastings31826802013-10-19 00:09:25 -07001#!/usr/bin/env python3
2#
3# Argument Clinic
4# Copyright 2012-2013 by Larry Hastings.
5# Licensed to the PSF under a contributor agreement.
6#
7
8import abc
9import ast
10import atexit
Larry Hastings31826802013-10-19 00:09:25 -070011import collections
12import contextlib
Larry Hastings7726ac92014-01-31 22:03:12 -080013import copy
14import cpp
Larry Hastings31826802013-10-19 00:09:25 -070015import functools
16import hashlib
17import inspect
18import io
19import itertools
20import os
Larry Hastingsbebf7352014-01-17 17:47:17 -080021import pprint
Larry Hastings31826802013-10-19 00:09:25 -070022import re
23import shlex
Larry Hastings581ee362014-01-28 05:00:08 -080024import string
Larry Hastings31826802013-10-19 00:09:25 -070025import sys
26import tempfile
27import textwrap
Georg Brandlaabebde2014-01-16 06:53:54 +010028import traceback
Larry Hastingsbebf7352014-01-17 17:47:17 -080029import uuid
Larry Hastings31826802013-10-19 00:09:25 -070030
Larry Hastings31826802013-10-19 00:09:25 -070031# TODO:
Larry Hastings31826802013-10-19 00:09:25 -070032#
33# soon:
34#
35# * allow mixing any two of {positional-only, positional-or-keyword,
36# keyword-only}
37# * dict constructor uses positional-only and keyword-only
38# * max and min use positional only with an optional group
39# and keyword-only
40#
Larry Hastings31826802013-10-19 00:09:25 -070041
Larry Hastingsebdcb502013-11-23 14:54:00 -080042version = '1'
43
Larry Hastings31826802013-10-19 00:09:25 -070044_empty = inspect._empty
45_void = inspect._void
46
Larry Hastings4a55fc52014-01-12 11:09:57 -080047NoneType = type(None)
Larry Hastings31826802013-10-19 00:09:25 -070048
49class Unspecified:
50 def __repr__(self):
51 return '<Unspecified>'
52
53unspecified = Unspecified()
54
55
56class Null:
57 def __repr__(self):
58 return '<Null>'
59
60NULL = Null()
61
62
Larry Hastings2a727912014-01-16 11:32:01 -080063class Unknown:
64 def __repr__(self):
65 return '<Unknown>'
66
67unknown = Unknown()
68
69
Larry Hastings31826802013-10-19 00:09:25 -070070def _text_accumulator():
71 text = []
72 def output():
73 s = ''.join(text)
74 text.clear()
75 return s
76 return text, text.append, output
77
78
79def text_accumulator():
80 """
81 Creates a simple text accumulator / joiner.
82
83 Returns a pair of callables:
84 append, output
85 "append" appends a string to the accumulator.
86 "output" returns the contents of the accumulator
87 joined together (''.join(accumulator)) and
88 empties the accumulator.
89 """
90 text, append, output = _text_accumulator()
91 return append, output
92
93
Larry Hastingsbebf7352014-01-17 17:47:17 -080094def warn_or_fail(fail=False, *args, filename=None, line_number=None):
Larry Hastings31826802013-10-19 00:09:25 -070095 joined = " ".join([str(a) for a in args])
96 add, output = text_accumulator()
Larry Hastingsbebf7352014-01-17 17:47:17 -080097 if fail:
98 add("Error")
99 else:
100 add("Warning")
Larry Hastings31826802013-10-19 00:09:25 -0700101 if clinic:
102 if filename is None:
103 filename = clinic.filename
Larry Hastings581ee362014-01-28 05:00:08 -0800104 if getattr(clinic, 'block_parser', None) and (line_number is None):
Larry Hastings31826802013-10-19 00:09:25 -0700105 line_number = clinic.block_parser.line_number
106 if filename is not None:
107 add(' in file "' + filename + '"')
108 if line_number is not None:
109 add(" on line " + str(line_number))
110 add(':\n')
111 add(joined)
112 print(output())
Larry Hastingsbebf7352014-01-17 17:47:17 -0800113 if fail:
114 sys.exit(-1)
Larry Hastings31826802013-10-19 00:09:25 -0700115
116
Larry Hastingsbebf7352014-01-17 17:47:17 -0800117def warn(*args, filename=None, line_number=None):
118 return warn_or_fail(False, *args, filename=filename, line_number=line_number)
119
120def fail(*args, filename=None, line_number=None):
121 return warn_or_fail(True, *args, filename=filename, line_number=line_number)
122
Larry Hastings31826802013-10-19 00:09:25 -0700123
124def quoted_for_c_string(s):
125 for old, new in (
Zachary Ware9d7849f2014-01-25 03:26:20 -0600126 ('\\', '\\\\'), # must be first!
Larry Hastings31826802013-10-19 00:09:25 -0700127 ('"', '\\"'),
128 ("'", "\\'"),
129 ):
130 s = s.replace(old, new)
131 return s
132
Larry Hastings4903e002014-01-18 00:26:16 -0800133def c_repr(s):
134 return '"' + s + '"'
135
136
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700137is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
138
139def is_legal_py_identifier(s):
140 return all(is_legal_c_identifier(field) for field in s.split('.'))
141
Larry Hastingsbebf7352014-01-17 17:47:17 -0800142# identifiers that are okay in Python but aren't a good idea in C.
143# so if they're used Argument Clinic will add "_value" to the end
144# of the name in C.
Larry Hastings31826802013-10-19 00:09:25 -0700145c_keywords = set("""
Larry Hastings5c661892014-01-24 06:17:25 -0800146asm auto break case char const continue default do double
147else enum extern float for goto if inline int long
148register return short signed sizeof static struct switch
Larry Hastingsbebf7352014-01-17 17:47:17 -0800149typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700150""".strip().split())
151
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700152def ensure_legal_c_identifier(s):
153 # for now, just complain if what we're given isn't legal
154 if not is_legal_c_identifier(s):
155 fail("Illegal C identifier: {}".format(s))
156 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700157 if s in c_keywords:
158 return s + "_value"
159 return s
160
161def rstrip_lines(s):
162 text, add, output = _text_accumulator()
163 for line in s.split('\n'):
164 add(line.rstrip())
165 add('\n')
166 text.pop()
167 return output()
168
169def linear_format(s, **kwargs):
170 """
171 Perform str.format-like substitution, except:
172 * The strings substituted must be on lines by
173 themselves. (This line is the "source line".)
174 * If the substitution text is empty, the source line
175 is removed in the output.
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800176 * If the field is not recognized, the original line
177 is passed unmodified through to the output.
Larry Hastings31826802013-10-19 00:09:25 -0700178 * If the substitution text is not empty:
179 * Each line of the substituted text is indented
180 by the indent of the source line.
181 * A newline will be added to the end.
182 """
183
184 add, output = text_accumulator()
185 for line in s.split('\n'):
186 indent, curly, trailing = line.partition('{')
187 if not curly:
188 add(line)
189 add('\n')
190 continue
191
192 name, curl, trailing = trailing.partition('}')
193 if not curly or name not in kwargs:
194 add(line)
195 add('\n')
196 continue
197
198 if trailing:
199 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
200 if indent.strip():
201 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
202
203 value = kwargs[name]
204 if not value:
205 continue
206
207 value = textwrap.indent(rstrip_lines(value), indent)
208 add(value)
209 add('\n')
210
211 return output()[:-1]
212
Larry Hastingsbebf7352014-01-17 17:47:17 -0800213def indent_all_lines(s, prefix):
214 """
215 Returns 's', with 'prefix' prepended to all lines.
216
217 If the last line is empty, prefix is not prepended
218 to it. (If s is blank, returns s unchanged.)
219
220 (textwrap.indent only adds to non-blank lines.)
221 """
222 split = s.split('\n')
223 last = split.pop()
224 final = []
225 for line in split:
226 final.append(prefix)
227 final.append(line)
228 final.append('\n')
229 if last:
230 final.append(prefix)
231 final.append(last)
232 return ''.join(final)
233
234def suffix_all_lines(s, suffix):
235 """
236 Returns 's', with 'suffix' appended to all lines.
237
238 If the last line is empty, suffix is not appended
239 to it. (If s is blank, returns s unchanged.)
240 """
241 split = s.split('\n')
242 last = split.pop()
243 final = []
244 for line in split:
245 final.append(line)
246 final.append(suffix)
247 final.append('\n')
248 if last:
249 final.append(last)
250 final.append(suffix)
251 return ''.join(final)
252
253
Larry Hastingsebdcb502013-11-23 14:54:00 -0800254def version_splitter(s):
255 """Splits a version string into a tuple of integers.
256
257 The following ASCII characters are allowed, and employ
258 the following conversions:
259 a -> -3
260 b -> -2
261 c -> -1
262 (This permits Python-style version strings such as "1.4b3".)
263 """
264 version = []
265 accumulator = []
266 def flush():
267 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800268 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800269 version.append(int(''.join(accumulator)))
270 accumulator.clear()
271
272 for c in s:
273 if c.isdigit():
274 accumulator.append(c)
275 elif c == '.':
276 flush()
277 elif c in 'abc':
278 flush()
279 version.append('abc'.index(c) - 3)
280 else:
281 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
282 flush()
283 return tuple(version)
284
285def version_comparitor(version1, version2):
286 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
287 for i, (a, b) in enumerate(iterator):
288 if a < b:
289 return -1
290 if a > b:
291 return 1
292 return 0
293
Larry Hastings31826802013-10-19 00:09:25 -0700294
295class CRenderData:
296 def __init__(self):
297
298 # The C statements to declare variables.
299 # Should be full lines with \n eol characters.
300 self.declarations = []
301
302 # The C statements required to initialize the variables before the parse call.
303 # Should be full lines with \n eol characters.
304 self.initializers = []
305
Larry Hastingsc2047262014-01-25 20:43:29 -0800306 # The C statements needed to dynamically modify the values
307 # parsed by the parse call, before calling the impl.
308 self.modifications = []
309
Larry Hastings31826802013-10-19 00:09:25 -0700310 # The entries for the "keywords" array for PyArg_ParseTuple.
311 # Should be individual strings representing the names.
312 self.keywords = []
313
314 # The "format units" for PyArg_ParseTuple.
315 # Should be individual strings that will get
316 self.format_units = []
317
318 # The varargs arguments for PyArg_ParseTuple.
319 self.parse_arguments = []
320
321 # The parameter declarations for the impl function.
322 self.impl_parameters = []
323
324 # The arguments to the impl function at the time it's called.
325 self.impl_arguments = []
326
327 # For return converters: the name of the variable that
328 # should receive the value returned by the impl.
329 self.return_value = "return_value"
330
331 # For return converters: the code to convert the return
332 # value from the parse function. This is also where
333 # you should check the _return_value for errors, and
334 # "goto exit" if there are any.
335 self.return_conversion = []
336
337 # The C statements required to clean up after the impl call.
338 self.cleanup = []
339
340
Larry Hastings581ee362014-01-28 05:00:08 -0800341class FormatCounterFormatter(string.Formatter):
342 """
343 This counts how many instances of each formatter
344 "replacement string" appear in the format string.
345
346 e.g. after evaluating "string {a}, {b}, {c}, {a}"
347 the counts dict would now look like
348 {'a': 2, 'b': 1, 'c': 1}
349 """
350 def __init__(self):
351 self.counts = collections.Counter()
352
353 def get_value(self, key, args, kwargs):
354 self.counts[key] += 1
355 return ''
356
Larry Hastings31826802013-10-19 00:09:25 -0700357class Language(metaclass=abc.ABCMeta):
358
359 start_line = ""
360 body_prefix = ""
361 stop_line = ""
362 checksum_line = ""
363
Larry Hastings7726ac92014-01-31 22:03:12 -0800364 def __init__(self, filename):
365 pass
366
Larry Hastings31826802013-10-19 00:09:25 -0700367 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800368 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700369 pass
370
Larry Hastings7726ac92014-01-31 22:03:12 -0800371 def parse_line(self, line):
372 pass
373
Larry Hastings31826802013-10-19 00:09:25 -0700374 def validate(self):
Larry Hastings581ee362014-01-28 05:00:08 -0800375 def assert_only_one(attr, *additional_fields):
376 """
377 Ensures that the string found at getattr(self, attr)
378 contains exactly one formatter replacement string for
379 each valid field. The list of valid fields is
380 ['dsl_name'] extended by additional_fields.
381
382 e.g.
383 self.fmt = "{dsl_name} {a} {b}"
384
385 # this passes
386 self.assert_only_one('fmt', 'a', 'b')
387
388 # this fails, the format string has a {b} in it
389 self.assert_only_one('fmt', 'a')
390
391 # this fails, the format string doesn't have a {c} in it
392 self.assert_only_one('fmt', 'a', 'b', 'c')
393
394 # this fails, the format string has two {a}s in it,
395 # it must contain exactly one
396 self.fmt2 = '{dsl_name} {a} {a}'
397 self.assert_only_one('fmt2', 'a')
398
399 """
400 fields = ['dsl_name']
401 fields.extend(additional_fields)
402 line = getattr(self, attr)
403 fcf = FormatCounterFormatter()
404 fcf.format(line)
405 def local_fail(should_be_there_but_isnt):
406 if should_be_there_but_isnt:
407 fail("{} {} must contain {{{}}} exactly once!".format(
408 self.__class__.__name__, attr, name))
409 else:
410 fail("{} {} must not contain {{{}}}!".format(
411 self.__class__.__name__, attr, name))
412
413 for name, count in fcf.counts.items():
414 if name in fields:
415 if count > 1:
416 local_fail(True)
417 else:
418 local_fail(False)
419 for name in fields:
420 if fcf.counts.get(name) != 1:
421 local_fail(True)
422
Larry Hastings31826802013-10-19 00:09:25 -0700423 assert_only_one('start_line')
424 assert_only_one('stop_line')
Larry Hastings31826802013-10-19 00:09:25 -0700425
Larry Hastings581ee362014-01-28 05:00:08 -0800426 field = "arguments" if "{arguments}" in self.checksum_line else "checksum"
427 assert_only_one('checksum_line', field)
Larry Hastings31826802013-10-19 00:09:25 -0700428
429
430
431class PythonLanguage(Language):
432
433 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800434 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700435 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800436 stop_line = "#[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800437 checksum_line = "#/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700438
439
440def permute_left_option_groups(l):
441 """
442 Given [1, 2, 3], should yield:
443 ()
444 (3,)
445 (2, 3)
446 (1, 2, 3)
447 """
448 yield tuple()
449 accumulator = []
450 for group in reversed(l):
451 accumulator = list(group) + accumulator
452 yield tuple(accumulator)
453
454
455def permute_right_option_groups(l):
456 """
457 Given [1, 2, 3], should yield:
458 ()
459 (1,)
460 (1, 2)
461 (1, 2, 3)
462 """
463 yield tuple()
464 accumulator = []
465 for group in l:
466 accumulator.extend(group)
467 yield tuple(accumulator)
468
469
470def permute_optional_groups(left, required, right):
471 """
472 Generator function that computes the set of acceptable
473 argument lists for the provided iterables of
474 argument groups. (Actually it generates a tuple of tuples.)
475
476 Algorithm: prefer left options over right options.
477
478 If required is empty, left must also be empty.
479 """
480 required = tuple(required)
481 result = []
482
483 if not required:
484 assert not left
485
486 accumulator = []
487 counts = set()
488 for r in permute_right_option_groups(right):
489 for l in permute_left_option_groups(left):
490 t = l + required + r
491 if len(t) in counts:
492 continue
493 counts.add(len(t))
494 accumulator.append(t)
495
496 accumulator.sort(key=len)
497 return tuple(accumulator)
498
499
Larry Hastings7726ac92014-01-31 22:03:12 -0800500def strip_leading_and_trailing_blank_lines(s):
501 lines = s.rstrip().split('\n')
502 while lines:
503 line = lines[0]
504 if line.strip():
505 break
506 del lines[0]
507 return '\n'.join(lines)
508
509@functools.lru_cache()
510def normalize_snippet(s, *, indent=0):
511 """
512 Reformats s:
513 * removes leading and trailing blank lines
514 * ensures that it does not end with a newline
515 * dedents so the first nonwhite character on any line is at column "indent"
516 """
517 s = strip_leading_and_trailing_blank_lines(s)
518 s = textwrap.dedent(s)
519 if indent:
520 s = textwrap.indent(s, ' ' * indent)
521 return s
522
523
Larry Hastings31826802013-10-19 00:09:25 -0700524class CLanguage(Language):
525
Larry Hastings61272b72014-01-07 12:41:53 -0800526 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700527 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800528 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700529 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800530 stop_line = "[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800531 checksum_line = "/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700532
Larry Hastings7726ac92014-01-31 22:03:12 -0800533 def __init__(self, filename):
534 super().__init__(filename)
535 self.cpp = cpp.Monitor(filename)
536 self.cpp.fail = fail
537
538 def parse_line(self, line):
539 self.cpp.writeline(line)
540
Larry Hastingsbebf7352014-01-17 17:47:17 -0800541 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700542 function = None
543 for o in signatures:
544 if isinstance(o, Function):
545 if function:
546 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
547 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800548 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700549
550 def docstring_for_c_string(self, f):
551 text, add, output = _text_accumulator()
552 # turn docstring into a properly quoted C string
553 for line in f.docstring.split('\n'):
554 add('"')
555 add(quoted_for_c_string(line))
556 add('\\n"\n')
557
558 text.pop()
559 add('"')
560 return ''.join(text)
561
Larry Hastingsbebf7352014-01-17 17:47:17 -0800562 def output_templates(self, f):
563 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800564 assert parameters
565 assert isinstance(parameters[0].converter, self_converter)
566 del parameters[0]
Larry Hastingsbebf7352014-01-17 17:47:17 -0800567 converters = [p.converter for p in parameters]
568
569 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
570 default_return_converter = (not f.return_converter or
571 f.return_converter.type == 'PyObject *')
572
573 positional = parameters and (parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY)
574 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
575 first_optional = len(parameters)
576 for i, p in enumerate(parameters):
577 c = p.converter
578 if type(c) != object_converter:
579 break
580 if c.format_unit != 'O':
581 break
582 if p.default is not unspecified:
583 first_optional = min(first_optional, i)
584 else:
585 all_boring_objects = True
586
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800587 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
588
Larry Hastingsbebf7352014-01-17 17:47:17 -0800589 meth_o = (len(parameters) == 1 and
590 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
591 not converters[0].is_optional() and
592 isinstance(converters[0], object_converter) and
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800593 converters[0].format_unit == 'O' and
594 not new_or_init)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800595
Larry Hastings7726ac92014-01-31 22:03:12 -0800596 # we have to set these things before we're done:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800597 #
598 # docstring_prototype
599 # docstring_definition
600 # impl_prototype
601 # methoddef_define
602 # parser_prototype
603 # parser_definition
604 # impl_definition
Larry Hastings7726ac92014-01-31 22:03:12 -0800605 # cpp_if
606 # cpp_endif
607 # methoddef_ifndef
Larry Hastingsbebf7352014-01-17 17:47:17 -0800608
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800609 return_value_declaration = "PyObject *return_value = NULL;"
Larry Hastings31826802013-10-19 00:09:25 -0700610
Larry Hastings7726ac92014-01-31 22:03:12 -0800611 methoddef_define = normalize_snippet("""
612 #define {methoddef_name} \\
613 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
614 """)
Larry Hastings5c661892014-01-24 06:17:25 -0800615 if new_or_init and not f.docstring:
616 docstring_prototype = docstring_definition = ''
617 else:
Larry Hastings7726ac92014-01-31 22:03:12 -0800618 docstring_prototype = normalize_snippet("""
619 PyDoc_VAR({c_basename}__doc__);
620 """)
621 docstring_definition = normalize_snippet("""
622 PyDoc_STRVAR({c_basename}__doc__,
623 {docstring});
624 """)
625 impl_definition = normalize_snippet("""
626 static {impl_return_type}
627 {c_basename}_impl({impl_parameters})
628 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800629 impl_prototype = parser_prototype = parser_definition = None
630
Larry Hastings7726ac92014-01-31 22:03:12 -0800631 parser_prototype_keyword = normalize_snippet("""
632 static PyObject *
633 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
634 """)
635
636 parser_prototype_varargs = normalize_snippet("""
637 static PyObject *
638 {c_basename}({self_type}{self_name}, PyObject *args)
639 """)
640
641 # parser_body_fields remembers the fields passed in to the
642 # previous call to parser_body. this is used for an awful hack.
Larry Hastingsc2047262014-01-25 20:43:29 -0800643 parser_body_fields = ()
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800644 def parser_body(prototype, *fields):
645 nonlocal parser_body_fields
646 add, output = text_accumulator()
647 add(prototype)
648 parser_body_fields = fields
Larry Hastings7726ac92014-01-31 22:03:12 -0800649
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800650 fields = list(fields)
Larry Hastings7726ac92014-01-31 22:03:12 -0800651 fields.insert(0, normalize_snippet("""
652 {{
653 {return_value_declaration}
654 {declarations}
655 {initializers}
656 """) + "\n")
657 # just imagine--your code is here in the middle
658 fields.append(normalize_snippet("""
659 {modifications}
660 {return_value} = {c_basename}_impl({impl_arguments});
661 {return_conversion}
662
663 {exit_label}
664 {cleanup}
665 return return_value;
666 }}
667 """))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800668 for field in fields:
669 add('\n')
Larry Hastings7726ac92014-01-31 22:03:12 -0800670 add(field)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800671 return output()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800672
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800673 def insert_keywords(s):
674 return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
Larry Hastingsbebf7352014-01-17 17:47:17 -0800675
676 if not parameters:
677 # no parameters, METH_NOARGS
678
679 flags = "METH_NOARGS"
680
Larry Hastings7726ac92014-01-31 22:03:12 -0800681 parser_prototype = normalize_snippet("""
682 static PyObject *
683 {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
684 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800685 parser_definition = parser_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800686
687 if default_return_converter:
Larry Hastings7726ac92014-01-31 22:03:12 -0800688 parser_definition = parser_prototype + '\n' + normalize_snippet("""
689 {{
690 return {c_basename}_impl({impl_arguments});
691 }}
692 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800693 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800694 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700695
Larry Hastingsbebf7352014-01-17 17:47:17 -0800696 elif meth_o:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800697 flags = "METH_O"
Larry Hastings7726ac92014-01-31 22:03:12 -0800698
699 meth_o_prototype = normalize_snippet("""
700 static PyObject *
701 {c_basename}({impl_parameters})
702 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800703
Larry Hastingsbebf7352014-01-17 17:47:17 -0800704 if default_return_converter:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800705 # maps perfectly to METH_O, doesn't need a return converter.
706 # so we skip making a parse function
707 # and call directly into the impl function.
Larry Hastingsbebf7352014-01-17 17:47:17 -0800708 impl_prototype = parser_prototype = parser_definition = ''
Larry Hastings7726ac92014-01-31 22:03:12 -0800709 impl_definition = meth_o_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800710 else:
Larry Hastings7726ac92014-01-31 22:03:12 -0800711 # SLIGHT HACK
712 # use impl_parameters for the parser here!
713 parser_prototype = meth_o_prototype
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800714 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700715
Larry Hastingsbebf7352014-01-17 17:47:17 -0800716 elif has_option_groups:
717 # positional parameters with option groups
718 # (we have to generate lots of PyArg_ParseTuple calls
719 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700720
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800721 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800722 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700723
Larry Hastings7726ac92014-01-31 22:03:12 -0800724 parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')
Larry Hastings31826802013-10-19 00:09:25 -0700725
Larry Hastingsbebf7352014-01-17 17:47:17 -0800726 elif positional and all_boring_objects:
727 # positional-only, but no option groups,
728 # and nothing but normal objects:
729 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700730
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800731 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800732 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700733
Larry Hastings7726ac92014-01-31 22:03:12 -0800734 parser_definition = parser_body(parser_prototype, normalize_snippet("""
735 if (!PyArg_UnpackTuple(args, "{name}",
736 {unpack_min}, {unpack_max},
737 {parse_arguments}))
738 goto exit;
739 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800740
741 elif positional:
742 # positional-only, but no option groups
743 # we only need one call to PyArg_ParseTuple
744
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800745 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800746 parser_prototype = parser_prototype_varargs
Larry Hastingsbebf7352014-01-17 17:47:17 -0800747
Larry Hastings7726ac92014-01-31 22:03:12 -0800748 parser_definition = parser_body(parser_prototype, normalize_snippet("""
749 if (!PyArg_ParseTuple(args,
750 "{format_units}:{name}",
751 {parse_arguments}))
752 goto exit;
753 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800754
755 else:
756 # positional-or-keyword arguments
757 flags = "METH_VARARGS|METH_KEYWORDS"
758
Larry Hastings7726ac92014-01-31 22:03:12 -0800759 parser_prototype = parser_prototype_keyword
Larry Hastingsbebf7352014-01-17 17:47:17 -0800760
Larry Hastings7726ac92014-01-31 22:03:12 -0800761 body = normalize_snippet("""
762 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
763 "{format_units}:{name}", _keywords,
764 {parse_arguments}))
765 goto exit;
766 """, indent=4)
767 parser_definition = parser_body(parser_prototype, normalize_snippet("""
768 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
769 "{format_units}:{name}", _keywords,
770 {parse_arguments}))
771 goto exit;
772 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800773 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700774
Larry Hastings31826802013-10-19 00:09:25 -0700775
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800776 if new_or_init:
777 methoddef_define = ''
778
779 if f.kind == METHOD_NEW:
Larry Hastings7726ac92014-01-31 22:03:12 -0800780 parser_prototype = parser_prototype_keyword
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800781 else:
782 return_value_declaration = "int return_value = -1;"
Larry Hastings7726ac92014-01-31 22:03:12 -0800783 parser_prototype = normalize_snippet("""
784 static int
785 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
786 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800787
788 fields = list(parser_body_fields)
789 parses_positional = 'METH_NOARGS' not in flags
790 parses_keywords = 'METH_KEYWORDS' in flags
791 if parses_keywords:
792 assert parses_positional
793
794 if not parses_keywords:
Larry Hastings7726ac92014-01-31 22:03:12 -0800795 fields.insert(0, normalize_snippet("""
796 if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs))
797 goto exit;
798 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800799 if not parses_positional:
Larry Hastings7726ac92014-01-31 22:03:12 -0800800 fields.insert(0, normalize_snippet("""
801 if ({self_type_check}!_PyArg_NoPositional("{name}", args))
802 goto exit;
803 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800804
805 parser_definition = parser_body(parser_prototype, *fields)
806 if parses_keywords:
807 parser_definition = insert_keywords(parser_definition)
808
Larry Hastings31826802013-10-19 00:09:25 -0700809
Larry Hastingsbebf7352014-01-17 17:47:17 -0800810 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800811 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700812
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800813 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700814
Larry Hastings7726ac92014-01-31 22:03:12 -0800815 methoddef_ifndef = ''
816 conditional = self.cpp.condition()
817 if not conditional:
818 cpp_if = cpp_endif = ''
819 else:
820 cpp_if = "#if " + conditional
821 cpp_endif = "#endif /* " + conditional + " */"
822
823 if methoddef_define:
824 methoddef_ifndef = normalize_snippet("""
825 #ifndef {methoddef_name}
826 #define {methoddef_name}
827 #endif /* !defined({methoddef_name}) */
828 """)
829
830
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800831 # add ';' to the end of parser_prototype and impl_prototype
832 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800833 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800834 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800835 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800836 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700837
Larry Hastingsbebf7352014-01-17 17:47:17 -0800838 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800839 impl_prototype = impl_definition
840 if impl_prototype:
841 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700842
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800843 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800844
845 d = {
846 "docstring_prototype" : docstring_prototype,
847 "docstring_definition" : docstring_definition,
848 "impl_prototype" : impl_prototype,
849 "methoddef_define" : methoddef_define,
850 "parser_prototype" : parser_prototype,
851 "parser_definition" : parser_definition,
852 "impl_definition" : impl_definition,
Larry Hastings7726ac92014-01-31 22:03:12 -0800853 "cpp_if" : cpp_if,
854 "cpp_endif" : cpp_endif,
855 "methoddef_ifndef" : methoddef_ifndef,
Larry Hastingsbebf7352014-01-17 17:47:17 -0800856 }
857
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800858 # make sure we didn't forget to assign something,
859 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -0800860 d2 = {}
861 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800862 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800863 if value:
864 value = '\n' + value + '\n'
865 d2[name] = value
866 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700867
868 @staticmethod
869 def group_to_variable_name(group):
870 adjective = "left_" if group < 0 else "right_"
871 return "group_" + adjective + str(abs(group))
872
873 def render_option_group_parsing(self, f, template_dict):
874 # positional only, grouped, optional arguments!
875 # can be optional on the left or right.
876 # here's an example:
877 #
878 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
879 #
880 # Here group D are required, and all other groups are optional.
881 # (Group D's "group" is actually None.)
882 # We can figure out which sets of arguments we have based on
883 # how many arguments are in the tuple.
884 #
885 # Note that you need to count up on both sides. For example,
886 # you could have groups C+D, or C+D+E, or C+D+E+F.
887 #
888 # What if the number of arguments leads us to an ambiguous result?
889 # Clinic prefers groups on the left. So in the above example,
890 # five arguments would map to B+C, not C+D.
891
892 add, output = text_accumulator()
893 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800894 if isinstance(parameters[0].converter, self_converter):
895 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -0700896
897 groups = []
898 group = None
899 left = []
900 right = []
901 required = []
902 last = unspecified
903
904 for p in parameters:
905 group_id = p.group
906 if group_id != last:
907 last = group_id
908 group = []
909 if group_id < 0:
910 left.append(group)
911 elif group_id == 0:
912 group = required
913 else:
914 right.append(group)
915 group.append(p)
916
917 count_min = sys.maxsize
918 count_max = -1
919
Larry Hastings2a727912014-01-16 11:32:01 -0800920 add("switch (PyTuple_GET_SIZE(args)) {{\n")
Larry Hastings31826802013-10-19 00:09:25 -0700921 for subset in permute_optional_groups(left, required, right):
922 count = len(subset)
923 count_min = min(count_min, count)
924 count_max = max(count_max, count)
925
Larry Hastings583baa82014-01-12 08:49:30 -0800926 if count == 0:
927 add(""" case 0:
928 break;
929""")
930 continue
931
Larry Hastings31826802013-10-19 00:09:25 -0700932 group_ids = {p.group for p in subset} # eliminate duplicates
933 d = {}
934 d['count'] = count
935 d['name'] = f.name
936 d['groups'] = sorted(group_ids)
937 d['format_units'] = "".join(p.converter.format_unit for p in subset)
938
939 parse_arguments = []
940 for p in subset:
941 p.converter.parse_argument(parse_arguments)
942 d['parse_arguments'] = ", ".join(parse_arguments)
943
944 group_ids.discard(0)
945 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
946 lines = "\n".join(lines)
947
948 s = """
949 case {count}:
950 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
Larry Hastings46258262014-01-22 03:05:49 -0800951 goto exit;
Larry Hastings31826802013-10-19 00:09:25 -0700952 {group_booleans}
953 break;
954"""[1:]
955 s = linear_format(s, group_booleans=lines)
956 s = s.format_map(d)
957 add(s)
958
959 add(" default:\n")
960 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
961 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -0800962 add(' goto exit;\n')
Larry Hastings31826802013-10-19 00:09:25 -0700963 add("}}")
964 template_dict['option_group_parsing'] = output()
965
Larry Hastingsbebf7352014-01-17 17:47:17 -0800966 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -0700967 if not f:
968 return ""
969
970 add, output = text_accumulator()
971 data = CRenderData()
972
Larry Hastings7726ac92014-01-31 22:03:12 -0800973 assert f.parameters, "We should always have a 'self' at this point!"
974 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -0700975 converters = [p.converter for p in parameters]
976
Larry Hastings5c661892014-01-24 06:17:25 -0800977 templates = self.output_templates(f)
978
979 f_self = parameters[0]
980 selfless = parameters[1:]
981 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
982
983 last_group = 0
984 first_optional = len(selfless)
985 positional = selfless and selfless[-1].kind == inspect.Parameter.POSITIONAL_ONLY
986 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
987 default_return_converter = (not f.return_converter or
988 f.return_converter.type == 'PyObject *')
989 has_option_groups = False
990
991 # offset i by -1 because first_optional needs to ignore self
992 for i, p in enumerate(parameters, -1):
993 c = p.converter
994
995 if (i != -1) and (p.default is not unspecified):
996 first_optional = min(first_optional, i)
997
998 # insert group variable
999 group = p.group
1000 if last_group != group:
1001 last_group = group
1002 if group:
1003 group_name = self.group_to_variable_name(group)
1004 data.impl_arguments.append(group_name)
1005 data.declarations.append("int " + group_name + " = 0;")
1006 data.impl_parameters.append("int " + group_name)
1007 has_option_groups = True
1008
1009 c.render(p, data)
1010
1011 if has_option_groups and (not positional):
1012 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
1013
1014 # HACK
1015 # when we're METH_O, but have a custom return converter,
1016 # we use "impl_parameters" for the parsing function
1017 # because that works better. but that means we must
Berker Peksagf23530f2014-10-19 18:04:38 +03001018 # suppress actually declaring the impl's parameters
Larry Hastings5c661892014-01-24 06:17:25 -08001019 # as variables in the parsing function. but since it's
1020 # METH_O, we have exactly one anyway, so we know exactly
1021 # where it is.
1022 if ("METH_O" in templates['methoddef_define'] and
1023 not default_return_converter):
1024 data.declarations.pop(0)
1025
Larry Hastings31826802013-10-19 00:09:25 -07001026 template_dict = {}
1027
1028 full_name = f.full_name
1029 template_dict['full_name'] = full_name
1030
Larry Hastings5c661892014-01-24 06:17:25 -08001031 if new_or_init:
1032 name = f.cls.name
1033 else:
1034 name = f.name
1035
Larry Hastings31826802013-10-19 00:09:25 -07001036 template_dict['name'] = name
1037
Larry Hastings8666e652014-01-12 14:12:59 -08001038 if f.c_basename:
1039 c_basename = f.c_basename
1040 else:
1041 fields = full_name.split(".")
1042 if fields[-1] == '__new__':
1043 fields.pop()
1044 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001045
Larry Hastings31826802013-10-19 00:09:25 -07001046 template_dict['c_basename'] = c_basename
1047
1048 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1049 template_dict['methoddef_name'] = methoddef_name
1050
1051 template_dict['docstring'] = self.docstring_for_c_string(f)
1052
Larry Hastingsc2047262014-01-25 20:43:29 -08001053 template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
Larry Hastings5c661892014-01-24 06:17:25 -08001054 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001055
Larry Hastings31826802013-10-19 00:09:25 -07001056 f.return_converter.render(f, data)
1057 template_dict['impl_return_type'] = f.return_converter.type
1058
1059 template_dict['declarations'] = "\n".join(data.declarations)
1060 template_dict['initializers'] = "\n\n".join(data.initializers)
Larry Hastingsc2047262014-01-25 20:43:29 -08001061 template_dict['modifications'] = '\n\n'.join(data.modifications)
Larry Hastings31826802013-10-19 00:09:25 -07001062 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1063 template_dict['format_units'] = ''.join(data.format_units)
1064 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1065 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1066 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
1067 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
1068 template_dict['cleanup'] = "".join(data.cleanup)
1069 template_dict['return_value'] = data.return_value
1070
Larry Hastings5c661892014-01-24 06:17:25 -08001071 # used by unpack tuple code generator
1072 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1073 unpack_min = first_optional
1074 unpack_max = len(selfless)
1075 template_dict['unpack_min'] = str(unpack_min)
1076 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001077
Larry Hastingsbebf7352014-01-17 17:47:17 -08001078 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001079 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001080
Larry Hastingsbebf7352014-01-17 17:47:17 -08001081 for name, destination in clinic.field_destinations.items():
1082 template = templates[name]
1083 if has_option_groups:
1084 template = linear_format(template,
1085 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001086 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001087 declarations=template_dict['declarations'],
1088 return_conversion=template_dict['return_conversion'],
1089 initializers=template_dict['initializers'],
Larry Hastingsc2047262014-01-25 20:43:29 -08001090 modifications=template_dict['modifications'],
Larry Hastingsbebf7352014-01-17 17:47:17 -08001091 cleanup=template_dict['cleanup'],
1092 )
Larry Hastings31826802013-10-19 00:09:25 -07001093
Larry Hastingsbebf7352014-01-17 17:47:17 -08001094 # Only generate the "exit:" label
1095 # if we have any gotos
1096 need_exit_label = "goto exit;" in template
1097 template = linear_format(template,
1098 exit_label="exit:" if need_exit_label else ''
1099 )
Larry Hastings31826802013-10-19 00:09:25 -07001100
Larry Hastingsbebf7352014-01-17 17:47:17 -08001101 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001102
Larry Hastingsbebf7352014-01-17 17:47:17 -08001103 if clinic.line_prefix:
1104 s = indent_all_lines(s, clinic.line_prefix)
1105 if clinic.line_suffix:
1106 s = suffix_all_lines(s, clinic.line_suffix)
1107
1108 destination.append(s)
1109
1110 return clinic.get_destination('block').dump()
1111
Larry Hastings31826802013-10-19 00:09:25 -07001112
1113
Larry Hastings5c661892014-01-24 06:17:25 -08001114
Larry Hastings31826802013-10-19 00:09:25 -07001115@contextlib.contextmanager
1116def OverrideStdioWith(stdout):
1117 saved_stdout = sys.stdout
1118 sys.stdout = stdout
1119 try:
1120 yield
1121 finally:
1122 assert sys.stdout is stdout
1123 sys.stdout = saved_stdout
1124
1125
Larry Hastings2623c8c2014-02-08 22:15:29 -08001126def create_regex(before, after, word=True, whole_line=True):
Larry Hastings31826802013-10-19 00:09:25 -07001127 """Create an re object for matching marker lines."""
Larry Hastings581ee362014-01-28 05:00:08 -08001128 group_re = "\w+" if word else ".+"
Larry Hastings2623c8c2014-02-08 22:15:29 -08001129 pattern = r'{}({}){}'
1130 if whole_line:
1131 pattern = '^' + pattern + '$'
Larry Hastings581ee362014-01-28 05:00:08 -08001132 pattern = pattern.format(re.escape(before), group_re, re.escape(after))
1133 return re.compile(pattern)
Larry Hastings31826802013-10-19 00:09:25 -07001134
1135
1136class Block:
1137 r"""
1138 Represents a single block of text embedded in
1139 another file. If dsl_name is None, the block represents
1140 verbatim text, raw original text from the file, in
1141 which case "input" will be the only non-false member.
1142 If dsl_name is not None, the block represents a Clinic
1143 block.
1144
1145 input is always str, with embedded \n characters.
1146 input represents the original text from the file;
1147 if it's a Clinic block, it is the original text with
1148 the body_prefix and redundant leading whitespace removed.
1149
1150 dsl_name is either str or None. If str, it's the text
1151 found on the start line of the block between the square
1152 brackets.
1153
1154 signatures is either list or None. If it's a list,
1155 it may only contain clinic.Module, clinic.Class, and
1156 clinic.Function objects. At the moment it should
1157 contain at most one of each.
1158
1159 output is either str or None. If str, it's the output
1160 from this block, with embedded '\n' characters.
1161
1162 indent is either str or None. It's the leading whitespace
1163 that was found on every line of input. (If body_prefix is
1164 not empty, this is the indent *after* removing the
1165 body_prefix.)
1166
1167 preindent is either str or None. It's the whitespace that
1168 was found in front of every line of input *before* the
1169 "body_prefix" (see the Language object). If body_prefix
1170 is empty, preindent must always be empty too.
1171
1172 To illustrate indent and preindent: Assume that '_'
1173 represents whitespace. If the block processed was in a
1174 Python file, and looked like this:
1175 ____#/*[python]
1176 ____#__for a in range(20):
1177 ____#____print(a)
1178 ____#[python]*/
1179 "preindent" would be "____" and "indent" would be "__".
1180
1181 """
1182 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1183 assert isinstance(input, str)
1184 self.input = input
1185 self.dsl_name = dsl_name
1186 self.signatures = signatures or []
1187 self.output = output
1188 self.indent = indent
1189 self.preindent = preindent
1190
Larry Hastings581ee362014-01-28 05:00:08 -08001191 def __repr__(self):
1192 dsl_name = self.dsl_name or "text"
1193 def summarize(s):
1194 s = repr(s)
1195 if len(s) > 30:
1196 return s[:26] + "..." + s[0]
1197 return s
1198 return "".join((
1199 "<Block ", dsl_name, " input=", summarize(self.input), " output=", summarize(self.output), ">"))
1200
Larry Hastings31826802013-10-19 00:09:25 -07001201
1202class BlockParser:
1203 """
1204 Block-oriented parser for Argument Clinic.
1205 Iterator, yields Block objects.
1206 """
1207
1208 def __init__(self, input, language, *, verify=True):
1209 """
1210 "input" should be a str object
1211 with embedded \n characters.
1212
1213 "language" should be a Language object.
1214 """
1215 language.validate()
1216
1217 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1218 self.block_start_line_number = self.line_number = 0
1219
1220 self.language = language
1221 before, _, after = language.start_line.partition('{dsl_name}')
1222 assert _ == '{dsl_name}'
Larry Hastings2623c8c2014-02-08 22:15:29 -08001223 self.find_start_re = create_regex(before, after, whole_line=False)
Larry Hastings31826802013-10-19 00:09:25 -07001224 self.start_re = create_regex(before, after)
1225 self.verify = verify
1226 self.last_checksum_re = None
1227 self.last_dsl_name = None
1228 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001229 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001230
1231 def __iter__(self):
1232 return self
1233
1234 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001235 while True:
1236 if not self.input:
1237 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001238
Larry Hastingsbebf7352014-01-17 17:47:17 -08001239 if self.dsl_name:
1240 return_value = self.parse_clinic_block(self.dsl_name)
1241 self.dsl_name = None
1242 self.first_block = False
1243 return return_value
1244 block = self.parse_verbatim_block()
1245 if self.first_block and not block.input:
1246 continue
1247 self.first_block = False
1248 return block
1249
Larry Hastings31826802013-10-19 00:09:25 -07001250
1251 def is_start_line(self, line):
1252 match = self.start_re.match(line.lstrip())
1253 return match.group(1) if match else None
1254
Larry Hastingse1b82532014-07-27 16:22:20 +02001255 def _line(self, lookahead=False):
Larry Hastings31826802013-10-19 00:09:25 -07001256 self.line_number += 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001257 line = self.input.pop()
Larry Hastingse1b82532014-07-27 16:22:20 +02001258 if not lookahead:
1259 self.language.parse_line(line)
Larry Hastings7726ac92014-01-31 22:03:12 -08001260 return line
Larry Hastings31826802013-10-19 00:09:25 -07001261
1262 def parse_verbatim_block(self):
1263 add, output = text_accumulator()
1264 self.block_start_line_number = self.line_number
1265
1266 while self.input:
1267 line = self._line()
1268 dsl_name = self.is_start_line(line)
1269 if dsl_name:
1270 self.dsl_name = dsl_name
1271 break
1272 add(line)
1273
1274 return Block(output())
1275
1276 def parse_clinic_block(self, dsl_name):
1277 input_add, input_output = text_accumulator()
1278 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001279 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001280 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1281
Larry Hastings90261132014-01-07 12:21:08 -08001282 def is_stop_line(line):
1283 # make sure to recognize stop line even if it
1284 # doesn't end with EOL (it could be the very end of the file)
1285 if not line.startswith(stop_line):
1286 return False
1287 remainder = line[len(stop_line):]
1288 return (not remainder) or remainder.isspace()
1289
Larry Hastings31826802013-10-19 00:09:25 -07001290 # consume body of program
1291 while self.input:
1292 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001293 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001294 break
1295 if body_prefix:
1296 line = line.lstrip()
1297 assert line.startswith(body_prefix)
1298 line = line[len(body_prefix):]
1299 input_add(line)
1300
1301 # consume output and checksum line, if present.
1302 if self.last_dsl_name == dsl_name:
1303 checksum_re = self.last_checksum_re
1304 else:
Larry Hastings581ee362014-01-28 05:00:08 -08001305 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, arguments='{arguments}').partition('{arguments}')
1306 assert _ == '{arguments}'
1307 checksum_re = create_regex(before, after, word=False)
Larry Hastings31826802013-10-19 00:09:25 -07001308 self.last_dsl_name = dsl_name
1309 self.last_checksum_re = checksum_re
1310
1311 # scan forward for checksum line
1312 output_add, output_output = text_accumulator()
Larry Hastings581ee362014-01-28 05:00:08 -08001313 arguments = None
Larry Hastings31826802013-10-19 00:09:25 -07001314 while self.input:
Larry Hastingse1b82532014-07-27 16:22:20 +02001315 line = self._line(lookahead=True)
Larry Hastings31826802013-10-19 00:09:25 -07001316 match = checksum_re.match(line.lstrip())
Larry Hastings581ee362014-01-28 05:00:08 -08001317 arguments = match.group(1) if match else None
1318 if arguments:
Larry Hastings31826802013-10-19 00:09:25 -07001319 break
1320 output_add(line)
1321 if self.is_start_line(line):
1322 break
1323
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001324 output = output_output()
Larry Hastings581ee362014-01-28 05:00:08 -08001325 if arguments:
1326 d = {}
1327 for field in shlex.split(arguments):
1328 name, equals, value = field.partition('=')
1329 if not equals:
1330 fail("Mangled Argument Clinic marker line: {!r}".format(line))
1331 d[name.strip()] = value.strip()
1332
Larry Hastings31826802013-10-19 00:09:25 -07001333 if self.verify:
Larry Hastings581ee362014-01-28 05:00:08 -08001334 if 'input' in d:
1335 checksum = d['output']
1336 input_checksum = d['input']
1337 else:
1338 checksum = d['checksum']
1339 input_checksum = None
1340
1341 computed = compute_checksum(output, len(checksum))
Larry Hastings31826802013-10-19 00:09:25 -07001342 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001343 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1344 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001345 "the end marker,\n"
1346 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001347 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001348 else:
1349 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001350 output_lines = output.splitlines(keepends=True)
1351 self.line_number -= len(output_lines)
1352 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001353 output = None
1354
1355 return Block(input_output(), dsl_name, output=output)
1356
1357
1358class BlockPrinter:
1359
1360 def __init__(self, language, f=None):
1361 self.language = language
1362 self.f = f or io.StringIO()
1363
1364 def print_block(self, block):
1365 input = block.input
1366 output = block.output
1367 dsl_name = block.dsl_name
1368 write = self.f.write
1369
Larry Hastings31826802013-10-19 00:09:25 -07001370 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1371
1372 if not dsl_name:
1373 write(input)
1374 return
1375
1376 write(self.language.start_line.format(dsl_name=dsl_name))
1377 write("\n")
1378
1379 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1380 if not body_prefix:
1381 write(input)
1382 else:
1383 for line in input.split('\n'):
1384 write(body_prefix)
1385 write(line)
1386 write("\n")
1387
1388 write(self.language.stop_line.format(dsl_name=dsl_name))
1389 write("\n")
1390
Larry Hastings581ee362014-01-28 05:00:08 -08001391 input = ''.join(block.input)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001392 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001393 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001394 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001395 output += '\n'
1396 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001397
Larry Hastings581ee362014-01-28 05:00:08 -08001398 arguments="output={} input={}".format(compute_checksum(output, 16), compute_checksum(input, 16))
1399 write(self.language.checksum_line.format(dsl_name=dsl_name, arguments=arguments))
Larry Hastings31826802013-10-19 00:09:25 -07001400 write("\n")
1401
Larry Hastingsbebf7352014-01-17 17:47:17 -08001402 def write(self, text):
1403 self.f.write(text)
1404
1405
1406class Destination:
1407 def __init__(self, name, type, clinic, *args):
1408 self.name = name
1409 self.type = type
1410 self.clinic = clinic
1411 valid_types = ('buffer', 'file', 'suppress', 'two-pass')
1412 if type not in valid_types:
1413 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1414 extra_arguments = 1 if type == "file" else 0
1415 if len(args) < extra_arguments:
1416 fail("Not enough arguments for destination " + name + " new " + type)
1417 if len(args) > extra_arguments:
1418 fail("Too many arguments for destination " + name + " new " + type)
1419 if type =='file':
1420 d = {}
Larry Hastingsc2047262014-01-25 20:43:29 -08001421 filename = clinic.filename
1422 d['path'] = filename
1423 dirname, basename = os.path.split(filename)
1424 if not dirname:
1425 dirname = '.'
1426 d['dirname'] = dirname
1427 d['basename'] = basename
1428 d['basename_root'], d['basename_extension'] = os.path.splitext(filename)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001429 self.filename = args[0].format_map(d)
1430 if type == 'two-pass':
1431 self.id = None
1432
1433 self.text, self.append, self._dump = _text_accumulator()
1434
1435 def __repr__(self):
1436 if self.type == 'file':
1437 file_repr = " " + repr(self.filename)
1438 else:
1439 file_repr = ''
1440 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1441
1442 def clear(self):
1443 if self.type != 'buffer':
1444 fail("Can't clear destination" + self.name + " , it's not of type buffer")
1445 self.text.clear()
1446
1447 def dump(self):
1448 if self.type == 'two-pass':
1449 if self.id is None:
1450 self.id = str(uuid.uuid4())
1451 return self.id
1452 fail("You can only dump a two-pass buffer exactly once!")
1453 return self._dump()
1454
Larry Hastings31826802013-10-19 00:09:25 -07001455
1456# maps strings to Language objects.
1457# "languages" maps the name of the language ("C", "Python").
1458# "extensions" maps the file extension ("c", "py").
1459languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001460extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1461extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001462
1463
1464# maps strings to callables.
1465# these callables must be of the form:
1466# def foo(name, default, *, ...)
1467# The callable may have any number of keyword-only parameters.
1468# The callable must return a CConverter object.
1469# The callable should not call builtins.print.
1470converters = {}
1471
1472# maps strings to callables.
1473# these callables follow the same rules as those for "converters" above.
1474# note however that they will never be called with keyword-only parameters.
1475legacy_converters = {}
1476
1477
1478# maps strings to callables.
1479# these callables must be of the form:
1480# def foo(*, ...)
1481# The callable may have any number of keyword-only parameters.
1482# The callable must return a CConverter object.
1483# The callable should not call builtins.print.
1484return_converters = {}
1485
Larry Hastings7726ac92014-01-31 22:03:12 -08001486clinic = None
Larry Hastings31826802013-10-19 00:09:25 -07001487class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001488
1489 presets_text = """
Larry Hastings7726ac92014-01-31 22:03:12 -08001490preset block
1491everything block
1492docstring_prototype suppress
1493parser_prototype suppress
1494cpp_if suppress
1495cpp_endif suppress
1496methoddef_ifndef buffer
1497
Larry Hastingsbebf7352014-01-17 17:47:17 -08001498preset original
1499everything block
1500docstring_prototype suppress
1501parser_prototype suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001502cpp_if suppress
1503cpp_endif suppress
1504methoddef_ifndef buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001505
1506preset file
1507everything file
1508docstring_prototype suppress
1509parser_prototype suppress
1510impl_definition block
1511
1512preset buffer
1513everything buffer
1514docstring_prototype suppress
1515impl_prototype suppress
1516parser_prototype suppress
1517impl_definition block
1518
1519preset partial-buffer
1520everything buffer
1521docstring_prototype block
1522impl_prototype suppress
1523methoddef_define block
1524parser_prototype block
1525impl_definition block
1526
1527preset two-pass
1528everything buffer
1529docstring_prototype two-pass
1530impl_prototype suppress
1531methoddef_define two-pass
1532parser_prototype two-pass
1533impl_definition block
1534
1535"""
1536
Larry Hastings581ee362014-01-28 05:00:08 -08001537 def __init__(self, language, printer=None, *, force=False, verify=True, filename=None):
Larry Hastings31826802013-10-19 00:09:25 -07001538 # maps strings to Parser objects.
1539 # (instantiated from the "parsers" global.)
1540 self.parsers = {}
1541 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001542 if printer:
1543 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001544 self.printer = printer or BlockPrinter(language)
1545 self.verify = verify
Larry Hastings581ee362014-01-28 05:00:08 -08001546 self.force = force
Larry Hastings31826802013-10-19 00:09:25 -07001547 self.filename = filename
1548 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001549 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001550 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001551
Larry Hastingsbebf7352014-01-17 17:47:17 -08001552 self.line_prefix = self.line_suffix = ''
1553
1554 self.destinations = {}
1555 self.add_destination("block", "buffer")
1556 self.add_destination("suppress", "suppress")
1557 self.add_destination("buffer", "buffer")
1558 self.add_destination("two-pass", "two-pass")
1559 if filename:
Larry Hastingsc2047262014-01-25 20:43:29 -08001560 self.add_destination("file", "file", "{dirname}/clinic/{basename}.h")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001561
1562 d = self.destinations.get
1563 self.field_destinations = collections.OrderedDict((
Larry Hastings7726ac92014-01-31 22:03:12 -08001564 ('cpp_if', d('suppress')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001565 ('docstring_prototype', d('suppress')),
1566 ('docstring_definition', d('block')),
1567 ('methoddef_define', d('block')),
1568 ('impl_prototype', d('block')),
1569 ('parser_prototype', d('suppress')),
1570 ('parser_definition', d('block')),
Larry Hastings7726ac92014-01-31 22:03:12 -08001571 ('cpp_endif', d('suppress')),
1572 ('methoddef_ifndef', d('buffer')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001573 ('impl_definition', d('block')),
1574 ))
1575
1576 self.field_destinations_stack = []
1577
1578 self.presets = {}
1579 preset = None
1580 for line in self.presets_text.strip().split('\n'):
1581 line = line.strip()
1582 if not line:
1583 continue
1584 name, value = line.split()
1585 if name == 'preset':
1586 self.presets[value] = preset = collections.OrderedDict()
1587 continue
1588
1589 destination = self.get_destination(value)
1590
1591 if name == 'everything':
1592 for name in self.field_destinations:
1593 preset[name] = destination
1594 continue
1595
1596 assert name in self.field_destinations
1597 preset[name] = destination
1598
Larry Hastings31826802013-10-19 00:09:25 -07001599 global clinic
1600 clinic = self
1601
Larry Hastingsbebf7352014-01-17 17:47:17 -08001602 def get_destination(self, name, default=unspecified):
1603 d = self.destinations.get(name)
1604 if not d:
1605 if default is not unspecified:
1606 return default
1607 fail("Destination does not exist: " + repr(name))
1608 return d
1609
1610 def add_destination(self, name, type, *args):
1611 if name in self.destinations:
1612 fail("Destination already exists: " + repr(name))
1613 self.destinations[name] = Destination(name, type, self, *args)
1614
Larry Hastings31826802013-10-19 00:09:25 -07001615 def parse(self, input):
1616 printer = self.printer
1617 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1618 for block in self.block_parser:
1619 dsl_name = block.dsl_name
1620 if dsl_name:
1621 if dsl_name not in self.parsers:
1622 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1623 self.parsers[dsl_name] = parsers[dsl_name](self)
1624 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001625 try:
1626 parser.parse(block)
1627 except Exception:
1628 fail('Exception raised during parsing:\n' +
1629 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001630 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001631
1632 second_pass_replacements = {}
1633
1634 for name, destination in self.destinations.items():
1635 if destination.type == 'suppress':
1636 continue
1637 output = destination._dump()
1638
1639 if destination.type == 'two-pass':
1640 if destination.id:
1641 second_pass_replacements[destination.id] = output
1642 elif output:
1643 fail("Two-pass buffer " + repr(name) + " not empty at end of file!")
1644 continue
1645
1646 if output:
1647
1648 block = Block("", dsl_name="clinic", output=output)
1649
1650 if destination.type == 'buffer':
1651 block.input = "dump " + name + "\n"
1652 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1653 printer.write("\n")
1654 printer.print_block(block)
1655 continue
1656
1657 if destination.type == 'file':
1658 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08001659 dirname = os.path.dirname(destination.filename)
1660 try:
1661 os.makedirs(dirname)
1662 except FileExistsError:
1663 if not os.path.isdir(dirname):
1664 fail("Can't write to destination {}, "
1665 "can't make directory {}!".format(
1666 destination.filename, dirname))
Larry Hastings581ee362014-01-28 05:00:08 -08001667 if self.verify:
1668 with open(destination.filename, "rt") as f:
1669 parser_2 = BlockParser(f.read(), language=self.language)
1670 blocks = list(parser_2)
1671 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1672 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001673 except FileNotFoundError:
1674 pass
1675
1676 block.input = 'preserve\n'
1677 printer_2 = BlockPrinter(self.language)
1678 printer_2.print_block(block)
1679 with open(destination.filename, "wt") as f:
1680 f.write(printer_2.f.getvalue())
1681 continue
1682 text = printer.f.getvalue()
1683
1684 if second_pass_replacements:
1685 printer_2 = BlockPrinter(self.language)
1686 parser_2 = BlockParser(text, self.language)
1687 changed = False
1688 for block in parser_2:
1689 if block.dsl_name:
1690 for id, replacement in second_pass_replacements.items():
1691 if id in block.output:
1692 changed = True
1693 block.output = block.output.replace(id, replacement)
1694 printer_2.print_block(block)
1695 if changed:
1696 text = printer_2.f.getvalue()
1697
1698 return text
1699
Larry Hastings31826802013-10-19 00:09:25 -07001700
1701 def _module_and_class(self, fields):
1702 """
1703 fields should be an iterable of field names.
1704 returns a tuple of (module, class).
1705 the module object could actually be self (a clinic object).
1706 this function is only ever used to find the parent of where
1707 a new class/module should go.
1708 """
1709 in_classes = False
1710 parent = module = self
1711 cls = None
1712 so_far = []
1713
1714 for field in fields:
1715 so_far.append(field)
1716 if not in_classes:
1717 child = parent.modules.get(field)
1718 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001719 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001720 continue
1721 in_classes = True
1722 if not hasattr(parent, 'classes'):
1723 return module, cls
1724 child = parent.classes.get(field)
1725 if not child:
1726 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1727 cls = parent = child
1728
1729 return module, cls
1730
1731
Larry Hastings581ee362014-01-28 05:00:08 -08001732def parse_file(filename, *, force=False, verify=True, output=None, encoding='utf-8'):
Larry Hastings31826802013-10-19 00:09:25 -07001733 extension = os.path.splitext(filename)[1][1:]
1734 if not extension:
1735 fail("Can't extract file type for file " + repr(filename))
1736
1737 try:
Larry Hastings7726ac92014-01-31 22:03:12 -08001738 language = extensions[extension](filename)
Larry Hastings31826802013-10-19 00:09:25 -07001739 except KeyError:
1740 fail("Can't identify file type for file " + repr(filename))
1741
Larry Hastings31826802013-10-19 00:09:25 -07001742 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001743 raw = f.read()
1744
Larry Hastings2623c8c2014-02-08 22:15:29 -08001745 # exit quickly if there are no clinic markers in the file
1746 find_start_re = BlockParser("", language).find_start_re
1747 if not find_start_re.search(raw):
1748 return
1749
1750 clinic = Clinic(language, force=force, verify=verify, filename=filename)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001751 cooked = clinic.parse(raw)
Larry Hastings581ee362014-01-28 05:00:08 -08001752 if (cooked == raw) and not force:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001753 return
Larry Hastings31826802013-10-19 00:09:25 -07001754
1755 directory = os.path.dirname(filename) or '.'
1756
1757 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001758 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001759 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1760 with open(tmpfilename, "wb") as f:
1761 f.write(bytes)
1762 os.replace(tmpfilename, output or filename)
1763
1764
Larry Hastings581ee362014-01-28 05:00:08 -08001765def compute_checksum(input, length=None):
Larry Hastings31826802013-10-19 00:09:25 -07001766 input = input or ''
Larry Hastings581ee362014-01-28 05:00:08 -08001767 s = hashlib.sha1(input.encode('utf-8')).hexdigest()
1768 if length:
1769 s = s[:length]
1770 return s
Larry Hastings31826802013-10-19 00:09:25 -07001771
1772
1773
1774
1775class PythonParser:
1776 def __init__(self, clinic):
1777 pass
1778
1779 def parse(self, block):
1780 s = io.StringIO()
1781 with OverrideStdioWith(s):
1782 exec(block.input)
1783 block.output = s.getvalue()
1784
1785
1786class Module:
1787 def __init__(self, name, module=None):
1788 self.name = name
1789 self.module = self.parent = module
1790
1791 self.modules = collections.OrderedDict()
1792 self.classes = collections.OrderedDict()
1793 self.functions = []
1794
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001795 def __repr__(self):
1796 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1797
Larry Hastings31826802013-10-19 00:09:25 -07001798class Class:
Larry Hastingsc2047262014-01-25 20:43:29 -08001799 def __init__(self, name, module=None, cls=None, typedef=None, type_object=None):
Larry Hastings31826802013-10-19 00:09:25 -07001800 self.name = name
1801 self.module = module
1802 self.cls = cls
Larry Hastingsc2047262014-01-25 20:43:29 -08001803 self.typedef = typedef
1804 self.type_object = type_object
Larry Hastings31826802013-10-19 00:09:25 -07001805 self.parent = cls or module
1806
1807 self.classes = collections.OrderedDict()
1808 self.functions = []
1809
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001810 def __repr__(self):
1811 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1812
Larry Hastings8666e652014-01-12 14:12:59 -08001813unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001814
Larry Hastings8666e652014-01-12 14:12:59 -08001815__abs__
1816__add__
1817__and__
1818__bytes__
1819__call__
1820__complex__
1821__delitem__
1822__divmod__
1823__eq__
1824__float__
1825__floordiv__
1826__ge__
1827__getattr__
1828__getattribute__
1829__getitem__
1830__gt__
1831__hash__
1832__iadd__
1833__iand__
1834__idivmod__
1835__ifloordiv__
1836__ilshift__
1837__imod__
1838__imul__
1839__index__
1840__int__
1841__invert__
1842__ior__
1843__ipow__
1844__irshift__
1845__isub__
1846__iter__
1847__itruediv__
1848__ixor__
1849__le__
1850__len__
1851__lshift__
1852__lt__
1853__mod__
1854__mul__
1855__neg__
1856__new__
1857__next__
1858__or__
1859__pos__
1860__pow__
1861__radd__
1862__rand__
1863__rdivmod__
1864__repr__
1865__rfloordiv__
1866__rlshift__
1867__rmod__
1868__rmul__
1869__ror__
1870__round__
1871__rpow__
1872__rrshift__
1873__rshift__
1874__rsub__
1875__rtruediv__
1876__rxor__
1877__setattr__
1878__setitem__
1879__str__
1880__sub__
1881__truediv__
1882__xor__
1883
1884""".strip().split())
1885
1886
Larry Hastings5c661892014-01-24 06:17:25 -08001887INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
1888INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
1889""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07001890
1891class Function:
1892 """
1893 Mutable duck type for inspect.Function.
1894
1895 docstring - a str containing
1896 * embedded line breaks
1897 * text outdented to the left margin
1898 * no trailing whitespace.
1899 It will always be true that
1900 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
1901 """
1902
1903 def __init__(self, parameters=None, *, name,
1904 module, cls=None, c_basename=None,
1905 full_name=None,
1906 return_converter, return_annotation=_empty,
Larry Hastings581ee362014-01-28 05:00:08 -08001907 docstring=None, kind=CALLABLE, coexist=False,
Larry Hastings2623c8c2014-02-08 22:15:29 -08001908 docstring_only=False):
Larry Hastings31826802013-10-19 00:09:25 -07001909 self.parameters = parameters or collections.OrderedDict()
1910 self.return_annotation = return_annotation
1911 self.name = name
1912 self.full_name = full_name
1913 self.module = module
1914 self.cls = cls
1915 self.parent = cls or module
1916 self.c_basename = c_basename
1917 self.return_converter = return_converter
1918 self.docstring = docstring or ''
1919 self.kind = kind
1920 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08001921 self.self_converter = None
Larry Hastings2623c8c2014-02-08 22:15:29 -08001922 # docstring_only means "don't generate a machine-readable
1923 # signature, just a normal docstring". it's True for
1924 # functions with optional groups because we can't represent
1925 # those accurately with inspect.Signature in 3.4.
1926 self.docstring_only = docstring_only
Larry Hastingsebdcb502013-11-23 14:54:00 -08001927
Larry Hastings7726ac92014-01-31 22:03:12 -08001928 self.rendered_parameters = None
1929
1930 __render_parameters__ = None
1931 @property
1932 def render_parameters(self):
1933 if not self.__render_parameters__:
1934 self.__render_parameters__ = l = []
1935 for p in self.parameters.values():
1936 p = p.copy()
1937 p.converter.pre_render()
1938 l.append(p)
1939 return self.__render_parameters__
1940
Larry Hastingsebdcb502013-11-23 14:54:00 -08001941 @property
1942 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08001943 if self.kind in (METHOD_INIT, METHOD_NEW):
1944 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001945 flags = []
1946 if self.kind == CLASS_METHOD:
1947 flags.append('METH_CLASS')
1948 elif self.kind == STATIC_METHOD:
1949 flags.append('METH_STATIC')
1950 else:
1951 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
1952 if self.coexist:
1953 flags.append('METH_COEXIST')
1954 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07001955
1956 def __repr__(self):
1957 return '<clinic.Function ' + self.name + '>'
1958
Larry Hastings7726ac92014-01-31 22:03:12 -08001959 def copy(self, **overrides):
1960 kwargs = {
1961 'name': self.name, 'module': self.module, 'parameters': self.parameters,
1962 'cls': self.cls, 'c_basename': self.c_basename,
1963 'full_name': self.full_name,
1964 'return_converter': self.return_converter, 'return_annotation': self.return_annotation,
1965 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist,
Larry Hastings2623c8c2014-02-08 22:15:29 -08001966 'docstring_only': self.docstring_only,
Larry Hastings7726ac92014-01-31 22:03:12 -08001967 }
1968 kwargs.update(overrides)
1969 f = Function(**kwargs)
1970
1971 parameters = collections.OrderedDict()
1972 for name, value in f.parameters.items():
1973 value = value.copy(function=f)
1974 parameters[name] = value
1975 f.parameters = parameters
1976 return f
1977
Larry Hastings31826802013-10-19 00:09:25 -07001978
1979class Parameter:
1980 """
1981 Mutable duck type of inspect.Parameter.
1982 """
1983
1984 def __init__(self, name, kind, *, default=_empty,
1985 function, converter, annotation=_empty,
1986 docstring=None, group=0):
1987 self.name = name
1988 self.kind = kind
1989 self.default = default
1990 self.function = function
1991 self.converter = converter
1992 self.annotation = annotation
1993 self.docstring = docstring or ''
1994 self.group = group
1995
1996 def __repr__(self):
1997 return '<clinic.Parameter ' + self.name + '>'
1998
1999 def is_keyword_only(self):
2000 return self.kind == inspect.Parameter.KEYWORD_ONLY
2001
Larry Hastings2623c8c2014-02-08 22:15:29 -08002002 def is_positional_only(self):
2003 return self.kind == inspect.Parameter.POSITIONAL_ONLY
2004
Larry Hastings7726ac92014-01-31 22:03:12 -08002005 def copy(self, **overrides):
2006 kwargs = {
2007 'name': self.name, 'kind': self.kind, 'default':self.default,
2008 'function': self.function, 'converter': self.converter, 'annotation': self.annotation,
2009 'docstring': self.docstring, 'group': self.group,
2010 }
2011 kwargs.update(overrides)
2012 if 'converter' not in overrides:
2013 converter = copy.copy(self.converter)
2014 converter.function = kwargs['function']
2015 kwargs['converter'] = converter
2016 return Parameter(**kwargs)
2017
2018
2019
2020class LandMine:
2021 # try to access any
2022 def __init__(self, message):
2023 self.__message__ = message
2024
2025 def __repr__(self):
2026 return '<LandMine ' + repr(self.__message__) + ">"
2027
2028 def __getattribute__(self, name):
2029 if name in ('__repr__', '__message__'):
2030 return super().__getattribute__(name)
2031 # raise RuntimeError(repr(name))
2032 fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__)
Larry Hastings31826802013-10-19 00:09:25 -07002033
Larry Hastings31826802013-10-19 00:09:25 -07002034
2035def add_c_converter(f, name=None):
2036 if not name:
2037 name = f.__name__
2038 if not name.endswith('_converter'):
2039 return f
2040 name = name[:-len('_converter')]
2041 converters[name] = f
2042 return f
2043
2044def add_default_legacy_c_converter(cls):
2045 # automatically add converter for default format unit
2046 # (but without stomping on the existing one if it's already
2047 # set, in case you subclass)
Larry Hastingsf1503782014-06-11 04:31:29 -07002048 if ((cls.format_unit not in ('O&', '')) and
Larry Hastings31826802013-10-19 00:09:25 -07002049 (cls.format_unit not in legacy_converters)):
2050 legacy_converters[cls.format_unit] = cls
2051 return cls
2052
2053def add_legacy_c_converter(format_unit, **kwargs):
2054 """
2055 Adds a legacy converter.
2056 """
2057 def closure(f):
2058 if not kwargs:
2059 added_f = f
2060 else:
2061 added_f = functools.partial(f, **kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002062 if format_unit:
2063 legacy_converters[format_unit] = added_f
Larry Hastings31826802013-10-19 00:09:25 -07002064 return f
2065 return closure
2066
2067class CConverterAutoRegister(type):
2068 def __init__(cls, name, bases, classdict):
2069 add_c_converter(cls)
2070 add_default_legacy_c_converter(cls)
2071
2072class CConverter(metaclass=CConverterAutoRegister):
2073 """
2074 For the init function, self, name, function, and default
2075 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08002076 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07002077 """
2078
Larry Hastings7726ac92014-01-31 22:03:12 -08002079 # The C name to use for this variable.
2080 name = None
2081
2082 # The Python name to use for this variable.
2083 py_name = None
2084
Larry Hastings78cf85c2014-01-04 12:44:57 -08002085 # The C type to use for this variable.
2086 # 'type' should be a Python string specifying the type, e.g. "int".
2087 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002088 type = None
Larry Hastings31826802013-10-19 00:09:25 -07002089
2090 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08002091 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08002092 # Or the magic value "unknown" if this value is a cannot be evaluated
2093 # at Argument-Clinic-preprocessing time (but is presumed to be valid
2094 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07002095 default = unspecified
2096
Larry Hastings4a55fc52014-01-12 11:09:57 -08002097 # If not None, default must be isinstance() of this type.
2098 # (You can also specify a tuple of types.)
2099 default_type = None
2100
Larry Hastings31826802013-10-19 00:09:25 -07002101 # "default" converted into a C value, as a string.
2102 # Or None if there is no default.
2103 c_default = None
2104
Larry Hastings2a727912014-01-16 11:32:01 -08002105 # "default" converted into a Python value, as a string.
2106 # Or None if there is no default.
2107 py_default = None
2108
Larry Hastingsabc716b2013-11-20 09:13:52 -08002109 # The default value used to initialize the C variable when
2110 # there is no default, but not specifying a default may
2111 # result in an "uninitialized variable" warning. This can
2112 # easily happen when using option groups--although
2113 # properly-written code won't actually use the variable,
2114 # the variable does get passed in to the _impl. (Ah, if
2115 # only dataflow analysis could inline the static function!)
2116 #
2117 # This value is specified as a string.
2118 # Every non-abstract subclass should supply a valid value.
2119 c_ignored_default = 'NULL'
2120
Larry Hastings31826802013-10-19 00:09:25 -07002121 # The C converter *function* to be used, if any.
2122 # (If this is not None, format_unit must be 'O&'.)
2123 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002124
Larry Hastings78cf85c2014-01-04 12:44:57 -08002125 # Should Argument Clinic add a '&' before the name of
2126 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07002127 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08002128
2129 # Should Argument Clinic add a '&' before the name of
2130 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07002131 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08002132
2133 #############################################################
2134 #############################################################
2135 ## You shouldn't need to read anything below this point to ##
2136 ## write your own converter functions. ##
2137 #############################################################
2138 #############################################################
2139
2140 # The "format unit" to specify for this variable when
2141 # parsing arguments using PyArg_ParseTuple (AndKeywords).
2142 # Custom converters should always use the default value of 'O&'.
2143 format_unit = 'O&'
2144
2145 # What encoding do we want for this variable? Only used
2146 # by format units starting with 'e'.
2147 encoding = None
2148
Larry Hastings77561cc2014-01-07 12:13:13 -08002149 # Should this object be required to be a subclass of a specific type?
2150 # If not None, should be a string representing a pointer to a
2151 # PyTypeObject (e.g. "&PyUnicode_Type").
2152 # Only used by the 'O!' format unit (and the "object" converter).
2153 subclass_of = None
2154
Larry Hastings78cf85c2014-01-04 12:44:57 -08002155 # Do we want an adjacent '_length' variable for this variable?
2156 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07002157 length = False
2158
Larry Hastings5c661892014-01-24 06:17:25 -08002159 # Should we show this parameter in the generated
2160 # __text_signature__? This is *almost* always True.
Larry Hastingsc2047262014-01-25 20:43:29 -08002161 # (It's only False for __new__, __init__, and METH_STATIC functions.)
Larry Hastings5c661892014-01-24 06:17:25 -08002162 show_in_signature = True
2163
2164 # Overrides the name used in a text signature.
2165 # The name used for a "self" parameter must be one of
2166 # self, type, or module; however users can set their own.
2167 # This lets the self_converter overrule the user-settable
2168 # name, *just* for the text signature.
2169 # Only set by self_converter.
2170 signature_name = None
2171
2172 # keep in sync with self_converter.__init__!
Larry Hastings7726ac92014-01-31 22:03:12 -08002173 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 -07002174 self.name = name
Larry Hastings7726ac92014-01-31 22:03:12 -08002175 self.py_name = py_name
Larry Hastings31826802013-10-19 00:09:25 -07002176
2177 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08002178 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002179 if isinstance(self.default_type, type):
2180 types_str = self.default_type.__name__
2181 else:
2182 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2183 fail("{}: default value {!r} for field {} is not of type {}".format(
2184 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002185 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002186
Larry Hastingsb4705752014-01-18 21:54:15 -08002187 if c_default:
2188 self.c_default = c_default
2189 if py_default:
2190 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002191
Larry Hastings31826802013-10-19 00:09:25 -07002192 if annotation != unspecified:
2193 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings7726ac92014-01-31 22:03:12 -08002194
2195 # this is deliberate, to prevent you from caching information
2196 # about the function in the init.
2197 # (that breaks if we get cloned.)
2198 # so after this change we will noisily fail.
2199 self.function = LandMine("Don't access members of self.function inside converter_init!")
Larry Hastings31826802013-10-19 00:09:25 -07002200 self.converter_init(**kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002201 self.function = function
Larry Hastings31826802013-10-19 00:09:25 -07002202
2203 def converter_init(self):
2204 pass
2205
2206 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002207 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002208
Larry Hastings5c661892014-01-24 06:17:25 -08002209 def _render_self(self, parameter, data):
2210 self.parameter = parameter
2211 original_name = self.name
2212 name = ensure_legal_c_identifier(original_name)
2213
2214 # impl_arguments
2215 s = ("&" if self.impl_by_reference else "") + name
2216 data.impl_arguments.append(s)
2217 if self.length:
2218 data.impl_arguments.append(self.length_name())
2219
2220 # impl_parameters
2221 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2222 if self.length:
2223 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2224
2225 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002226 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002227 original_name = self.name
2228 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002229
2230 # declarations
2231 d = self.declaration()
2232 data.declarations.append(d)
2233
2234 # initializers
2235 initializers = self.initialize()
2236 if initializers:
2237 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2238
Larry Hastingsc2047262014-01-25 20:43:29 -08002239 # modifications
2240 modifications = self.modify()
2241 if modifications:
2242 data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2243
Larry Hastings31826802013-10-19 00:09:25 -07002244 # keywords
Larry Hastings7726ac92014-01-31 22:03:12 -08002245 data.keywords.append(parameter.name)
Larry Hastings31826802013-10-19 00:09:25 -07002246
2247 # format_units
2248 if self.is_optional() and '|' not in data.format_units:
2249 data.format_units.append('|')
2250 if parameter.is_keyword_only() and '$' not in data.format_units:
2251 data.format_units.append('$')
2252 data.format_units.append(self.format_unit)
2253
2254 # parse_arguments
2255 self.parse_argument(data.parse_arguments)
2256
Larry Hastings31826802013-10-19 00:09:25 -07002257 # cleanup
2258 cleanup = self.cleanup()
2259 if cleanup:
2260 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2261
Larry Hastings5c661892014-01-24 06:17:25 -08002262 def render(self, parameter, data):
2263 """
2264 parameter is a clinic.Parameter instance.
2265 data is a CRenderData instance.
2266 """
2267 self._render_self(parameter, data)
2268 self._render_non_self(parameter, data)
2269
Larry Hastingsebdcb502013-11-23 14:54:00 -08002270 def length_name(self):
2271 """Computes the name of the associated "length" variable."""
2272 if not self.length:
2273 return None
2274 return ensure_legal_c_identifier(self.name) + "_length"
2275
Larry Hastings31826802013-10-19 00:09:25 -07002276 # Why is this one broken out separately?
2277 # For "positional-only" function parsing,
2278 # which generates a bunch of PyArg_ParseTuple calls.
2279 def parse_argument(self, list):
2280 assert not (self.converter and self.encoding)
2281 if self.format_unit == 'O&':
2282 assert self.converter
2283 list.append(self.converter)
2284
2285 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002286 list.append(c_repr(self.encoding))
2287 elif self.subclass_of:
2288 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002289
Larry Hastingsebdcb502013-11-23 14:54:00 -08002290 legal_name = ensure_legal_c_identifier(self.name)
2291 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002292 list.append(s)
2293
Larry Hastingsebdcb502013-11-23 14:54:00 -08002294 if self.length:
2295 list.append("&" + self.length_name())
2296
Larry Hastings31826802013-10-19 00:09:25 -07002297 #
2298 # All the functions after here are intended as extension points.
2299 #
2300
2301 def simple_declaration(self, by_reference=False):
2302 """
2303 Computes the basic declaration of the variable.
2304 Used in computing the prototype declaration and the
2305 variable declaration.
2306 """
2307 prototype = [self.type]
2308 if by_reference or not self.type.endswith('*'):
2309 prototype.append(" ")
2310 if by_reference:
2311 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002312 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002313 return "".join(prototype)
2314
2315 def declaration(self):
2316 """
2317 The C statement to declare this variable.
2318 """
2319 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002320 default = self.c_default
2321 if not default and self.parameter.group:
2322 default = self.c_ignored_default
2323 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002324 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002325 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002326 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002327 if self.length:
2328 declaration.append('\nPy_ssize_clean_t ')
2329 declaration.append(self.length_name())
2330 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002331 s = "".join(declaration)
2332 # double up curly-braces, this string will be used
2333 # as part of a format_map() template later
2334 s = s.replace("{", "{{")
2335 s = s.replace("}", "}}")
2336 return s
Larry Hastings31826802013-10-19 00:09:25 -07002337
2338 def initialize(self):
2339 """
2340 The C statements required to set up this variable before parsing.
2341 Returns a string containing this code indented at column 0.
2342 If no initialization is necessary, returns an empty string.
2343 """
2344 return ""
2345
Larry Hastingsc2047262014-01-25 20:43:29 -08002346 def modify(self):
2347 """
2348 The C statements required to modify this variable after parsing.
2349 Returns a string containing this code indented at column 0.
2350 If no initialization is necessary, returns an empty string.
2351 """
2352 return ""
2353
Larry Hastings31826802013-10-19 00:09:25 -07002354 def cleanup(self):
2355 """
2356 The C statements required to clean up after this variable.
2357 Returns a string containing this code indented at column 0.
2358 If no cleanup is necessary, returns an empty string.
2359 """
2360 return ""
2361
Larry Hastings7726ac92014-01-31 22:03:12 -08002362 def pre_render(self):
2363 """
2364 A second initialization function, like converter_init,
2365 called just before rendering.
2366 You are permitted to examine self.function here.
2367 """
2368 pass
2369
Larry Hastings31826802013-10-19 00:09:25 -07002370
2371class bool_converter(CConverter):
2372 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002373 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002374 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002375 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002376
2377 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002378 if self.default is not unspecified:
2379 self.default = bool(self.default)
2380 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002381
2382class char_converter(CConverter):
2383 type = 'char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002384 default_type = str
Larry Hastings31826802013-10-19 00:09:25 -07002385 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002386 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002387
Larry Hastings4a55fc52014-01-12 11:09:57 -08002388 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002389 if isinstance(self.default, str) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002390 fail("char_converter: illegal default value " + repr(self.default))
2391
2392
Larry Hastings31826802013-10-19 00:09:25 -07002393@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002394class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002395 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002396 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002397 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002398 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002399
2400 def converter_init(self, *, bitwise=False):
2401 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002402 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002403
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002404class byte_converter(unsigned_char_converter): pass
2405
Larry Hastings31826802013-10-19 00:09:25 -07002406class short_converter(CConverter):
2407 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002408 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002409 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002410 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002411
2412class unsigned_short_converter(CConverter):
2413 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002414 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002415 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002416 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002417
2418 def converter_init(self, *, bitwise=False):
2419 if not bitwise:
2420 fail("Unsigned shorts must be bitwise (for now).")
2421
Larry Hastingsebdcb502013-11-23 14:54:00 -08002422@add_legacy_c_converter('C', types='str')
Larry Hastings31826802013-10-19 00:09:25 -07002423class int_converter(CConverter):
2424 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002425 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002426 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002427 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002428
Larry Hastingsdfbeb162014-10-13 10:39:41 +01002429 def converter_init(self, *, types='int', type=None):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002430 if types == 'str':
2431 self.format_unit = 'C'
2432 elif types != 'int':
2433 fail("int_converter: illegal 'types' argument")
Larry Hastingsdfbeb162014-10-13 10:39:41 +01002434 if type != None:
2435 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002436
2437class unsigned_int_converter(CConverter):
2438 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002439 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002440 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002441 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002442
2443 def converter_init(self, *, bitwise=False):
2444 if not bitwise:
2445 fail("Unsigned ints must be bitwise (for now).")
2446
2447class long_converter(CConverter):
2448 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002449 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002450 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002451 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002452
2453class unsigned_long_converter(CConverter):
2454 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002455 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002456 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002457 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002458
2459 def converter_init(self, *, bitwise=False):
2460 if not bitwise:
2461 fail("Unsigned longs must be bitwise (for now).")
2462
2463class PY_LONG_LONG_converter(CConverter):
2464 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002465 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002466 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002467 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002468
2469class unsigned_PY_LONG_LONG_converter(CConverter):
2470 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002471 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002472 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002473 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002474
2475 def converter_init(self, *, bitwise=False):
2476 if not bitwise:
2477 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2478
2479class Py_ssize_t_converter(CConverter):
2480 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002481 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002482 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002483 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002484
2485
2486class float_converter(CConverter):
2487 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002488 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002489 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002490 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002491
2492class double_converter(CConverter):
2493 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002494 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002495 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002496 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002497
2498
2499class Py_complex_converter(CConverter):
2500 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002501 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002502 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002503 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002504
2505
2506class object_converter(CConverter):
2507 type = 'PyObject *'
2508 format_unit = 'O'
2509
Larry Hastings4a55fc52014-01-12 11:09:57 -08002510 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2511 if converter:
2512 if subclass_of:
2513 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2514 self.format_unit = 'O&'
2515 self.converter = converter
2516 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002517 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002518 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002519
Larry Hastings77561cc2014-01-07 12:13:13 -08002520 if type is not None:
2521 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002522
2523
Larry Hastingsebdcb502013-11-23 14:54:00 -08002524@add_legacy_c_converter('s#', length=True)
Larry Hastings2a727912014-01-16 11:32:01 -08002525@add_legacy_c_converter('y', types="bytes")
2526@add_legacy_c_converter('y#', types="bytes", length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002527@add_legacy_c_converter('z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002528@add_legacy_c_converter('z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002529class str_converter(CConverter):
2530 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002531 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002532 format_unit = 's'
2533
Larry Hastingsebdcb502013-11-23 14:54:00 -08002534 def converter_init(self, *, encoding=None, types="str",
2535 length=False, nullable=False, zeroes=False):
2536
2537 types = set(types.strip().split())
2538 bytes_type = set(("bytes",))
2539 str_type = set(("str",))
2540 all_3_type = set(("bytearray",)) | bytes_type | str_type
2541 is_bytes = types == bytes_type
2542 is_str = types == str_type
2543 is_all_3 = types == all_3_type
2544
2545 self.length = bool(length)
2546 format_unit = None
2547
2548 if encoding:
2549 self.encoding = encoding
2550
2551 if is_str and not (length or zeroes or nullable):
2552 format_unit = 'es'
2553 elif is_all_3 and not (length or zeroes or nullable):
2554 format_unit = 'et'
2555 elif is_str and length and zeroes and not nullable:
2556 format_unit = 'es#'
2557 elif is_all_3 and length and not (nullable or zeroes):
2558 format_unit = 'et#'
2559
2560 if format_unit.endswith('#'):
Larry Hastings5c661892014-01-24 06:17:25 -08002561 fail("Sorry: code using format unit ", repr(format_unit), "probably doesn't work properly yet.\nGive Larry your test case and he'll it.")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002562 # TODO set pointer to NULL
2563 # TODO add cleanup for buffer
2564 pass
2565
2566 else:
2567 if zeroes:
2568 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
2569
2570 if is_bytes and not (nullable or length):
2571 format_unit = 'y'
2572 elif is_bytes and length and not nullable:
2573 format_unit = 'y#'
2574 elif is_str and not (nullable or length):
2575 format_unit = 's'
2576 elif is_str and length and not nullable:
2577 format_unit = 's#'
2578 elif is_str and nullable and not length:
2579 format_unit = 'z'
2580 elif is_str and nullable and length:
2581 format_unit = 'z#'
2582
2583 if not format_unit:
2584 fail("str_converter: illegal combination of arguments")
2585 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002586
2587
2588class PyBytesObject_converter(CConverter):
2589 type = 'PyBytesObject *'
2590 format_unit = 'S'
2591
2592class PyByteArrayObject_converter(CConverter):
2593 type = 'PyByteArrayObject *'
2594 format_unit = 'Y'
2595
2596class unicode_converter(CConverter):
2597 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002598 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002599 format_unit = 'U'
2600
Larry Hastingsebdcb502013-11-23 14:54:00 -08002601@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002602@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002603@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002604class Py_UNICODE_converter(CConverter):
2605 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002606 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002607 format_unit = 'u'
2608
Larry Hastingsebdcb502013-11-23 14:54:00 -08002609 def converter_init(self, *, nullable=False, length=False):
2610 format_unit = 'Z' if nullable else 'u'
2611 if length:
2612 format_unit += '#'
2613 self.length = True
2614 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002615
Larry Hastingsebdcb502013-11-23 14:54:00 -08002616#
2617# We define three string conventions for buffer types in the 'types' argument:
2618# 'buffer' : any object supporting the buffer interface
2619# 'rwbuffer': any object supporting the buffer interface, but must be writeable
2620# 'robuffer': any object supporting the buffer interface, but must not be writeable
2621#
2622@add_legacy_c_converter('s*', types='str bytes bytearray buffer')
2623@add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True)
2624@add_legacy_c_converter('w*', types='bytearray rwbuffer')
Larry Hastings31826802013-10-19 00:09:25 -07002625class Py_buffer_converter(CConverter):
2626 type = 'Py_buffer'
2627 format_unit = 'y*'
2628 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002629 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002630
Larry Hastingsebdcb502013-11-23 14:54:00 -08002631 def converter_init(self, *, types='bytes bytearray buffer', nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002632 if self.default not in (unspecified, None):
2633 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08002634 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002635 types = set(types.strip().split())
2636 bytes_type = set(('bytes',))
2637 bytearray_type = set(('bytearray',))
2638 buffer_type = set(('buffer',))
2639 rwbuffer_type = set(('rwbuffer',))
2640 robuffer_type = set(('robuffer',))
2641 str_type = set(('str',))
2642 bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type
2643
2644 format_unit = None
2645 if types == (str_type | bytes_bytearray_buffer_type):
2646 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07002647 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002648 if nullable:
2649 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
2650 elif types == (bytes_bytearray_buffer_type):
2651 format_unit = 'y*'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002652 elif types == (bytearray_type | rwbuffer_type):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002653 format_unit = 'w*'
2654 if not format_unit:
2655 fail("Py_buffer_converter: illegal combination of arguments")
2656
2657 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002658
2659 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002660 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002661 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002662
2663
Larry Hastings5c661892014-01-24 06:17:25 -08002664def correct_name_for_self(f):
2665 if f.kind in (CALLABLE, METHOD_INIT):
2666 if f.cls:
2667 return "PyObject *", "self"
2668 return "PyModuleDef *", "module"
2669 if f.kind == STATIC_METHOD:
2670 return "void *", "null"
2671 if f.kind in (CLASS_METHOD, METHOD_NEW):
2672 return "PyTypeObject *", "type"
2673 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2674
Larry Hastingsc2047262014-01-25 20:43:29 -08002675def required_type_for_self_for_parser(f):
2676 type, _ = correct_name_for_self(f)
2677 if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2678 return type
2679 return None
2680
Larry Hastings5c661892014-01-24 06:17:25 -08002681
Larry Hastingsebdcb502013-11-23 14:54:00 -08002682class self_converter(CConverter):
2683 """
2684 A special-case converter:
2685 this is the default converter used for "self".
2686 """
Larry Hastings5c661892014-01-24 06:17:25 -08002687 type = None
2688 format_unit = ''
2689
Larry Hastings78cf85c2014-01-04 12:44:57 -08002690 def converter_init(self, *, type=None):
Larry Hastings7726ac92014-01-31 22:03:12 -08002691 self.specified_type = type
2692
2693 def pre_render(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002694 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002695 default_type, default_name = correct_name_for_self(f)
2696 self.signature_name = default_name
Larry Hastings7726ac92014-01-31 22:03:12 -08002697 self.type = self.specified_type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002698
Larry Hastings5c661892014-01-24 06:17:25 -08002699 kind = self.function.kind
2700 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2701
2702 if (kind == STATIC_METHOD) or new_or_init:
2703 self.show_in_signature = False
2704
2705 # tp_new (METHOD_NEW) functions are of type newfunc:
2706 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2707 # PyTypeObject is a typedef for struct _typeobject.
2708 #
2709 # tp_init (METHOD_INIT) functions are of type initproc:
2710 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2711 #
2712 # All other functions generated by Argument Clinic are stored in
2713 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2714 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2715 # However! We habitually cast these functions to PyCFunction,
2716 # since functions that accept keyword arguments don't fit this signature
2717 # but are stored there anyway. So strict type equality isn't important
2718 # for these functions.
2719 #
2720 # So:
2721 #
2722 # * The name of the first parameter to the impl and the parsing function will always
2723 # be self.name.
2724 #
2725 # * The type of the first parameter to the impl will always be of self.type.
2726 #
2727 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2728 # * The type of the first parameter to the parsing function is also self.type.
2729 # This means that if you step into the parsing function, your "self" parameter
2730 # is of the correct type, which may make debugging more pleasant.
2731 #
2732 # * Else if the function is tp_new (METHOD_NEW):
2733 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2734 # so the type signature of the function call is an exact match.
2735 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2736 # in the impl call.
2737 #
2738 # * Else if the function is tp_init (METHOD_INIT):
2739 # * The type of the first parameter to the parsing function is "PyObject *",
2740 # so the type signature of the function call is an exact match.
2741 # * If self.type != "PyObject *", we cast the first parameter to self.type
2742 # in the impl call.
2743
2744 @property
2745 def parser_type(self):
Larry Hastingsc2047262014-01-25 20:43:29 -08002746 return required_type_for_self_for_parser(self.function) or self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002747
Larry Hastingsebdcb502013-11-23 14:54:00 -08002748 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002749 """
2750 parameter is a clinic.Parameter instance.
2751 data is a CRenderData instance.
2752 """
2753 if self.function.kind == STATIC_METHOD:
2754 return
2755
2756 self._render_self(parameter, data)
2757
2758 if self.type != self.parser_type:
2759 # insert cast to impl_argument[0], aka self.
2760 # we know we're in the first slot in all the CRenderData lists,
2761 # because we render parameters in order, and self is always first.
2762 assert len(data.impl_arguments) == 1
2763 assert data.impl_arguments[0] == self.name
2764 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2765
2766 def set_template_dict(self, template_dict):
2767 template_dict['self_name'] = self.name
2768 template_dict['self_type'] = self.parser_type
Larry Hastingsf0537e82014-01-25 22:01:12 -08002769 kind = self.function.kind
2770 cls = self.function.cls
2771
2772 if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef):
2773 if kind == METHOD_NEW:
2774 passed_in_type = self.name
2775 else:
2776 passed_in_type = 'Py_TYPE({})'.format(self.name)
2777
2778 line = '({passed_in_type} == {type_object}) &&\n '
2779 d = {
2780 'type_object': self.function.cls.type_object,
2781 'passed_in_type': passed_in_type
2782 }
2783 template_dict['self_type_check'] = line.format_map(d)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002784
Larry Hastings31826802013-10-19 00:09:25 -07002785
2786
2787def add_c_return_converter(f, name=None):
2788 if not name:
2789 name = f.__name__
2790 if not name.endswith('_return_converter'):
2791 return f
2792 name = name[:-len('_return_converter')]
2793 return_converters[name] = f
2794 return f
2795
2796
2797class CReturnConverterAutoRegister(type):
2798 def __init__(cls, name, bases, classdict):
2799 add_c_return_converter(cls)
2800
2801class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2802
Larry Hastings78cf85c2014-01-04 12:44:57 -08002803 # The C type to use for this variable.
2804 # 'type' should be a Python string specifying the type, e.g. "int".
2805 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002806 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002807
2808 # The Python default value for this parameter, as a Python value.
2809 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002810 default = None
2811
Larry Hastings2a727912014-01-16 11:32:01 -08002812 def __init__(self, *, py_default=None, **kwargs):
2813 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002814 try:
2815 self.return_converter_init(**kwargs)
2816 except TypeError as e:
2817 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2818 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2819
2820 def return_converter_init(self):
2821 pass
2822
2823 def declare(self, data, name="_return_value"):
2824 line = []
2825 add = line.append
2826 add(self.type)
2827 if not self.type.endswith('*'):
2828 add(' ')
2829 add(name + ';')
2830 data.declarations.append(''.join(line))
2831 data.return_value = name
2832
2833 def err_occurred_if(self, expr, data):
2834 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2835
2836 def err_occurred_if_null_pointer(self, variable, data):
2837 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2838
2839 def render(self, function, data):
2840 """
2841 function is a clinic.Function instance.
2842 data is a CRenderData instance.
2843 """
2844 pass
2845
2846add_c_return_converter(CReturnConverter, 'object')
2847
Larry Hastings78cf85c2014-01-04 12:44:57 -08002848class NoneType_return_converter(CReturnConverter):
2849 def render(self, function, data):
2850 self.declare(data)
2851 data.return_conversion.append('''
2852if (_return_value != Py_None)
2853 goto exit;
2854return_value = Py_None;
2855Py_INCREF(Py_None);
2856'''.strip())
2857
Larry Hastings4a55fc52014-01-12 11:09:57 -08002858class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002859 type = 'int'
2860
2861 def render(self, function, data):
2862 self.declare(data)
2863 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002864 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002865
2866class long_return_converter(CReturnConverter):
2867 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002868 conversion_fn = 'PyLong_FromLong'
2869 cast = ''
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002870 unsigned_cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002871
2872 def render(self, function, data):
2873 self.declare(data)
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002874 self.err_occurred_if("_return_value == {}-1".format(self.unsigned_cast), data)
Larry Hastings31826802013-10-19 00:09:25 -07002875 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002876 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002877
Larry Hastings4a55fc52014-01-12 11:09:57 -08002878class int_return_converter(long_return_converter):
2879 type = 'int'
2880 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002881
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002882class init_return_converter(long_return_converter):
2883 """
2884 Special return converter for __init__ functions.
2885 """
2886 type = 'int'
2887 cast = '(long)'
2888
2889 def render(self, function, data):
2890 pass
2891
Larry Hastings4a55fc52014-01-12 11:09:57 -08002892class unsigned_long_return_converter(long_return_converter):
2893 type = 'unsigned long'
2894 conversion_fn = 'PyLong_FromUnsignedLong'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002895 unsigned_cast = '(unsigned long)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002896
2897class unsigned_int_return_converter(unsigned_long_return_converter):
2898 type = 'unsigned int'
2899 cast = '(unsigned long)'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002900 unsigned_cast = '(unsigned int)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002901
2902class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07002903 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002904 conversion_fn = 'PyLong_FromSsize_t'
2905
2906class size_t_return_converter(long_return_converter):
2907 type = 'size_t'
2908 conversion_fn = 'PyLong_FromSize_t'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002909 unsigned_cast = '(size_t)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002910
2911
2912class double_return_converter(CReturnConverter):
2913 type = 'double'
2914 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002915
2916 def render(self, function, data):
2917 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002918 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07002919 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002920 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
2921
2922class float_return_converter(double_return_converter):
2923 type = 'float'
2924 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07002925
2926
2927class DecodeFSDefault_return_converter(CReturnConverter):
2928 type = 'char *'
2929
2930 def render(self, function, data):
2931 self.declare(data)
2932 self.err_occurred_if_null_pointer("_return_value", data)
2933 data.return_conversion.append(
2934 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
2935
2936
2937class IndentStack:
2938 def __init__(self):
2939 self.indents = []
2940 self.margin = None
2941
2942 def _ensure(self):
2943 if not self.indents:
2944 fail('IndentStack expected indents, but none are defined.')
2945
2946 def measure(self, line):
2947 """
2948 Returns the length of the line's margin.
2949 """
2950 if '\t' in line:
Larry Hastings2623c8c2014-02-08 22:15:29 -08002951 fail('Tab characters are illegal in the Argument Clinic DSL.')
Larry Hastings31826802013-10-19 00:09:25 -07002952 stripped = line.lstrip()
2953 if not len(stripped):
2954 # we can't tell anything from an empty line
2955 # so just pretend it's indented like our current indent
2956 self._ensure()
2957 return self.indents[-1]
2958 return len(line) - len(stripped)
2959
2960 def infer(self, line):
2961 """
2962 Infer what is now the current margin based on this line.
2963 Returns:
2964 1 if we have indented (or this is the first margin)
2965 0 if the margin has not changed
2966 -N if we have dedented N times
2967 """
2968 indent = self.measure(line)
2969 margin = ' ' * indent
2970 if not self.indents:
2971 self.indents.append(indent)
2972 self.margin = margin
2973 return 1
2974 current = self.indents[-1]
2975 if indent == current:
2976 return 0
2977 if indent > current:
2978 self.indents.append(indent)
2979 self.margin = margin
2980 return 1
2981 # indent < current
2982 if indent not in self.indents:
2983 fail("Illegal outdent.")
2984 outdent_count = 0
2985 while indent != current:
2986 self.indents.pop()
2987 current = self.indents[-1]
2988 outdent_count -= 1
2989 self.margin = margin
2990 return outdent_count
2991
2992 @property
2993 def depth(self):
2994 """
2995 Returns how many margins are currently defined.
2996 """
2997 return len(self.indents)
2998
2999 def indent(self, line):
3000 """
3001 Indents a line by the currently defined margin.
3002 """
3003 return self.margin + line
3004
3005 def dedent(self, line):
3006 """
3007 Dedents a line by the currently defined margin.
3008 (The inverse of 'indent'.)
3009 """
3010 margin = self.margin
3011 indent = self.indents[-1]
3012 if not line.startswith(margin):
3013 fail('Cannot dedent, line does not start with the previous margin:')
3014 return line[indent:]
3015
3016
3017class DSLParser:
3018 def __init__(self, clinic):
3019 self.clinic = clinic
3020
3021 self.directives = {}
3022 for name in dir(self):
3023 # functions that start with directive_ are added to directives
3024 _, s, key = name.partition("directive_")
3025 if s:
3026 self.directives[key] = getattr(self, name)
3027
3028 # functions that start with at_ are too, with an @ in front
3029 _, s, key = name.partition("at_")
3030 if s:
3031 self.directives['@' + key] = getattr(self, name)
3032
3033 self.reset()
3034
3035 def reset(self):
3036 self.function = None
3037 self.state = self.state_dsl_start
3038 self.parameter_indent = None
3039 self.keyword_only = False
3040 self.group = 0
3041 self.parameter_state = self.ps_start
Larry Hastingsc2047262014-01-25 20:43:29 -08003042 self.seen_positional_with_default = False
Larry Hastings31826802013-10-19 00:09:25 -07003043 self.indent = IndentStack()
3044 self.kind = CALLABLE
3045 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08003046 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08003047 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07003048
Larry Hastingsebdcb502013-11-23 14:54:00 -08003049 def directive_version(self, required):
3050 global version
3051 if version_comparitor(version, required) < 0:
3052 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
3053
Larry Hastings31826802013-10-19 00:09:25 -07003054 def directive_module(self, name):
3055 fields = name.split('.')
3056 new = fields.pop()
3057 module, cls = self.clinic._module_and_class(fields)
3058 if cls:
3059 fail("Can't nest a module inside a class!")
Larry Hastingsc2047262014-01-25 20:43:29 -08003060
3061 if name in module.classes:
3062 fail("Already defined module " + repr(name) + "!")
3063
Larry Hastings31826802013-10-19 00:09:25 -07003064 m = Module(name, module)
3065 module.modules[name] = m
3066 self.block.signatures.append(m)
3067
Larry Hastingsc2047262014-01-25 20:43:29 -08003068 def directive_class(self, name, typedef, type_object):
Larry Hastings31826802013-10-19 00:09:25 -07003069 fields = name.split('.')
3070 in_classes = False
3071 parent = self
3072 name = fields.pop()
3073 so_far = []
3074 module, cls = self.clinic._module_and_class(fields)
3075
Larry Hastingsc2047262014-01-25 20:43:29 -08003076 parent = cls or module
3077 if name in parent.classes:
3078 fail("Already defined class " + repr(name) + "!")
3079
3080 c = Class(name, module, cls, typedef, type_object)
3081 parent.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07003082 self.block.signatures.append(c)
3083
Larry Hastingsbebf7352014-01-17 17:47:17 -08003084 def directive_set(self, name, value):
3085 if name not in ("line_prefix", "line_suffix"):
3086 fail("unknown variable", repr(name))
3087
3088 value = value.format_map({
3089 'block comment start': '/*',
3090 'block comment end': '*/',
3091 })
3092
3093 self.clinic.__dict__[name] = value
3094
3095 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06003096 if command == 'new':
3097 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003098 return
3099
Zachary Ware071baa62014-01-21 23:07:12 -06003100 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08003101 self.clinic.get_destination(name).clear()
3102 fail("unknown destination command", repr(command))
3103
3104
3105 def directive_output(self, field, destination=''):
3106 fd = self.clinic.field_destinations
3107
3108 if field == "preset":
3109 preset = self.clinic.presets.get(destination)
3110 if not preset:
3111 fail("Unknown preset " + repr(destination) + "!")
3112 fd.update(preset)
3113 return
3114
3115 if field == "push":
3116 self.clinic.field_destinations_stack.append(fd.copy())
3117 return
3118
3119 if field == "pop":
3120 if not self.clinic.field_destinations_stack:
3121 fail("Can't 'output pop', stack is empty!")
3122 previous_fd = self.clinic.field_destinations_stack.pop()
3123 fd.update(previous_fd)
3124 return
3125
3126 # secret command for debugging!
3127 if field == "print":
3128 self.block.output.append(pprint.pformat(fd))
3129 self.block.output.append('\n')
3130 return
3131
3132 d = self.clinic.get_destination(destination)
3133
3134 if field == "everything":
3135 for name in list(fd):
3136 fd[name] = d
3137 return
3138
3139 if field not in fd:
Larry Hastings7726ac92014-01-31 22:03:12 -08003140 fail("Invalid field " + repr(field) + ", must be one of:\n preset push pop print everything " + " ".join(fd))
Larry Hastingsbebf7352014-01-17 17:47:17 -08003141 fd[field] = d
3142
3143 def directive_dump(self, name):
3144 self.block.output.append(self.clinic.get_destination(name).dump())
3145
3146 def directive_print(self, *args):
3147 self.block.output.append(' '.join(args))
3148 self.block.output.append('\n')
3149
3150 def directive_preserve(self):
3151 if self.preserve_output:
3152 fail("Can't have preserve twice in one block!")
3153 self.preserve_output = True
3154
Larry Hastings31826802013-10-19 00:09:25 -07003155 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003156 if self.kind is not CALLABLE:
3157 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003158 self.kind = CLASS_METHOD
3159
3160 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003161 if self.kind is not CALLABLE:
3162 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003163 self.kind = STATIC_METHOD
3164
3165 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003166 if self.coexist:
3167 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07003168 self.coexist = True
3169
3170 def parse(self, block):
3171 self.reset()
3172 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08003173 self.saved_output = self.block.output
3174 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07003175 block_start = self.clinic.block_parser.line_number
3176 lines = block.input.split('\n')
3177 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
3178 if '\t' in line:
3179 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
3180 self.state(line)
3181
3182 self.next(self.state_terminal)
3183 self.state(None)
3184
Larry Hastingsbebf7352014-01-17 17:47:17 -08003185 block.output.extend(self.clinic.language.render(clinic, block.signatures))
3186
3187 if self.preserve_output:
3188 if block.output:
3189 fail("'preserve' only works for blocks that don't produce any output!")
3190 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07003191
3192 @staticmethod
3193 def ignore_line(line):
3194 # ignore comment-only lines
3195 if line.lstrip().startswith('#'):
3196 return True
3197
3198 # Ignore empty lines too
3199 # (but not in docstring sections!)
3200 if not line.strip():
3201 return True
3202
3203 return False
3204
3205 @staticmethod
3206 def calculate_indent(line):
3207 return len(line) - len(line.strip())
3208
3209 def next(self, state, line=None):
3210 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3211 self.state = state
3212 if line is not None:
3213 self.state(line)
3214
3215 def state_dsl_start(self, line):
3216 # self.block = self.ClinicOutputBlock(self)
3217 if self.ignore_line(line):
3218 return
Larry Hastings7726ac92014-01-31 22:03:12 -08003219
3220 # is it a directive?
3221 fields = shlex.split(line)
3222 directive_name = fields[0]
3223 directive = self.directives.get(directive_name, None)
3224 if directive:
3225 try:
3226 directive(*fields[1:])
3227 except TypeError as e:
3228 fail(str(e))
3229 return
3230
Larry Hastings31826802013-10-19 00:09:25 -07003231 self.next(self.state_modulename_name, line)
3232
3233 def state_modulename_name(self, line):
3234 # looking for declaration, which establishes the leftmost column
3235 # line should be
3236 # modulename.fnname [as c_basename] [-> return annotation]
3237 # square brackets denote optional syntax.
3238 #
Larry Hastings4a714d42014-01-14 22:22:41 -08003239 # alternatively:
3240 # modulename.fnname [as c_basename] = modulename.existing_fn_name
3241 # clones the parameters and return converter from that
3242 # function. you can't modify them. you must enter a
3243 # new docstring.
3244 #
Larry Hastings31826802013-10-19 00:09:25 -07003245 # (but we might find a directive first!)
3246 #
3247 # this line is permitted to start with whitespace.
3248 # we'll call this number of spaces F (for "function").
3249
3250 if not line.strip():
3251 return
3252
3253 self.indent.infer(line)
3254
Larry Hastings4a714d42014-01-14 22:22:41 -08003255 # are we cloning?
3256 before, equals, existing = line.rpartition('=')
3257 if equals:
3258 full_name, _, c_basename = before.partition(' as ')
3259 full_name = full_name.strip()
3260 c_basename = c_basename.strip()
3261 existing = existing.strip()
3262 if (is_legal_py_identifier(full_name) and
3263 (not c_basename or is_legal_c_identifier(c_basename)) and
3264 is_legal_py_identifier(existing)):
3265 # we're cloning!
3266 fields = [x.strip() for x in existing.split('.')]
3267 function_name = fields.pop()
3268 module, cls = self.clinic._module_and_class(fields)
3269
3270 for existing_function in (cls or module).functions:
3271 if existing_function.name == function_name:
3272 break
3273 else:
3274 existing_function = None
3275 if not existing_function:
Larry Hastings7726ac92014-01-31 22:03:12 -08003276 print("class", cls, "module", module, "existing", existing)
Larry Hastingsc2047262014-01-25 20:43:29 -08003277 print("cls. functions", cls.functions)
Larry Hastings4a714d42014-01-14 22:22:41 -08003278 fail("Couldn't find existing function " + repr(existing) + "!")
3279
3280 fields = [x.strip() for x in full_name.split('.')]
3281 function_name = fields.pop()
3282 module, cls = self.clinic._module_and_class(fields)
3283
3284 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3285 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
Larry Hastings7726ac92014-01-31 22:03:12 -08003286 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 -08003287
3288 self.block.signatures.append(self.function)
3289 (cls or module).functions.append(self.function)
3290 self.next(self.state_function_docstring)
3291 return
3292
Larry Hastings31826802013-10-19 00:09:25 -07003293 line, _, returns = line.partition('->')
3294
3295 full_name, _, c_basename = line.partition(' as ')
3296 full_name = full_name.strip()
3297 c_basename = c_basename.strip() or None
3298
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003299 if not is_legal_py_identifier(full_name):
3300 fail("Illegal function name: {}".format(full_name))
3301 if c_basename and not is_legal_c_identifier(c_basename):
3302 fail("Illegal C basename: {}".format(c_basename))
3303
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003304 return_converter = None
3305 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003306 ast_input = "def x() -> {}: pass".format(returns)
3307 module = None
3308 try:
3309 module = ast.parse(ast_input)
3310 except SyntaxError:
3311 pass
3312 if not module:
3313 fail("Badly-formed annotation for " + full_name + ": " + returns)
3314 try:
3315 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003316 if legacy:
3317 fail("Legacy converter {!r} not allowed as a return converter"
3318 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003319 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003320 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003321 return_converter = return_converters[name](**kwargs)
3322 except ValueError:
3323 fail("Badly-formed annotation for " + full_name + ": " + returns)
3324
3325 fields = [x.strip() for x in full_name.split('.')]
3326 function_name = fields.pop()
3327 module, cls = self.clinic._module_and_class(fields)
3328
Larry Hastings8666e652014-01-12 14:12:59 -08003329 fields = full_name.split('.')
3330 if fields[-1] == '__new__':
3331 if (self.kind != CLASS_METHOD) or (not cls):
3332 fail("__new__ must be a class method!")
3333 self.kind = METHOD_NEW
3334 elif fields[-1] == '__init__':
3335 if (self.kind != CALLABLE) or (not cls):
3336 fail("__init__ must be a normal method, not a class or static method!")
3337 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003338 if not return_converter:
3339 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003340 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003341 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003342
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003343 if not return_converter:
3344 return_converter = CReturnConverter()
3345
Larry Hastings31826802013-10-19 00:09:25 -07003346 if not module:
3347 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3348 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3349 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3350 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003351
3352 # insert a self converter automatically
Larry Hastingsc2047262014-01-25 20:43:29 -08003353 type, name = correct_name_for_self(self.function)
3354 kwargs = {}
3355 if cls and type == "PyObject *":
3356 kwargs['type'] = cls.typedef
Larry Hastings7726ac92014-01-31 22:03:12 -08003357 sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs)
Larry Hastings5c661892014-01-24 06:17:25 -08003358 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3359 self.function.parameters[sc.name] = p_self
3360
Larry Hastings4a714d42014-01-14 22:22:41 -08003361 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003362 self.next(self.state_parameters_start)
3363
3364 # Now entering the parameters section. The rules, formally stated:
3365 #
3366 # * All lines must be indented with spaces only.
3367 # * The first line must be a parameter declaration.
3368 # * The first line must be indented.
3369 # * This first line establishes the indent for parameters.
3370 # * We'll call this number of spaces P (for "parameter").
3371 # * Thenceforth:
3372 # * Lines indented with P spaces specify a parameter.
3373 # * Lines indented with > P spaces are docstrings for the previous
3374 # parameter.
3375 # * We'll call this number of spaces D (for "docstring").
3376 # * All subsequent lines indented with >= D spaces are stored as
3377 # part of the per-parameter docstring.
3378 # * All lines will have the first D spaces of the indent stripped
3379 # before they are stored.
3380 # * It's illegal to have a line starting with a number of spaces X
3381 # such that P < X < D.
3382 # * A line with < P spaces is the first line of the function
3383 # docstring, which ends processing for parameters and per-parameter
3384 # docstrings.
3385 # * The first line of the function docstring must be at the same
3386 # indent as the function declaration.
3387 # * It's illegal to have any line in the parameters section starting
3388 # with X spaces such that F < X < P. (As before, F is the indent
3389 # of the function declaration.)
3390 #
Larry Hastings31826802013-10-19 00:09:25 -07003391 # Also, currently Argument Clinic places the following restrictions on groups:
3392 # * Each group must contain at least one parameter.
3393 # * Each group may contain at most one group, which must be the furthest
3394 # thing in the group from the required parameters. (The nested group
3395 # must be the first in the group when it's before the required
3396 # parameters, and the last thing in the group when after the required
3397 # parameters.)
3398 # * There may be at most one (top-level) group to the left or right of
3399 # the required parameters.
3400 # * You must specify a slash, and it must be after all parameters.
3401 # (In other words: either all parameters are positional-only,
3402 # or none are.)
3403 #
3404 # Said another way:
3405 # * Each group must contain at least one parameter.
3406 # * All left square brackets before the required parameters must be
3407 # consecutive. (You can't have a left square bracket followed
3408 # by a parameter, then another left square bracket. You can't
3409 # have a left square bracket, a parameter, a right square bracket,
3410 # and then a left square bracket.)
3411 # * All right square brackets after the required parameters must be
3412 # consecutive.
3413 #
3414 # These rules are enforced with a single state variable:
3415 # "parameter_state". (Previously the code was a miasma of ifs and
3416 # separate boolean state variables.) The states are:
3417 #
Larry Hastingsc2047262014-01-25 20:43:29 -08003418 # [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ] / <- line
3419 # 01 2 3 4 5 6 7 <- state transitions
Larry Hastings31826802013-10-19 00:09:25 -07003420 #
3421 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3422 # 1: ps_left_square_before. left square brackets before required parameters.
3423 # 2: ps_group_before. in a group, before required parameters.
Larry Hastingsc2047262014-01-25 20:43:29 -08003424 # 3: ps_required. required parameters, positional-or-keyword or positional-only
3425 # (we don't know yet). (renumber left groups!)
3426 # 4: ps_optional. positional-or-keyword or positional-only parameters that
3427 # now must have default values.
3428 # 5: ps_group_after. in a group, after required parameters.
3429 # 6: ps_right_square_after. right square brackets after required parameters.
3430 # 7: ps_seen_slash. seen slash.
Larry Hastings31826802013-10-19 00:09:25 -07003431 ps_start, ps_left_square_before, ps_group_before, ps_required, \
Larry Hastingsc2047262014-01-25 20:43:29 -08003432 ps_optional, ps_group_after, ps_right_square_after, ps_seen_slash = range(8)
Larry Hastings31826802013-10-19 00:09:25 -07003433
3434 def state_parameters_start(self, line):
3435 if self.ignore_line(line):
3436 return
3437
3438 # if this line is not indented, we have no parameters
3439 if not self.indent.infer(line):
3440 return self.next(self.state_function_docstring, line)
3441
Larry Hastings2a727912014-01-16 11:32:01 -08003442 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003443 return self.next(self.state_parameter, line)
3444
3445
3446 def to_required(self):
3447 """
3448 Transition to the "required" parameter state.
3449 """
3450 if self.parameter_state != self.ps_required:
3451 self.parameter_state = self.ps_required
3452 for p in self.function.parameters.values():
3453 p.group = -p.group
3454
3455 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003456 if self.parameter_continuation:
3457 line = self.parameter_continuation + ' ' + line.lstrip()
3458 self.parameter_continuation = ''
3459
Larry Hastings31826802013-10-19 00:09:25 -07003460 if self.ignore_line(line):
3461 return
3462
3463 assert self.indent.depth == 2
3464 indent = self.indent.infer(line)
3465 if indent == -1:
3466 # we outdented, must be to definition column
3467 return self.next(self.state_function_docstring, line)
3468
3469 if indent == 1:
3470 # we indented, must be to new parameter docstring column
3471 return self.next(self.state_parameter_docstring_start, line)
3472
Larry Hastings2a727912014-01-16 11:32:01 -08003473 line = line.rstrip()
3474 if line.endswith('\\'):
3475 self.parameter_continuation = line[:-1]
3476 return
3477
Larry Hastings31826802013-10-19 00:09:25 -07003478 line = line.lstrip()
3479
3480 if line in ('*', '/', '[', ']'):
3481 self.parse_special_symbol(line)
3482 return
3483
3484 if self.parameter_state in (self.ps_start, self.ps_required):
3485 self.to_required()
3486 elif self.parameter_state == self.ps_left_square_before:
3487 self.parameter_state = self.ps_group_before
3488 elif self.parameter_state == self.ps_group_before:
3489 if not self.group:
3490 self.to_required()
Larry Hastingsc2047262014-01-25 20:43:29 -08003491 elif self.parameter_state in (self.ps_group_after, self.ps_optional):
Larry Hastings31826802013-10-19 00:09:25 -07003492 pass
3493 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003494 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
Larry Hastings31826802013-10-19 00:09:25 -07003495
Larry Hastings7726ac92014-01-31 22:03:12 -08003496 # handle "as" for parameters too
3497 c_name = None
3498 name, have_as_token, trailing = line.partition(' as ')
3499 if have_as_token:
3500 name = name.strip()
3501 if ' ' not in name:
3502 fields = trailing.strip().split(' ')
3503 if not fields:
3504 fail("Invalid 'as' clause!")
3505 c_name = fields[0]
3506 if c_name.endswith(':'):
3507 name += ':'
3508 c_name = c_name[:-1]
3509 fields[0] = name
3510 line = ' '.join(fields)
3511
Larry Hastings2a727912014-01-16 11:32:01 -08003512 base, equals, default = line.rpartition('=')
3513 if not equals:
3514 base = default
3515 default = None
Larry Hastingsc2047262014-01-25 20:43:29 -08003516
Larry Hastings31826802013-10-19 00:09:25 -07003517 module = None
3518 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003519 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003520 module = ast.parse(ast_input)
3521 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003522 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08003523 # the last = was probably inside a function call, like
3524 # i: int(nullable=True)
3525 # so assume there was no actual default value.
Larry Hastings2a727912014-01-16 11:32:01 -08003526 default = None
3527 ast_input = "def x({}): pass".format(line)
3528 module = ast.parse(ast_input)
3529 except SyntaxError:
3530 pass
Larry Hastings31826802013-10-19 00:09:25 -07003531 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003532 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003533
3534 function_args = module.body[0].args
3535 parameter = function_args.args[0]
3536
Larry Hastings16c51912014-01-07 11:53:01 -08003537 parameter_name = parameter.arg
3538 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3539
Larry Hastings2a727912014-01-16 11:32:01 -08003540 if not default:
Larry Hastingsc2047262014-01-25 20:43:29 -08003541 if self.parameter_state == self.ps_optional:
3542 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 -08003543 value = unspecified
3544 if 'py_default' in kwargs:
3545 fail("You can't specify py_default without specifying a default value!")
3546 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003547 if self.parameter_state == self.ps_required:
3548 self.parameter_state = self.ps_optional
Larry Hastings2a727912014-01-16 11:32:01 -08003549 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003550 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003551 ast_input = "x = {}".format(default)
Larry Hastingsc2047262014-01-25 20:43:29 -08003552 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003553 try:
3554 module = ast.parse(ast_input)
3555
Larry Hastings5c661892014-01-24 06:17:25 -08003556 if 'c_default' not in kwargs:
3557 # we can only represent very simple data values in C.
3558 # detect whether default is okay, via a blacklist
3559 # of disallowed ast nodes.
3560 class DetectBadNodes(ast.NodeVisitor):
3561 bad = False
3562 def bad_node(self, node):
3563 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003564
Larry Hastings5c661892014-01-24 06:17:25 -08003565 # inline function call
3566 visit_Call = bad_node
3567 # inline if statement ("x = 3 if y else z")
3568 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003569
Larry Hastings5c661892014-01-24 06:17:25 -08003570 # comprehensions and generator expressions
3571 visit_ListComp = visit_SetComp = bad_node
3572 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003573
Larry Hastings5c661892014-01-24 06:17:25 -08003574 # literals for advanced types
3575 visit_Dict = visit_Set = bad_node
3576 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003577
Larry Hastings5c661892014-01-24 06:17:25 -08003578 # "starred": "a = [1, 2, 3]; *a"
3579 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003580
Larry Hastings5c661892014-01-24 06:17:25 -08003581 # allow ellipsis, for now
3582 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003583
Larry Hastings5c661892014-01-24 06:17:25 -08003584 blacklist = DetectBadNodes()
3585 blacklist.visit(module)
3586 bad = blacklist.bad
3587 else:
3588 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003589 # but at least make an attempt at ensuring it's a valid expression.
3590 try:
3591 value = eval(default)
3592 if value == unspecified:
3593 fail("'unspecified' is not a legal default value!")
3594 except NameError:
3595 pass # probably a named constant
3596 except Exception as e:
3597 fail("Malformed expression given as default value\n"
3598 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003599 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003600 fail("Unsupported expression as default value: " + repr(default))
3601
3602 expr = module.body[0].value
3603 # mild hack: explicitly support NULL as a default value
3604 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3605 value = NULL
3606 py_default = 'None'
3607 c_default = "NULL"
3608 elif (isinstance(expr, ast.BinOp) or
3609 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3610 c_default = kwargs.get("c_default")
3611 if not (isinstance(c_default, str) and c_default):
3612 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3613 py_default = default
3614 value = unknown
3615 elif isinstance(expr, ast.Attribute):
3616 a = []
3617 n = expr
3618 while isinstance(n, ast.Attribute):
3619 a.append(n.attr)
3620 n = n.value
3621 if not isinstance(n, ast.Name):
3622 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3623 a.append(n.id)
3624 py_default = ".".join(reversed(a))
3625
3626 c_default = kwargs.get("c_default")
3627 if not (isinstance(c_default, str) and c_default):
3628 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3629
3630 try:
3631 value = eval(py_default)
3632 except NameError:
3633 value = unknown
3634 else:
3635 value = ast.literal_eval(expr)
3636 py_default = repr(value)
3637 if isinstance(value, (bool, None.__class__)):
3638 c_default = "Py_" + py_default
3639 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003640 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003641 else:
3642 c_default = py_default
3643
3644 except SyntaxError as e:
3645 fail("Syntax error: " + repr(e.text))
3646 except (ValueError, AttributeError):
3647 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003648 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003649 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003650 if not (isinstance(c_default, str) and c_default):
3651 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3652
Larry Hastings2a727912014-01-16 11:32:01 -08003653 kwargs.setdefault('c_default', c_default)
3654 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003655
Larry Hastings31826802013-10-19 00:09:25 -07003656 dict = legacy_converters if legacy else converters
3657 legacy_str = "legacy " if legacy else ""
3658 if name not in dict:
3659 fail('{} is not a valid {}converter'.format(name, legacy_str))
Larry Hastings7726ac92014-01-31 22:03:12 -08003660 # if you use a c_name for the parameter, we just give that name to the converter
3661 # but the parameter object gets the python name
3662 converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
Larry Hastings31826802013-10-19 00:09:25 -07003663
3664 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003665
3666 if isinstance(converter, self_converter):
3667 if len(self.function.parameters) == 1:
3668 if (self.parameter_state != self.ps_required):
3669 fail("A 'self' parameter cannot be marked optional.")
3670 if value is not unspecified:
3671 fail("A 'self' parameter cannot have a default value.")
3672 if self.group:
3673 fail("A 'self' parameter cannot be in an optional group.")
3674 kind = inspect.Parameter.POSITIONAL_ONLY
3675 self.parameter_state = self.ps_start
3676 self.function.parameters.clear()
3677 else:
3678 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3679
Larry Hastings31826802013-10-19 00:09:25 -07003680 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003681
3682 if parameter_name in self.function.parameters:
3683 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003684 self.function.parameters[parameter_name] = p
3685
3686 def parse_converter(self, annotation):
3687 if isinstance(annotation, ast.Str):
3688 return annotation.s, True, {}
3689
3690 if isinstance(annotation, ast.Name):
3691 return annotation.id, False, {}
3692
Larry Hastings4a55fc52014-01-12 11:09:57 -08003693 if not isinstance(annotation, ast.Call):
3694 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003695
3696 name = annotation.func.id
3697 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
3698 return name, False, kwargs
3699
3700 def parse_special_symbol(self, symbol):
3701 if self.parameter_state == self.ps_seen_slash:
3702 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3703
3704 if symbol == '*':
3705 if self.keyword_only:
3706 fail("Function " + self.function.name + " uses '*' more than once.")
3707 self.keyword_only = True
3708 elif symbol == '[':
3709 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3710 self.parameter_state = self.ps_left_square_before
3711 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3712 self.parameter_state = self.ps_group_after
3713 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003714 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
Larry Hastings31826802013-10-19 00:09:25 -07003715 self.group += 1
Larry Hastings2623c8c2014-02-08 22:15:29 -08003716 self.function.docstring_only = True
Larry Hastings31826802013-10-19 00:09:25 -07003717 elif symbol == ']':
3718 if not self.group:
3719 fail("Function " + self.function.name + " has a ] without a matching [.")
3720 if not any(p.group == self.group for p in self.function.parameters.values()):
3721 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3722 self.group -= 1
3723 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3724 self.parameter_state = self.ps_group_before
3725 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3726 self.parameter_state = self.ps_right_square_after
3727 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003728 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
Larry Hastings31826802013-10-19 00:09:25 -07003729 elif symbol == '/':
Larry Hastingsc2047262014-01-25 20:43:29 -08003730 # ps_required and ps_optional are allowed here, that allows positional-only without option groups
Larry Hastings31826802013-10-19 00:09:25 -07003731 # to work (and have default values!)
Larry Hastingsc2047262014-01-25 20:43:29 -08003732 if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
3733 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
Larry Hastings31826802013-10-19 00:09:25 -07003734 if self.keyword_only:
3735 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3736 self.parameter_state = self.ps_seen_slash
Berker Peksagf23530f2014-10-19 18:04:38 +03003737 # fixup preceding parameters
Larry Hastings31826802013-10-19 00:09:25 -07003738 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003739 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003740 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3741 p.kind = inspect.Parameter.POSITIONAL_ONLY
3742
3743 def state_parameter_docstring_start(self, line):
3744 self.parameter_docstring_indent = len(self.indent.margin)
3745 assert self.indent.depth == 3
3746 return self.next(self.state_parameter_docstring, line)
3747
3748 # every line of the docstring must start with at least F spaces,
3749 # where F > P.
3750 # these F spaces will be stripped.
3751 def state_parameter_docstring(self, line):
3752 stripped = line.strip()
3753 if stripped.startswith('#'):
3754 return
3755
3756 indent = self.indent.measure(line)
3757 if indent < self.parameter_docstring_indent:
3758 self.indent.infer(line)
3759 assert self.indent.depth < 3
3760 if self.indent.depth == 2:
3761 # back to a parameter
3762 return self.next(self.state_parameter, line)
3763 assert self.indent.depth == 1
3764 return self.next(self.state_function_docstring, line)
3765
3766 assert self.function.parameters
3767 last_parameter = next(reversed(list(self.function.parameters.values())))
3768
3769 new_docstring = last_parameter.docstring
3770
3771 if new_docstring:
3772 new_docstring += '\n'
3773 if stripped:
3774 new_docstring += self.indent.dedent(line)
3775
3776 last_parameter.docstring = new_docstring
3777
3778 # the final stanza of the DSL is the docstring.
3779 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003780 if self.group:
3781 fail("Function " + self.function.name + " has a ] without a matching [.")
3782
3783 stripped = line.strip()
3784 if stripped.startswith('#'):
3785 return
3786
3787 new_docstring = self.function.docstring
3788 if new_docstring:
3789 new_docstring += "\n"
3790 if stripped:
3791 line = self.indent.dedent(line).rstrip()
3792 else:
3793 line = ''
3794 new_docstring += line
3795 self.function.docstring = new_docstring
3796
3797 def format_docstring(self):
3798 f = self.function
3799
Larry Hastings5c661892014-01-24 06:17:25 -08003800 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3801 if new_or_init and not f.docstring:
3802 # don't render a docstring at all, no signature, nothing.
3803 return f.docstring
3804
Larry Hastings2623c8c2014-02-08 22:15:29 -08003805 text, add, output = _text_accumulator()
Larry Hastings7726ac92014-01-31 22:03:12 -08003806 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07003807
3808 ##
3809 ## docstring first line
3810 ##
3811
Larry Hastings2623c8c2014-02-08 22:15:29 -08003812 if new_or_init:
3813 # classes get *just* the name of the class
3814 # not __new__, not __init__, and not module.classname
3815 assert f.cls
3816 add(f.cls.name)
Larry Hastings46258262014-01-22 03:05:49 -08003817 else:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003818 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003819 add('(')
3820
3821 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003822 assert parameters, "We should always have a self parameter. " + repr(f)
3823 assert isinstance(parameters[0].converter, self_converter)
3824 parameters[0].right_bracket_count = 0
3825 parameters_after_self = parameters[1:]
3826 if parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003827 # for now, the only way Clinic supports positional-only parameters
Larry Hastings5c661892014-01-24 06:17:25 -08003828 # is if all of them are positional-only...
3829 #
3830 # ... except for self! self is always positional-only.
3831
3832 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters_after_self]
3833 if parameters_after_self[0].kind == inspect.Parameter.POSITIONAL_ONLY:
Larry Hastings31826802013-10-19 00:09:25 -07003834 assert all(positional_only_parameters)
3835 for p in parameters:
3836 p.right_bracket_count = abs(p.group)
3837 else:
3838 # don't put any right brackets around non-positional-only parameters, ever.
Larry Hastings5c661892014-01-24 06:17:25 -08003839 for p in parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003840 p.right_bracket_count = 0
3841
3842 right_bracket_count = 0
3843
3844 def fix_right_bracket_count(desired):
3845 nonlocal right_bracket_count
3846 s = ''
3847 while right_bracket_count < desired:
3848 s += '['
3849 right_bracket_count += 1
3850 while right_bracket_count > desired:
3851 s += ']'
3852 right_bracket_count -= 1
3853 return s
3854
Larry Hastings2623c8c2014-02-08 22:15:29 -08003855 need_slash = False
3856 added_slash = False
3857 need_a_trailing_slash = False
3858
3859 # we only need a trailing slash:
3860 # * if this is not a "docstring_only" signature
3861 # * and if the last *shown* parameter is
3862 # positional only
3863 if not f.docstring_only:
3864 for p in reversed(parameters):
3865 if not p.converter.show_in_signature:
3866 continue
3867 if p.is_positional_only():
3868 need_a_trailing_slash = True
3869 break
3870
3871
Larry Hastings31826802013-10-19 00:09:25 -07003872 added_star = False
Larry Hastings2623c8c2014-02-08 22:15:29 -08003873
3874 first_parameter = True
3875 last_p = parameters[-1]
3876 line_length = len(''.join(text))
3877 indent = " " * line_length
3878 def add_parameter(text):
3879 nonlocal line_length
3880 nonlocal first_parameter
3881 if first_parameter:
3882 s = text
3883 first_parameter = False
3884 else:
3885 s = ' ' + text
3886 if line_length + len(s) >= 72:
3887 add('\n')
3888 add(indent)
3889 line_length = len(indent)
3890 s = text
3891 line_length += len(s)
3892 add(s)
Larry Hastings31826802013-10-19 00:09:25 -07003893
3894 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08003895 if not p.converter.show_in_signature:
3896 continue
Larry Hastings31826802013-10-19 00:09:25 -07003897 assert p.name
3898
Larry Hastings2623c8c2014-02-08 22:15:29 -08003899 is_self = isinstance(p.converter, self_converter)
3900 if is_self and f.docstring_only:
3901 # this isn't a real machine-parsable signature,
3902 # so let's not print the "self" parameter
3903 continue
3904
3905 if p.is_positional_only():
3906 need_slash = not f.docstring_only
3907 elif need_slash and not (added_slash or p.is_positional_only()):
3908 added_slash = True
3909 add_parameter('/,')
3910
Larry Hastings31826802013-10-19 00:09:25 -07003911 if p.is_keyword_only() and not added_star:
3912 added_star = True
Larry Hastings2623c8c2014-02-08 22:15:29 -08003913 add_parameter('*,')
3914
3915 p_add, p_output = text_accumulator()
3916 p_add(fix_right_bracket_count(p.right_bracket_count))
3917
3918 if isinstance(p.converter, self_converter):
3919 # annotate first parameter as being a "self".
3920 #
3921 # if inspect.Signature gets this function,
3922 # and it's already bound, the self parameter
3923 # will be stripped off.
3924 #
3925 # if it's not bound, it should be marked
3926 # as positional-only.
3927 #
3928 # note: we don't print "self" for __init__,
3929 # because this isn't actually the signature
3930 # for __init__. (it can't be, __init__ doesn't
3931 # have a docstring.) if this is an __init__
3932 # (or __new__), then this signature is for
Berker Peksagf23530f2014-10-19 18:04:38 +03003933 # calling the class to construct a new instance.
Larry Hastings2623c8c2014-02-08 22:15:29 -08003934 p_add('$')
Larry Hastings31826802013-10-19 00:09:25 -07003935
Larry Hastings5c661892014-01-24 06:17:25 -08003936 name = p.converter.signature_name or p.name
Larry Hastings2623c8c2014-02-08 22:15:29 -08003937 p_add(name)
Larry Hastings581ee362014-01-28 05:00:08 -08003938
Larry Hastings31826802013-10-19 00:09:25 -07003939 if p.converter.is_optional():
Larry Hastings2623c8c2014-02-08 22:15:29 -08003940 p_add('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08003941 value = p.converter.py_default
3942 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08003943 value = repr(p.converter.default)
Larry Hastings2623c8c2014-02-08 22:15:29 -08003944 p_add(value)
3945
3946 if (p != last_p) or need_a_trailing_slash:
3947 p_add(',')
3948
3949 add_parameter(p_output())
Larry Hastings31826802013-10-19 00:09:25 -07003950
3951 add(fix_right_bracket_count(0))
Larry Hastings2623c8c2014-02-08 22:15:29 -08003952 if need_a_trailing_slash:
3953 add_parameter('/')
Larry Hastings31826802013-10-19 00:09:25 -07003954 add(')')
3955
Larry Hastings2a727912014-01-16 11:32:01 -08003956 # PEP 8 says:
3957 #
3958 # The Python standard library will not use function annotations
3959 # as that would result in a premature commitment to a particular
3960 # annotation style. Instead, the annotations are left for users
3961 # to discover and experiment with useful annotation styles.
3962 #
3963 # therefore this is commented out:
3964 #
3965 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003966 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08003967 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003968
Larry Hastings2623c8c2014-02-08 22:15:29 -08003969 if not f.docstring_only:
3970 add("\n--\n")
3971
Larry Hastings31826802013-10-19 00:09:25 -07003972 docstring_first_line = output()
3973
3974 # now fix up the places where the brackets look wrong
3975 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
3976
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003977 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07003978 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003979 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07003980 for p in parameters:
3981 if not p.docstring.strip():
3982 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003983 if spacer_line:
3984 add('\n')
3985 else:
3986 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07003987 add(" ")
3988 add(p.name)
3989 add('\n')
3990 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003991 parameters = output()
3992 if parameters:
3993 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07003994
3995 ##
3996 ## docstring body
3997 ##
3998
3999 docstring = f.docstring.rstrip()
4000 lines = [line.rstrip() for line in docstring.split('\n')]
4001
4002 # Enforce the summary line!
4003 # The first line of a docstring should be a summary of the function.
4004 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
4005 # by itself.
4006 #
4007 # Argument Clinic enforces the following rule:
4008 # * either the docstring is empty,
4009 # * or it must have a summary line.
4010 #
4011 # Guido said Clinic should enforce this:
4012 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
4013
4014 if len(lines) >= 2:
4015 if lines[1]:
4016 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
4017 "Every non-blank function docstring must start with\n" +
4018 "a single line summary followed by an empty line.")
4019 elif len(lines) == 1:
4020 # the docstring is only one line right now--the summary line.
4021 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004022 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07004023 lines.append('')
4024
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004025 parameters_marker_count = len(docstring.split('{parameters}')) - 1
4026 if parameters_marker_count > 1:
4027 fail('You may not specify {parameters} more than once in a docstring!')
4028
4029 if not parameters_marker_count:
4030 # insert after summary line
4031 lines.insert(2, '{parameters}')
4032
4033 # insert at front of docstring
4034 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07004035
4036 docstring = "\n".join(lines)
4037
4038 add(docstring)
4039 docstring = output()
4040
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004041 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07004042 docstring = docstring.rstrip()
4043
4044 return docstring
4045
4046 def state_terminal(self, line):
4047 """
4048 Called when processing the block is done.
4049 """
4050 assert not line
4051
4052 if not self.function:
4053 return
4054
4055 if self.keyword_only:
4056 values = self.function.parameters.values()
4057 if not values:
4058 no_parameter_after_star = True
4059 else:
4060 last_parameter = next(reversed(list(values)))
4061 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
4062 if no_parameter_after_star:
4063 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
4064
4065 # remove trailing whitespace from all parameter docstrings
4066 for name, value in self.function.parameters.items():
4067 if not value:
4068 continue
4069 value.docstring = value.docstring.rstrip()
4070
4071 self.function.docstring = self.format_docstring()
4072
4073
Larry Hastings5c661892014-01-24 06:17:25 -08004074
4075
Larry Hastings31826802013-10-19 00:09:25 -07004076# maps strings to callables.
4077# the callable should return an object
4078# that implements the clinic parser
4079# interface (__init__ and parse).
4080#
4081# example parsers:
4082# "clinic", handles the Clinic DSL
4083# "python", handles running Python code
4084#
4085parsers = {'clinic' : DSLParser, 'python': PythonParser}
4086
4087
4088clinic = None
4089
4090
4091def main(argv):
4092 import sys
4093
4094 if sys.version_info.major < 3 or sys.version_info.minor < 3:
4095 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
4096
4097 import argparse
4098 cmdline = argparse.ArgumentParser()
4099 cmdline.add_argument("-f", "--force", action='store_true')
4100 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08004101 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004102 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004103 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004104 cmdline.add_argument("filename", type=str, nargs="*")
4105 ns = cmdline.parse_args(argv)
4106
4107 if ns.converters:
4108 if ns.filename:
4109 print("Usage error: can't specify --converters and a filename at the same time.")
4110 print()
4111 cmdline.print_usage()
4112 sys.exit(-1)
4113 converters = []
4114 return_converters = []
4115 ignored = set("""
4116 add_c_converter
4117 add_c_return_converter
4118 add_default_legacy_c_converter
4119 add_legacy_c_converter
4120 """.strip().split())
4121 module = globals()
4122 for name in module:
4123 for suffix, ids in (
4124 ("_return_converter", return_converters),
4125 ("_converter", converters),
4126 ):
4127 if name in ignored:
4128 continue
4129 if name.endswith(suffix):
4130 ids.append((name, name[:-len(suffix)]))
4131 break
4132 print()
4133
4134 print("Legacy converters:")
4135 legacy = sorted(legacy_converters)
4136 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
4137 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
4138 print()
4139
4140 for title, attribute, ids in (
4141 ("Converters", 'converter_init', converters),
4142 ("Return converters", 'return_converter_init', return_converters),
4143 ):
4144 print(title + ":")
4145 longest = -1
4146 for name, short_name in ids:
4147 longest = max(longest, len(short_name))
4148 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
4149 cls = module[name]
4150 callable = getattr(cls, attribute, None)
4151 if not callable:
4152 continue
4153 signature = inspect.signature(callable)
4154 parameters = []
4155 for parameter_name, parameter in signature.parameters.items():
4156 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
4157 if parameter.default != inspect.Parameter.empty:
4158 s = '{}={!r}'.format(parameter_name, parameter.default)
4159 else:
4160 s = parameter_name
4161 parameters.append(s)
4162 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07004163 print()
Larry Hastings2a727912014-01-16 11:32:01 -08004164 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
4165 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07004166 sys.exit(0)
4167
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004168 if ns.make:
4169 if ns.output or ns.filename:
4170 print("Usage error: can't use -o or filenames with --make.")
4171 print()
4172 cmdline.print_usage()
4173 sys.exit(-1)
4174 for root, dirs, files in os.walk('.'):
Larry Hastings5c661892014-01-24 06:17:25 -08004175 for rcs_dir in ('.svn', '.git', '.hg', 'build'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004176 if rcs_dir in dirs:
4177 dirs.remove(rcs_dir)
4178 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08004179 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004180 continue
4181 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08004182 if ns.verbose:
4183 print(path)
Larry Hastings581ee362014-01-28 05:00:08 -08004184 parse_file(path, force=ns.force, verify=not ns.force)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004185 return
4186
Larry Hastings31826802013-10-19 00:09:25 -07004187 if not ns.filename:
4188 cmdline.print_usage()
4189 sys.exit(-1)
4190
4191 if ns.output and len(ns.filename) > 1:
4192 print("Usage error: can't use -o with multiple filenames.")
4193 print()
4194 cmdline.print_usage()
4195 sys.exit(-1)
4196
4197 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08004198 if ns.verbose:
4199 print(filename)
Larry Hastings581ee362014-01-28 05:00:08 -08004200 parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
Larry Hastings31826802013-10-19 00:09:25 -07004201
4202
4203if __name__ == "__main__":
4204 sys.exit(main(sys.argv[1:]))