blob: 64b9bf738e12920ab55b2010d0b6efa178b83ff8 [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__
Larry Hastings8666e652014-01-12 14:12:59 -08001834__ifloordiv__
1835__ilshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001836__imatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001837__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__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001853__matmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001854__mod__
1855__mul__
1856__neg__
1857__new__
1858__next__
1859__or__
1860__pos__
1861__pow__
1862__radd__
1863__rand__
1864__rdivmod__
1865__repr__
1866__rfloordiv__
1867__rlshift__
Serhiy Storchakac2ccce72015-03-12 22:01:30 +02001868__rmatmul__
Larry Hastings8666e652014-01-12 14:12:59 -08001869__rmod__
1870__rmul__
1871__ror__
1872__round__
1873__rpow__
1874__rrshift__
1875__rshift__
1876__rsub__
1877__rtruediv__
1878__rxor__
1879__setattr__
1880__setitem__
1881__str__
1882__sub__
1883__truediv__
1884__xor__
1885
1886""".strip().split())
1887
1888
Larry Hastings5c661892014-01-24 06:17:25 -08001889INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
1890INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
1891""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07001892
1893class Function:
1894 """
1895 Mutable duck type for inspect.Function.
1896
1897 docstring - a str containing
1898 * embedded line breaks
1899 * text outdented to the left margin
1900 * no trailing whitespace.
1901 It will always be true that
1902 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
1903 """
1904
1905 def __init__(self, parameters=None, *, name,
1906 module, cls=None, c_basename=None,
1907 full_name=None,
1908 return_converter, return_annotation=_empty,
Larry Hastings581ee362014-01-28 05:00:08 -08001909 docstring=None, kind=CALLABLE, coexist=False,
Larry Hastings2623c8c2014-02-08 22:15:29 -08001910 docstring_only=False):
Larry Hastings31826802013-10-19 00:09:25 -07001911 self.parameters = parameters or collections.OrderedDict()
1912 self.return_annotation = return_annotation
1913 self.name = name
1914 self.full_name = full_name
1915 self.module = module
1916 self.cls = cls
1917 self.parent = cls or module
1918 self.c_basename = c_basename
1919 self.return_converter = return_converter
1920 self.docstring = docstring or ''
1921 self.kind = kind
1922 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08001923 self.self_converter = None
Larry Hastings2623c8c2014-02-08 22:15:29 -08001924 # docstring_only means "don't generate a machine-readable
1925 # signature, just a normal docstring". it's True for
1926 # functions with optional groups because we can't represent
1927 # those accurately with inspect.Signature in 3.4.
1928 self.docstring_only = docstring_only
Larry Hastingsebdcb502013-11-23 14:54:00 -08001929
Larry Hastings7726ac92014-01-31 22:03:12 -08001930 self.rendered_parameters = None
1931
1932 __render_parameters__ = None
1933 @property
1934 def render_parameters(self):
1935 if not self.__render_parameters__:
1936 self.__render_parameters__ = l = []
1937 for p in self.parameters.values():
1938 p = p.copy()
1939 p.converter.pre_render()
1940 l.append(p)
1941 return self.__render_parameters__
1942
Larry Hastingsebdcb502013-11-23 14:54:00 -08001943 @property
1944 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08001945 if self.kind in (METHOD_INIT, METHOD_NEW):
1946 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001947 flags = []
1948 if self.kind == CLASS_METHOD:
1949 flags.append('METH_CLASS')
1950 elif self.kind == STATIC_METHOD:
1951 flags.append('METH_STATIC')
1952 else:
1953 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
1954 if self.coexist:
1955 flags.append('METH_COEXIST')
1956 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07001957
1958 def __repr__(self):
1959 return '<clinic.Function ' + self.name + '>'
1960
Larry Hastings7726ac92014-01-31 22:03:12 -08001961 def copy(self, **overrides):
1962 kwargs = {
1963 'name': self.name, 'module': self.module, 'parameters': self.parameters,
1964 'cls': self.cls, 'c_basename': self.c_basename,
1965 'full_name': self.full_name,
1966 'return_converter': self.return_converter, 'return_annotation': self.return_annotation,
1967 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist,
Larry Hastings2623c8c2014-02-08 22:15:29 -08001968 'docstring_only': self.docstring_only,
Larry Hastings7726ac92014-01-31 22:03:12 -08001969 }
1970 kwargs.update(overrides)
1971 f = Function(**kwargs)
1972
1973 parameters = collections.OrderedDict()
1974 for name, value in f.parameters.items():
1975 value = value.copy(function=f)
1976 parameters[name] = value
1977 f.parameters = parameters
1978 return f
1979
Larry Hastings31826802013-10-19 00:09:25 -07001980
1981class Parameter:
1982 """
1983 Mutable duck type of inspect.Parameter.
1984 """
1985
1986 def __init__(self, name, kind, *, default=_empty,
1987 function, converter, annotation=_empty,
1988 docstring=None, group=0):
1989 self.name = name
1990 self.kind = kind
1991 self.default = default
1992 self.function = function
1993 self.converter = converter
1994 self.annotation = annotation
1995 self.docstring = docstring or ''
1996 self.group = group
1997
1998 def __repr__(self):
1999 return '<clinic.Parameter ' + self.name + '>'
2000
2001 def is_keyword_only(self):
2002 return self.kind == inspect.Parameter.KEYWORD_ONLY
2003
Larry Hastings2623c8c2014-02-08 22:15:29 -08002004 def is_positional_only(self):
2005 return self.kind == inspect.Parameter.POSITIONAL_ONLY
2006
Larry Hastings7726ac92014-01-31 22:03:12 -08002007 def copy(self, **overrides):
2008 kwargs = {
2009 'name': self.name, 'kind': self.kind, 'default':self.default,
2010 'function': self.function, 'converter': self.converter, 'annotation': self.annotation,
2011 'docstring': self.docstring, 'group': self.group,
2012 }
2013 kwargs.update(overrides)
2014 if 'converter' not in overrides:
2015 converter = copy.copy(self.converter)
2016 converter.function = kwargs['function']
2017 kwargs['converter'] = converter
2018 return Parameter(**kwargs)
2019
2020
2021
2022class LandMine:
2023 # try to access any
2024 def __init__(self, message):
2025 self.__message__ = message
2026
2027 def __repr__(self):
2028 return '<LandMine ' + repr(self.__message__) + ">"
2029
2030 def __getattribute__(self, name):
2031 if name in ('__repr__', '__message__'):
2032 return super().__getattribute__(name)
2033 # raise RuntimeError(repr(name))
2034 fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__)
Larry Hastings31826802013-10-19 00:09:25 -07002035
Larry Hastings31826802013-10-19 00:09:25 -07002036
2037def add_c_converter(f, name=None):
2038 if not name:
2039 name = f.__name__
2040 if not name.endswith('_converter'):
2041 return f
2042 name = name[:-len('_converter')]
2043 converters[name] = f
2044 return f
2045
2046def add_default_legacy_c_converter(cls):
2047 # automatically add converter for default format unit
2048 # (but without stomping on the existing one if it's already
2049 # set, in case you subclass)
Larry Hastingsf1503782014-06-11 04:31:29 -07002050 if ((cls.format_unit not in ('O&', '')) and
Larry Hastings31826802013-10-19 00:09:25 -07002051 (cls.format_unit not in legacy_converters)):
2052 legacy_converters[cls.format_unit] = cls
2053 return cls
2054
2055def add_legacy_c_converter(format_unit, **kwargs):
2056 """
2057 Adds a legacy converter.
2058 """
2059 def closure(f):
2060 if not kwargs:
2061 added_f = f
2062 else:
2063 added_f = functools.partial(f, **kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002064 if format_unit:
2065 legacy_converters[format_unit] = added_f
Larry Hastings31826802013-10-19 00:09:25 -07002066 return f
2067 return closure
2068
2069class CConverterAutoRegister(type):
2070 def __init__(cls, name, bases, classdict):
2071 add_c_converter(cls)
2072 add_default_legacy_c_converter(cls)
2073
2074class CConverter(metaclass=CConverterAutoRegister):
2075 """
2076 For the init function, self, name, function, and default
2077 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08002078 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07002079 """
2080
Larry Hastings7726ac92014-01-31 22:03:12 -08002081 # The C name to use for this variable.
2082 name = None
2083
2084 # The Python name to use for this variable.
2085 py_name = None
2086
Larry Hastings78cf85c2014-01-04 12:44:57 -08002087 # The C type to use for this variable.
2088 # 'type' should be a Python string specifying the type, e.g. "int".
2089 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002090 type = None
Larry Hastings31826802013-10-19 00:09:25 -07002091
2092 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08002093 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08002094 # Or the magic value "unknown" if this value is a cannot be evaluated
2095 # at Argument-Clinic-preprocessing time (but is presumed to be valid
2096 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07002097 default = unspecified
2098
Larry Hastings4a55fc52014-01-12 11:09:57 -08002099 # If not None, default must be isinstance() of this type.
2100 # (You can also specify a tuple of types.)
2101 default_type = None
2102
Larry Hastings31826802013-10-19 00:09:25 -07002103 # "default" converted into a C value, as a string.
2104 # Or None if there is no default.
2105 c_default = None
2106
Larry Hastings2a727912014-01-16 11:32:01 -08002107 # "default" converted into a Python value, as a string.
2108 # Or None if there is no default.
2109 py_default = None
2110
Larry Hastingsabc716b2013-11-20 09:13:52 -08002111 # The default value used to initialize the C variable when
2112 # there is no default, but not specifying a default may
2113 # result in an "uninitialized variable" warning. This can
2114 # easily happen when using option groups--although
2115 # properly-written code won't actually use the variable,
2116 # the variable does get passed in to the _impl. (Ah, if
2117 # only dataflow analysis could inline the static function!)
2118 #
2119 # This value is specified as a string.
2120 # Every non-abstract subclass should supply a valid value.
2121 c_ignored_default = 'NULL'
2122
Larry Hastings31826802013-10-19 00:09:25 -07002123 # The C converter *function* to be used, if any.
2124 # (If this is not None, format_unit must be 'O&'.)
2125 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002126
Larry Hastings78cf85c2014-01-04 12:44:57 -08002127 # Should Argument Clinic add a '&' before the name of
2128 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07002129 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08002130
2131 # Should Argument Clinic add a '&' before the name of
2132 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07002133 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08002134
2135 #############################################################
2136 #############################################################
2137 ## You shouldn't need to read anything below this point to ##
2138 ## write your own converter functions. ##
2139 #############################################################
2140 #############################################################
2141
2142 # The "format unit" to specify for this variable when
2143 # parsing arguments using PyArg_ParseTuple (AndKeywords).
2144 # Custom converters should always use the default value of 'O&'.
2145 format_unit = 'O&'
2146
2147 # What encoding do we want for this variable? Only used
2148 # by format units starting with 'e'.
2149 encoding = None
2150
Larry Hastings77561cc2014-01-07 12:13:13 -08002151 # Should this object be required to be a subclass of a specific type?
2152 # If not None, should be a string representing a pointer to a
2153 # PyTypeObject (e.g. "&PyUnicode_Type").
2154 # Only used by the 'O!' format unit (and the "object" converter).
2155 subclass_of = None
2156
Larry Hastings78cf85c2014-01-04 12:44:57 -08002157 # Do we want an adjacent '_length' variable for this variable?
2158 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07002159 length = False
2160
Larry Hastings5c661892014-01-24 06:17:25 -08002161 # Should we show this parameter in the generated
2162 # __text_signature__? This is *almost* always True.
Larry Hastingsc2047262014-01-25 20:43:29 -08002163 # (It's only False for __new__, __init__, and METH_STATIC functions.)
Larry Hastings5c661892014-01-24 06:17:25 -08002164 show_in_signature = True
2165
2166 # Overrides the name used in a text signature.
2167 # The name used for a "self" parameter must be one of
2168 # self, type, or module; however users can set their own.
2169 # This lets the self_converter overrule the user-settable
2170 # name, *just* for the text signature.
2171 # Only set by self_converter.
2172 signature_name = None
2173
2174 # keep in sync with self_converter.__init__!
Larry Hastings7726ac92014-01-31 22:03:12 -08002175 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 -07002176 self.name = name
Larry Hastings7726ac92014-01-31 22:03:12 -08002177 self.py_name = py_name
Larry Hastings31826802013-10-19 00:09:25 -07002178
2179 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08002180 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002181 if isinstance(self.default_type, type):
2182 types_str = self.default_type.__name__
2183 else:
2184 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2185 fail("{}: default value {!r} for field {} is not of type {}".format(
2186 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002187 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002188
Larry Hastingsb4705752014-01-18 21:54:15 -08002189 if c_default:
2190 self.c_default = c_default
2191 if py_default:
2192 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002193
Larry Hastings31826802013-10-19 00:09:25 -07002194 if annotation != unspecified:
2195 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings7726ac92014-01-31 22:03:12 -08002196
2197 # this is deliberate, to prevent you from caching information
2198 # about the function in the init.
2199 # (that breaks if we get cloned.)
2200 # so after this change we will noisily fail.
2201 self.function = LandMine("Don't access members of self.function inside converter_init!")
Larry Hastings31826802013-10-19 00:09:25 -07002202 self.converter_init(**kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002203 self.function = function
Larry Hastings31826802013-10-19 00:09:25 -07002204
2205 def converter_init(self):
2206 pass
2207
2208 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002209 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002210
Larry Hastings5c661892014-01-24 06:17:25 -08002211 def _render_self(self, parameter, data):
2212 self.parameter = parameter
2213 original_name = self.name
2214 name = ensure_legal_c_identifier(original_name)
2215
2216 # impl_arguments
2217 s = ("&" if self.impl_by_reference else "") + name
2218 data.impl_arguments.append(s)
2219 if self.length:
2220 data.impl_arguments.append(self.length_name())
2221
2222 # impl_parameters
2223 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2224 if self.length:
2225 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2226
2227 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002228 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002229 original_name = self.name
2230 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002231
2232 # declarations
2233 d = self.declaration()
2234 data.declarations.append(d)
2235
2236 # initializers
2237 initializers = self.initialize()
2238 if initializers:
2239 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2240
Larry Hastingsc2047262014-01-25 20:43:29 -08002241 # modifications
2242 modifications = self.modify()
2243 if modifications:
2244 data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2245
Larry Hastings31826802013-10-19 00:09:25 -07002246 # keywords
Larry Hastings7726ac92014-01-31 22:03:12 -08002247 data.keywords.append(parameter.name)
Larry Hastings31826802013-10-19 00:09:25 -07002248
2249 # format_units
2250 if self.is_optional() and '|' not in data.format_units:
2251 data.format_units.append('|')
2252 if parameter.is_keyword_only() and '$' not in data.format_units:
2253 data.format_units.append('$')
2254 data.format_units.append(self.format_unit)
2255
2256 # parse_arguments
2257 self.parse_argument(data.parse_arguments)
2258
Larry Hastings31826802013-10-19 00:09:25 -07002259 # cleanup
2260 cleanup = self.cleanup()
2261 if cleanup:
2262 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2263
Larry Hastings5c661892014-01-24 06:17:25 -08002264 def render(self, parameter, data):
2265 """
2266 parameter is a clinic.Parameter instance.
2267 data is a CRenderData instance.
2268 """
2269 self._render_self(parameter, data)
2270 self._render_non_self(parameter, data)
2271
Larry Hastingsebdcb502013-11-23 14:54:00 -08002272 def length_name(self):
2273 """Computes the name of the associated "length" variable."""
2274 if not self.length:
2275 return None
2276 return ensure_legal_c_identifier(self.name) + "_length"
2277
Larry Hastings31826802013-10-19 00:09:25 -07002278 # Why is this one broken out separately?
2279 # For "positional-only" function parsing,
2280 # which generates a bunch of PyArg_ParseTuple calls.
2281 def parse_argument(self, list):
2282 assert not (self.converter and self.encoding)
2283 if self.format_unit == 'O&':
2284 assert self.converter
2285 list.append(self.converter)
2286
2287 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002288 list.append(c_repr(self.encoding))
2289 elif self.subclass_of:
2290 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002291
Larry Hastingsebdcb502013-11-23 14:54:00 -08002292 legal_name = ensure_legal_c_identifier(self.name)
2293 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002294 list.append(s)
2295
Larry Hastingsebdcb502013-11-23 14:54:00 -08002296 if self.length:
2297 list.append("&" + self.length_name())
2298
Larry Hastings31826802013-10-19 00:09:25 -07002299 #
2300 # All the functions after here are intended as extension points.
2301 #
2302
2303 def simple_declaration(self, by_reference=False):
2304 """
2305 Computes the basic declaration of the variable.
2306 Used in computing the prototype declaration and the
2307 variable declaration.
2308 """
2309 prototype = [self.type]
2310 if by_reference or not self.type.endswith('*'):
2311 prototype.append(" ")
2312 if by_reference:
2313 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002314 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002315 return "".join(prototype)
2316
2317 def declaration(self):
2318 """
2319 The C statement to declare this variable.
2320 """
2321 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002322 default = self.c_default
2323 if not default and self.parameter.group:
2324 default = self.c_ignored_default
2325 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002326 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002327 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002328 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002329 if self.length:
2330 declaration.append('\nPy_ssize_clean_t ')
2331 declaration.append(self.length_name())
2332 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002333 s = "".join(declaration)
2334 # double up curly-braces, this string will be used
2335 # as part of a format_map() template later
2336 s = s.replace("{", "{{")
2337 s = s.replace("}", "}}")
2338 return s
Larry Hastings31826802013-10-19 00:09:25 -07002339
2340 def initialize(self):
2341 """
2342 The C statements required to set up this variable before parsing.
2343 Returns a string containing this code indented at column 0.
2344 If no initialization is necessary, returns an empty string.
2345 """
2346 return ""
2347
Larry Hastingsc2047262014-01-25 20:43:29 -08002348 def modify(self):
2349 """
2350 The C statements required to modify this variable after parsing.
2351 Returns a string containing this code indented at column 0.
2352 If no initialization is necessary, returns an empty string.
2353 """
2354 return ""
2355
Larry Hastings31826802013-10-19 00:09:25 -07002356 def cleanup(self):
2357 """
2358 The C statements required to clean up after this variable.
2359 Returns a string containing this code indented at column 0.
2360 If no cleanup is necessary, returns an empty string.
2361 """
2362 return ""
2363
Larry Hastings7726ac92014-01-31 22:03:12 -08002364 def pre_render(self):
2365 """
2366 A second initialization function, like converter_init,
2367 called just before rendering.
2368 You are permitted to examine self.function here.
2369 """
2370 pass
2371
Larry Hastings31826802013-10-19 00:09:25 -07002372
2373class bool_converter(CConverter):
2374 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002375 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002376 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002377 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002378
2379 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002380 if self.default is not unspecified:
2381 self.default = bool(self.default)
2382 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002383
2384class char_converter(CConverter):
2385 type = 'char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002386 default_type = str
Larry Hastings31826802013-10-19 00:09:25 -07002387 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002388 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002389
Larry Hastings4a55fc52014-01-12 11:09:57 -08002390 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002391 if isinstance(self.default, str) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002392 fail("char_converter: illegal default value " + repr(self.default))
2393
2394
Larry Hastings31826802013-10-19 00:09:25 -07002395@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002396class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002397 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002398 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002399 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002400 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002401
2402 def converter_init(self, *, bitwise=False):
2403 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002404 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002405
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002406class byte_converter(unsigned_char_converter): pass
2407
Larry Hastings31826802013-10-19 00:09:25 -07002408class short_converter(CConverter):
2409 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002410 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002411 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002412 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002413
2414class unsigned_short_converter(CConverter):
2415 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002416 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002417 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002418 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002419
2420 def converter_init(self, *, bitwise=False):
2421 if not bitwise:
2422 fail("Unsigned shorts must be bitwise (for now).")
2423
Larry Hastingsebdcb502013-11-23 14:54:00 -08002424@add_legacy_c_converter('C', types='str')
Larry Hastings31826802013-10-19 00:09:25 -07002425class int_converter(CConverter):
2426 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002427 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002428 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002429 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002430
Larry Hastingsdfbeb162014-10-13 10:39:41 +01002431 def converter_init(self, *, types='int', type=None):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002432 if types == 'str':
2433 self.format_unit = 'C'
2434 elif types != 'int':
2435 fail("int_converter: illegal 'types' argument")
Larry Hastingsdfbeb162014-10-13 10:39:41 +01002436 if type != None:
2437 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002438
2439class unsigned_int_converter(CConverter):
2440 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002441 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002442 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002443 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002444
2445 def converter_init(self, *, bitwise=False):
2446 if not bitwise:
2447 fail("Unsigned ints must be bitwise (for now).")
2448
2449class long_converter(CConverter):
2450 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002451 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002452 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002453 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002454
2455class unsigned_long_converter(CConverter):
2456 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002457 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002458 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002459 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002460
2461 def converter_init(self, *, bitwise=False):
2462 if not bitwise:
2463 fail("Unsigned longs must be bitwise (for now).")
2464
2465class PY_LONG_LONG_converter(CConverter):
2466 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002467 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002468 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002469 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002470
2471class unsigned_PY_LONG_LONG_converter(CConverter):
2472 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002473 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002474 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002475 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002476
2477 def converter_init(self, *, bitwise=False):
2478 if not bitwise:
2479 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2480
2481class Py_ssize_t_converter(CConverter):
2482 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002483 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002484 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002485 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002486
2487
2488class float_converter(CConverter):
2489 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002490 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002491 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002492 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002493
2494class double_converter(CConverter):
2495 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002496 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002497 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002498 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002499
2500
2501class Py_complex_converter(CConverter):
2502 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002503 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002504 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002505 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002506
2507
2508class object_converter(CConverter):
2509 type = 'PyObject *'
2510 format_unit = 'O'
2511
Larry Hastings4a55fc52014-01-12 11:09:57 -08002512 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2513 if converter:
2514 if subclass_of:
2515 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2516 self.format_unit = 'O&'
2517 self.converter = converter
2518 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002519 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002520 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002521
Larry Hastings77561cc2014-01-07 12:13:13 -08002522 if type is not None:
2523 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002524
2525
Larry Hastingsebdcb502013-11-23 14:54:00 -08002526@add_legacy_c_converter('s#', length=True)
Larry Hastings2a727912014-01-16 11:32:01 -08002527@add_legacy_c_converter('y', types="bytes")
2528@add_legacy_c_converter('y#', types="bytes", length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002529@add_legacy_c_converter('z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002530@add_legacy_c_converter('z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002531class str_converter(CConverter):
2532 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002533 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002534 format_unit = 's'
2535
Larry Hastingsebdcb502013-11-23 14:54:00 -08002536 def converter_init(self, *, encoding=None, types="str",
2537 length=False, nullable=False, zeroes=False):
2538
2539 types = set(types.strip().split())
Serhiy Storchaka5d438332014-11-15 13:30:42 +02002540 bytes_type = {"bytes"}
2541 str_type = {"str"}
2542 all_3_type = {"bytearray"} | bytes_type | str_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002543 is_bytes = types == bytes_type
2544 is_str = types == str_type
2545 is_all_3 = types == all_3_type
2546
2547 self.length = bool(length)
2548 format_unit = None
2549
2550 if encoding:
2551 self.encoding = encoding
2552
2553 if is_str and not (length or zeroes or nullable):
2554 format_unit = 'es'
2555 elif is_all_3 and not (length or zeroes or nullable):
2556 format_unit = 'et'
2557 elif is_str and length and zeroes and not nullable:
2558 format_unit = 'es#'
2559 elif is_all_3 and length and not (nullable or zeroes):
2560 format_unit = 'et#'
2561
2562 if format_unit.endswith('#'):
Larry Hastings5c661892014-01-24 06:17:25 -08002563 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 -08002564 # TODO set pointer to NULL
2565 # TODO add cleanup for buffer
2566 pass
2567
2568 else:
2569 if zeroes:
2570 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
2571
2572 if is_bytes and not (nullable or length):
2573 format_unit = 'y'
2574 elif is_bytes and length and not nullable:
2575 format_unit = 'y#'
2576 elif is_str and not (nullable or length):
2577 format_unit = 's'
2578 elif is_str and length and not nullable:
2579 format_unit = 's#'
2580 elif is_str and nullable and not length:
2581 format_unit = 'z'
2582 elif is_str and nullable and length:
2583 format_unit = 'z#'
2584
2585 if not format_unit:
2586 fail("str_converter: illegal combination of arguments")
2587 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002588
2589
2590class PyBytesObject_converter(CConverter):
2591 type = 'PyBytesObject *'
2592 format_unit = 'S'
2593
2594class PyByteArrayObject_converter(CConverter):
2595 type = 'PyByteArrayObject *'
2596 format_unit = 'Y'
2597
2598class unicode_converter(CConverter):
2599 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002600 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002601 format_unit = 'U'
2602
Larry Hastingsebdcb502013-11-23 14:54:00 -08002603@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002604@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002605@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002606class Py_UNICODE_converter(CConverter):
2607 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002608 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002609 format_unit = 'u'
2610
Larry Hastingsebdcb502013-11-23 14:54:00 -08002611 def converter_init(self, *, nullable=False, length=False):
2612 format_unit = 'Z' if nullable else 'u'
2613 if length:
2614 format_unit += '#'
2615 self.length = True
2616 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002617
Larry Hastingsebdcb502013-11-23 14:54:00 -08002618#
2619# We define three string conventions for buffer types in the 'types' argument:
2620# 'buffer' : any object supporting the buffer interface
2621# 'rwbuffer': any object supporting the buffer interface, but must be writeable
2622# 'robuffer': any object supporting the buffer interface, but must not be writeable
2623#
2624@add_legacy_c_converter('s*', types='str bytes bytearray buffer')
2625@add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True)
2626@add_legacy_c_converter('w*', types='bytearray rwbuffer')
Larry Hastings31826802013-10-19 00:09:25 -07002627class Py_buffer_converter(CConverter):
2628 type = 'Py_buffer'
2629 format_unit = 'y*'
2630 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002631 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002632
Larry Hastingsebdcb502013-11-23 14:54:00 -08002633 def converter_init(self, *, types='bytes bytearray buffer', nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002634 if self.default not in (unspecified, None):
2635 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08002636 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002637 types = set(types.strip().split())
Serhiy Storchaka5d438332014-11-15 13:30:42 +02002638 bytes_type = {'bytes'}
2639 bytearray_type = {'bytearray'}
2640 buffer_type = {'buffer'}
2641 rwbuffer_type = {'rwbuffer'}
2642 robuffer_type = {'robuffer'}
2643 str_type = {'str'}
Larry Hastingsebdcb502013-11-23 14:54:00 -08002644 bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type
2645
2646 format_unit = None
2647 if types == (str_type | bytes_bytearray_buffer_type):
2648 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07002649 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002650 if nullable:
2651 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
2652 elif types == (bytes_bytearray_buffer_type):
2653 format_unit = 'y*'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002654 elif types == (bytearray_type | rwbuffer_type):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002655 format_unit = 'w*'
2656 if not format_unit:
2657 fail("Py_buffer_converter: illegal combination of arguments")
2658
2659 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002660
2661 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002662 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002663 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002664
2665
Larry Hastings5c661892014-01-24 06:17:25 -08002666def correct_name_for_self(f):
2667 if f.kind in (CALLABLE, METHOD_INIT):
2668 if f.cls:
2669 return "PyObject *", "self"
2670 return "PyModuleDef *", "module"
2671 if f.kind == STATIC_METHOD:
2672 return "void *", "null"
2673 if f.kind in (CLASS_METHOD, METHOD_NEW):
2674 return "PyTypeObject *", "type"
2675 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2676
Larry Hastingsc2047262014-01-25 20:43:29 -08002677def required_type_for_self_for_parser(f):
2678 type, _ = correct_name_for_self(f)
2679 if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2680 return type
2681 return None
2682
Larry Hastings5c661892014-01-24 06:17:25 -08002683
Larry Hastingsebdcb502013-11-23 14:54:00 -08002684class self_converter(CConverter):
2685 """
2686 A special-case converter:
2687 this is the default converter used for "self".
2688 """
Larry Hastings5c661892014-01-24 06:17:25 -08002689 type = None
2690 format_unit = ''
2691
Larry Hastings78cf85c2014-01-04 12:44:57 -08002692 def converter_init(self, *, type=None):
Larry Hastings7726ac92014-01-31 22:03:12 -08002693 self.specified_type = type
2694
2695 def pre_render(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002696 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002697 default_type, default_name = correct_name_for_self(f)
2698 self.signature_name = default_name
Larry Hastings7726ac92014-01-31 22:03:12 -08002699 self.type = self.specified_type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002700
Larry Hastings5c661892014-01-24 06:17:25 -08002701 kind = self.function.kind
2702 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2703
2704 if (kind == STATIC_METHOD) or new_or_init:
2705 self.show_in_signature = False
2706
2707 # tp_new (METHOD_NEW) functions are of type newfunc:
2708 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2709 # PyTypeObject is a typedef for struct _typeobject.
2710 #
2711 # tp_init (METHOD_INIT) functions are of type initproc:
2712 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2713 #
2714 # All other functions generated by Argument Clinic are stored in
2715 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2716 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2717 # However! We habitually cast these functions to PyCFunction,
2718 # since functions that accept keyword arguments don't fit this signature
2719 # but are stored there anyway. So strict type equality isn't important
2720 # for these functions.
2721 #
2722 # So:
2723 #
2724 # * The name of the first parameter to the impl and the parsing function will always
2725 # be self.name.
2726 #
2727 # * The type of the first parameter to the impl will always be of self.type.
2728 #
2729 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2730 # * The type of the first parameter to the parsing function is also self.type.
2731 # This means that if you step into the parsing function, your "self" parameter
2732 # is of the correct type, which may make debugging more pleasant.
2733 #
2734 # * Else if the function is tp_new (METHOD_NEW):
2735 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2736 # so the type signature of the function call is an exact match.
2737 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2738 # in the impl call.
2739 #
2740 # * Else if the function is tp_init (METHOD_INIT):
2741 # * The type of the first parameter to the parsing function is "PyObject *",
2742 # so the type signature of the function call is an exact match.
2743 # * If self.type != "PyObject *", we cast the first parameter to self.type
2744 # in the impl call.
2745
2746 @property
2747 def parser_type(self):
Larry Hastingsc2047262014-01-25 20:43:29 -08002748 return required_type_for_self_for_parser(self.function) or self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002749
Larry Hastingsebdcb502013-11-23 14:54:00 -08002750 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002751 """
2752 parameter is a clinic.Parameter instance.
2753 data is a CRenderData instance.
2754 """
2755 if self.function.kind == STATIC_METHOD:
2756 return
2757
2758 self._render_self(parameter, data)
2759
2760 if self.type != self.parser_type:
2761 # insert cast to impl_argument[0], aka self.
2762 # we know we're in the first slot in all the CRenderData lists,
2763 # because we render parameters in order, and self is always first.
2764 assert len(data.impl_arguments) == 1
2765 assert data.impl_arguments[0] == self.name
2766 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2767
2768 def set_template_dict(self, template_dict):
2769 template_dict['self_name'] = self.name
2770 template_dict['self_type'] = self.parser_type
Larry Hastingsf0537e82014-01-25 22:01:12 -08002771 kind = self.function.kind
2772 cls = self.function.cls
2773
2774 if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef):
2775 if kind == METHOD_NEW:
2776 passed_in_type = self.name
2777 else:
2778 passed_in_type = 'Py_TYPE({})'.format(self.name)
2779
2780 line = '({passed_in_type} == {type_object}) &&\n '
2781 d = {
2782 'type_object': self.function.cls.type_object,
2783 'passed_in_type': passed_in_type
2784 }
2785 template_dict['self_type_check'] = line.format_map(d)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002786
Larry Hastings31826802013-10-19 00:09:25 -07002787
2788
2789def add_c_return_converter(f, name=None):
2790 if not name:
2791 name = f.__name__
2792 if not name.endswith('_return_converter'):
2793 return f
2794 name = name[:-len('_return_converter')]
2795 return_converters[name] = f
2796 return f
2797
2798
2799class CReturnConverterAutoRegister(type):
2800 def __init__(cls, name, bases, classdict):
2801 add_c_return_converter(cls)
2802
2803class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2804
Larry Hastings78cf85c2014-01-04 12:44:57 -08002805 # The C type to use for this variable.
2806 # 'type' should be a Python string specifying the type, e.g. "int".
2807 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002808 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002809
2810 # The Python default value for this parameter, as a Python value.
2811 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002812 default = None
2813
Larry Hastings2a727912014-01-16 11:32:01 -08002814 def __init__(self, *, py_default=None, **kwargs):
2815 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002816 try:
2817 self.return_converter_init(**kwargs)
2818 except TypeError as e:
2819 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2820 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2821
2822 def return_converter_init(self):
2823 pass
2824
2825 def declare(self, data, name="_return_value"):
2826 line = []
2827 add = line.append
2828 add(self.type)
2829 if not self.type.endswith('*'):
2830 add(' ')
2831 add(name + ';')
2832 data.declarations.append(''.join(line))
2833 data.return_value = name
2834
2835 def err_occurred_if(self, expr, data):
2836 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2837
2838 def err_occurred_if_null_pointer(self, variable, data):
2839 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2840
2841 def render(self, function, data):
2842 """
2843 function is a clinic.Function instance.
2844 data is a CRenderData instance.
2845 """
2846 pass
2847
2848add_c_return_converter(CReturnConverter, 'object')
2849
Larry Hastings78cf85c2014-01-04 12:44:57 -08002850class NoneType_return_converter(CReturnConverter):
2851 def render(self, function, data):
2852 self.declare(data)
2853 data.return_conversion.append('''
2854if (_return_value != Py_None)
2855 goto exit;
2856return_value = Py_None;
2857Py_INCREF(Py_None);
2858'''.strip())
2859
Larry Hastings4a55fc52014-01-12 11:09:57 -08002860class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002861 type = 'int'
2862
2863 def render(self, function, data):
2864 self.declare(data)
2865 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002866 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002867
2868class long_return_converter(CReturnConverter):
2869 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002870 conversion_fn = 'PyLong_FromLong'
2871 cast = ''
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002872 unsigned_cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002873
2874 def render(self, function, data):
2875 self.declare(data)
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002876 self.err_occurred_if("_return_value == {}-1".format(self.unsigned_cast), data)
Larry Hastings31826802013-10-19 00:09:25 -07002877 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002878 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002879
Larry Hastings4a55fc52014-01-12 11:09:57 -08002880class int_return_converter(long_return_converter):
2881 type = 'int'
2882 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002883
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002884class init_return_converter(long_return_converter):
2885 """
2886 Special return converter for __init__ functions.
2887 """
2888 type = 'int'
2889 cast = '(long)'
2890
2891 def render(self, function, data):
2892 pass
2893
Larry Hastings4a55fc52014-01-12 11:09:57 -08002894class unsigned_long_return_converter(long_return_converter):
2895 type = 'unsigned long'
2896 conversion_fn = 'PyLong_FromUnsignedLong'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002897 unsigned_cast = '(unsigned long)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002898
2899class unsigned_int_return_converter(unsigned_long_return_converter):
2900 type = 'unsigned int'
2901 cast = '(unsigned long)'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002902 unsigned_cast = '(unsigned int)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002903
2904class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07002905 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002906 conversion_fn = 'PyLong_FromSsize_t'
2907
2908class size_t_return_converter(long_return_converter):
2909 type = 'size_t'
2910 conversion_fn = 'PyLong_FromSize_t'
Larry Hastingsa73cb8a2014-08-05 19:55:21 +10002911 unsigned_cast = '(size_t)'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002912
2913
2914class double_return_converter(CReturnConverter):
2915 type = 'double'
2916 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002917
2918 def render(self, function, data):
2919 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002920 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07002921 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002922 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
2923
2924class float_return_converter(double_return_converter):
2925 type = 'float'
2926 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07002927
2928
2929class DecodeFSDefault_return_converter(CReturnConverter):
2930 type = 'char *'
2931
2932 def render(self, function, data):
2933 self.declare(data)
2934 self.err_occurred_if_null_pointer("_return_value", data)
2935 data.return_conversion.append(
2936 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
2937
2938
2939class IndentStack:
2940 def __init__(self):
2941 self.indents = []
2942 self.margin = None
2943
2944 def _ensure(self):
2945 if not self.indents:
2946 fail('IndentStack expected indents, but none are defined.')
2947
2948 def measure(self, line):
2949 """
2950 Returns the length of the line's margin.
2951 """
2952 if '\t' in line:
Larry Hastings2623c8c2014-02-08 22:15:29 -08002953 fail('Tab characters are illegal in the Argument Clinic DSL.')
Larry Hastings31826802013-10-19 00:09:25 -07002954 stripped = line.lstrip()
2955 if not len(stripped):
2956 # we can't tell anything from an empty line
2957 # so just pretend it's indented like our current indent
2958 self._ensure()
2959 return self.indents[-1]
2960 return len(line) - len(stripped)
2961
2962 def infer(self, line):
2963 """
2964 Infer what is now the current margin based on this line.
2965 Returns:
2966 1 if we have indented (or this is the first margin)
2967 0 if the margin has not changed
2968 -N if we have dedented N times
2969 """
2970 indent = self.measure(line)
2971 margin = ' ' * indent
2972 if not self.indents:
2973 self.indents.append(indent)
2974 self.margin = margin
2975 return 1
2976 current = self.indents[-1]
2977 if indent == current:
2978 return 0
2979 if indent > current:
2980 self.indents.append(indent)
2981 self.margin = margin
2982 return 1
2983 # indent < current
2984 if indent not in self.indents:
2985 fail("Illegal outdent.")
2986 outdent_count = 0
2987 while indent != current:
2988 self.indents.pop()
2989 current = self.indents[-1]
2990 outdent_count -= 1
2991 self.margin = margin
2992 return outdent_count
2993
2994 @property
2995 def depth(self):
2996 """
2997 Returns how many margins are currently defined.
2998 """
2999 return len(self.indents)
3000
3001 def indent(self, line):
3002 """
3003 Indents a line by the currently defined margin.
3004 """
3005 return self.margin + line
3006
3007 def dedent(self, line):
3008 """
3009 Dedents a line by the currently defined margin.
3010 (The inverse of 'indent'.)
3011 """
3012 margin = self.margin
3013 indent = self.indents[-1]
3014 if not line.startswith(margin):
3015 fail('Cannot dedent, line does not start with the previous margin:')
3016 return line[indent:]
3017
3018
3019class DSLParser:
3020 def __init__(self, clinic):
3021 self.clinic = clinic
3022
3023 self.directives = {}
3024 for name in dir(self):
3025 # functions that start with directive_ are added to directives
3026 _, s, key = name.partition("directive_")
3027 if s:
3028 self.directives[key] = getattr(self, name)
3029
3030 # functions that start with at_ are too, with an @ in front
3031 _, s, key = name.partition("at_")
3032 if s:
3033 self.directives['@' + key] = getattr(self, name)
3034
3035 self.reset()
3036
3037 def reset(self):
3038 self.function = None
3039 self.state = self.state_dsl_start
3040 self.parameter_indent = None
3041 self.keyword_only = False
3042 self.group = 0
3043 self.parameter_state = self.ps_start
Larry Hastingsc2047262014-01-25 20:43:29 -08003044 self.seen_positional_with_default = False
Larry Hastings31826802013-10-19 00:09:25 -07003045 self.indent = IndentStack()
3046 self.kind = CALLABLE
3047 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08003048 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08003049 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07003050
Larry Hastingsebdcb502013-11-23 14:54:00 -08003051 def directive_version(self, required):
3052 global version
3053 if version_comparitor(version, required) < 0:
3054 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
3055
Larry Hastings31826802013-10-19 00:09:25 -07003056 def directive_module(self, name):
3057 fields = name.split('.')
3058 new = fields.pop()
3059 module, cls = self.clinic._module_and_class(fields)
3060 if cls:
3061 fail("Can't nest a module inside a class!")
Larry Hastingsc2047262014-01-25 20:43:29 -08003062
3063 if name in module.classes:
3064 fail("Already defined module " + repr(name) + "!")
3065
Larry Hastings31826802013-10-19 00:09:25 -07003066 m = Module(name, module)
3067 module.modules[name] = m
3068 self.block.signatures.append(m)
3069
Larry Hastingsc2047262014-01-25 20:43:29 -08003070 def directive_class(self, name, typedef, type_object):
Larry Hastings31826802013-10-19 00:09:25 -07003071 fields = name.split('.')
3072 in_classes = False
3073 parent = self
3074 name = fields.pop()
3075 so_far = []
3076 module, cls = self.clinic._module_and_class(fields)
3077
Larry Hastingsc2047262014-01-25 20:43:29 -08003078 parent = cls or module
3079 if name in parent.classes:
3080 fail("Already defined class " + repr(name) + "!")
3081
3082 c = Class(name, module, cls, typedef, type_object)
3083 parent.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07003084 self.block.signatures.append(c)
3085
Larry Hastingsbebf7352014-01-17 17:47:17 -08003086 def directive_set(self, name, value):
3087 if name not in ("line_prefix", "line_suffix"):
3088 fail("unknown variable", repr(name))
3089
3090 value = value.format_map({
3091 'block comment start': '/*',
3092 'block comment end': '*/',
3093 })
3094
3095 self.clinic.__dict__[name] = value
3096
3097 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06003098 if command == 'new':
3099 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003100 return
3101
Zachary Ware071baa62014-01-21 23:07:12 -06003102 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08003103 self.clinic.get_destination(name).clear()
3104 fail("unknown destination command", repr(command))
3105
3106
3107 def directive_output(self, field, destination=''):
3108 fd = self.clinic.field_destinations
3109
3110 if field == "preset":
3111 preset = self.clinic.presets.get(destination)
3112 if not preset:
3113 fail("Unknown preset " + repr(destination) + "!")
3114 fd.update(preset)
3115 return
3116
3117 if field == "push":
3118 self.clinic.field_destinations_stack.append(fd.copy())
3119 return
3120
3121 if field == "pop":
3122 if not self.clinic.field_destinations_stack:
3123 fail("Can't 'output pop', stack is empty!")
3124 previous_fd = self.clinic.field_destinations_stack.pop()
3125 fd.update(previous_fd)
3126 return
3127
3128 # secret command for debugging!
3129 if field == "print":
3130 self.block.output.append(pprint.pformat(fd))
3131 self.block.output.append('\n')
3132 return
3133
3134 d = self.clinic.get_destination(destination)
3135
3136 if field == "everything":
3137 for name in list(fd):
3138 fd[name] = d
3139 return
3140
3141 if field not in fd:
Larry Hastings7726ac92014-01-31 22:03:12 -08003142 fail("Invalid field " + repr(field) + ", must be one of:\n preset push pop print everything " + " ".join(fd))
Larry Hastingsbebf7352014-01-17 17:47:17 -08003143 fd[field] = d
3144
3145 def directive_dump(self, name):
3146 self.block.output.append(self.clinic.get_destination(name).dump())
3147
3148 def directive_print(self, *args):
3149 self.block.output.append(' '.join(args))
3150 self.block.output.append('\n')
3151
3152 def directive_preserve(self):
3153 if self.preserve_output:
3154 fail("Can't have preserve twice in one block!")
3155 self.preserve_output = True
3156
Larry Hastings31826802013-10-19 00:09:25 -07003157 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003158 if self.kind is not CALLABLE:
3159 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003160 self.kind = CLASS_METHOD
3161
3162 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003163 if self.kind is not CALLABLE:
3164 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003165 self.kind = STATIC_METHOD
3166
3167 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003168 if self.coexist:
3169 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07003170 self.coexist = True
3171
3172 def parse(self, block):
3173 self.reset()
3174 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08003175 self.saved_output = self.block.output
3176 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07003177 block_start = self.clinic.block_parser.line_number
3178 lines = block.input.split('\n')
3179 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
3180 if '\t' in line:
3181 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
3182 self.state(line)
3183
3184 self.next(self.state_terminal)
3185 self.state(None)
3186
Larry Hastingsbebf7352014-01-17 17:47:17 -08003187 block.output.extend(self.clinic.language.render(clinic, block.signatures))
3188
3189 if self.preserve_output:
3190 if block.output:
3191 fail("'preserve' only works for blocks that don't produce any output!")
3192 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07003193
3194 @staticmethod
3195 def ignore_line(line):
3196 # ignore comment-only lines
3197 if line.lstrip().startswith('#'):
3198 return True
3199
3200 # Ignore empty lines too
3201 # (but not in docstring sections!)
3202 if not line.strip():
3203 return True
3204
3205 return False
3206
3207 @staticmethod
3208 def calculate_indent(line):
3209 return len(line) - len(line.strip())
3210
3211 def next(self, state, line=None):
3212 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3213 self.state = state
3214 if line is not None:
3215 self.state(line)
3216
3217 def state_dsl_start(self, line):
3218 # self.block = self.ClinicOutputBlock(self)
3219 if self.ignore_line(line):
3220 return
Larry Hastings7726ac92014-01-31 22:03:12 -08003221
3222 # is it a directive?
3223 fields = shlex.split(line)
3224 directive_name = fields[0]
3225 directive = self.directives.get(directive_name, None)
3226 if directive:
3227 try:
3228 directive(*fields[1:])
3229 except TypeError as e:
3230 fail(str(e))
3231 return
3232
Larry Hastings31826802013-10-19 00:09:25 -07003233 self.next(self.state_modulename_name, line)
3234
3235 def state_modulename_name(self, line):
3236 # looking for declaration, which establishes the leftmost column
3237 # line should be
3238 # modulename.fnname [as c_basename] [-> return annotation]
3239 # square brackets denote optional syntax.
3240 #
Larry Hastings4a714d42014-01-14 22:22:41 -08003241 # alternatively:
3242 # modulename.fnname [as c_basename] = modulename.existing_fn_name
3243 # clones the parameters and return converter from that
3244 # function. you can't modify them. you must enter a
3245 # new docstring.
3246 #
Larry Hastings31826802013-10-19 00:09:25 -07003247 # (but we might find a directive first!)
3248 #
3249 # this line is permitted to start with whitespace.
3250 # we'll call this number of spaces F (for "function").
3251
3252 if not line.strip():
3253 return
3254
3255 self.indent.infer(line)
3256
Larry Hastings4a714d42014-01-14 22:22:41 -08003257 # are we cloning?
3258 before, equals, existing = line.rpartition('=')
3259 if equals:
3260 full_name, _, c_basename = before.partition(' as ')
3261 full_name = full_name.strip()
3262 c_basename = c_basename.strip()
3263 existing = existing.strip()
3264 if (is_legal_py_identifier(full_name) and
3265 (not c_basename or is_legal_c_identifier(c_basename)) and
3266 is_legal_py_identifier(existing)):
3267 # we're cloning!
3268 fields = [x.strip() for x in existing.split('.')]
3269 function_name = fields.pop()
3270 module, cls = self.clinic._module_and_class(fields)
3271
3272 for existing_function in (cls or module).functions:
3273 if existing_function.name == function_name:
3274 break
3275 else:
3276 existing_function = None
3277 if not existing_function:
Larry Hastings7726ac92014-01-31 22:03:12 -08003278 print("class", cls, "module", module, "existing", existing)
Larry Hastingsc2047262014-01-25 20:43:29 -08003279 print("cls. functions", cls.functions)
Larry Hastings4a714d42014-01-14 22:22:41 -08003280 fail("Couldn't find existing function " + repr(existing) + "!")
3281
3282 fields = [x.strip() for x in full_name.split('.')]
3283 function_name = fields.pop()
3284 module, cls = self.clinic._module_and_class(fields)
3285
3286 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3287 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
Larry Hastings7726ac92014-01-31 22:03:12 -08003288 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 -08003289
3290 self.block.signatures.append(self.function)
3291 (cls or module).functions.append(self.function)
3292 self.next(self.state_function_docstring)
3293 return
3294
Larry Hastings31826802013-10-19 00:09:25 -07003295 line, _, returns = line.partition('->')
3296
3297 full_name, _, c_basename = line.partition(' as ')
3298 full_name = full_name.strip()
3299 c_basename = c_basename.strip() or None
3300
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003301 if not is_legal_py_identifier(full_name):
3302 fail("Illegal function name: {}".format(full_name))
3303 if c_basename and not is_legal_c_identifier(c_basename):
3304 fail("Illegal C basename: {}".format(c_basename))
3305
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003306 return_converter = None
3307 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003308 ast_input = "def x() -> {}: pass".format(returns)
3309 module = None
3310 try:
3311 module = ast.parse(ast_input)
3312 except SyntaxError:
3313 pass
3314 if not module:
3315 fail("Badly-formed annotation for " + full_name + ": " + returns)
3316 try:
3317 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003318 if legacy:
3319 fail("Legacy converter {!r} not allowed as a return converter"
3320 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003321 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003322 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003323 return_converter = return_converters[name](**kwargs)
3324 except ValueError:
3325 fail("Badly-formed annotation for " + full_name + ": " + returns)
3326
3327 fields = [x.strip() for x in full_name.split('.')]
3328 function_name = fields.pop()
3329 module, cls = self.clinic._module_and_class(fields)
3330
Larry Hastings8666e652014-01-12 14:12:59 -08003331 fields = full_name.split('.')
3332 if fields[-1] == '__new__':
3333 if (self.kind != CLASS_METHOD) or (not cls):
3334 fail("__new__ must be a class method!")
3335 self.kind = METHOD_NEW
3336 elif fields[-1] == '__init__':
3337 if (self.kind != CALLABLE) or (not cls):
3338 fail("__init__ must be a normal method, not a class or static method!")
3339 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003340 if not return_converter:
3341 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003342 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003343 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003344
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003345 if not return_converter:
3346 return_converter = CReturnConverter()
3347
Larry Hastings31826802013-10-19 00:09:25 -07003348 if not module:
3349 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3350 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3351 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3352 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003353
3354 # insert a self converter automatically
Larry Hastingsc2047262014-01-25 20:43:29 -08003355 type, name = correct_name_for_self(self.function)
3356 kwargs = {}
3357 if cls and type == "PyObject *":
3358 kwargs['type'] = cls.typedef
Larry Hastings7726ac92014-01-31 22:03:12 -08003359 sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs)
Larry Hastings5c661892014-01-24 06:17:25 -08003360 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3361 self.function.parameters[sc.name] = p_self
3362
Larry Hastings4a714d42014-01-14 22:22:41 -08003363 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003364 self.next(self.state_parameters_start)
3365
3366 # Now entering the parameters section. The rules, formally stated:
3367 #
3368 # * All lines must be indented with spaces only.
3369 # * The first line must be a parameter declaration.
3370 # * The first line must be indented.
3371 # * This first line establishes the indent for parameters.
3372 # * We'll call this number of spaces P (for "parameter").
3373 # * Thenceforth:
3374 # * Lines indented with P spaces specify a parameter.
3375 # * Lines indented with > P spaces are docstrings for the previous
3376 # parameter.
3377 # * We'll call this number of spaces D (for "docstring").
3378 # * All subsequent lines indented with >= D spaces are stored as
3379 # part of the per-parameter docstring.
3380 # * All lines will have the first D spaces of the indent stripped
3381 # before they are stored.
3382 # * It's illegal to have a line starting with a number of spaces X
3383 # such that P < X < D.
3384 # * A line with < P spaces is the first line of the function
3385 # docstring, which ends processing for parameters and per-parameter
3386 # docstrings.
3387 # * The first line of the function docstring must be at the same
3388 # indent as the function declaration.
3389 # * It's illegal to have any line in the parameters section starting
3390 # with X spaces such that F < X < P. (As before, F is the indent
3391 # of the function declaration.)
3392 #
Larry Hastings31826802013-10-19 00:09:25 -07003393 # Also, currently Argument Clinic places the following restrictions on groups:
3394 # * Each group must contain at least one parameter.
3395 # * Each group may contain at most one group, which must be the furthest
3396 # thing in the group from the required parameters. (The nested group
3397 # must be the first in the group when it's before the required
3398 # parameters, and the last thing in the group when after the required
3399 # parameters.)
3400 # * There may be at most one (top-level) group to the left or right of
3401 # the required parameters.
3402 # * You must specify a slash, and it must be after all parameters.
3403 # (In other words: either all parameters are positional-only,
3404 # or none are.)
3405 #
3406 # Said another way:
3407 # * Each group must contain at least one parameter.
3408 # * All left square brackets before the required parameters must be
3409 # consecutive. (You can't have a left square bracket followed
3410 # by a parameter, then another left square bracket. You can't
3411 # have a left square bracket, a parameter, a right square bracket,
3412 # and then a left square bracket.)
3413 # * All right square brackets after the required parameters must be
3414 # consecutive.
3415 #
3416 # These rules are enforced with a single state variable:
3417 # "parameter_state". (Previously the code was a miasma of ifs and
3418 # separate boolean state variables.) The states are:
3419 #
Larry Hastingsc2047262014-01-25 20:43:29 -08003420 # [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ] / <- line
3421 # 01 2 3 4 5 6 7 <- state transitions
Larry Hastings31826802013-10-19 00:09:25 -07003422 #
3423 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3424 # 1: ps_left_square_before. left square brackets before required parameters.
3425 # 2: ps_group_before. in a group, before required parameters.
Larry Hastingsc2047262014-01-25 20:43:29 -08003426 # 3: ps_required. required parameters, positional-or-keyword or positional-only
3427 # (we don't know yet). (renumber left groups!)
3428 # 4: ps_optional. positional-or-keyword or positional-only parameters that
3429 # now must have default values.
3430 # 5: ps_group_after. in a group, after required parameters.
3431 # 6: ps_right_square_after. right square brackets after required parameters.
3432 # 7: ps_seen_slash. seen slash.
Larry Hastings31826802013-10-19 00:09:25 -07003433 ps_start, ps_left_square_before, ps_group_before, ps_required, \
Larry Hastingsc2047262014-01-25 20:43:29 -08003434 ps_optional, ps_group_after, ps_right_square_after, ps_seen_slash = range(8)
Larry Hastings31826802013-10-19 00:09:25 -07003435
3436 def state_parameters_start(self, line):
3437 if self.ignore_line(line):
3438 return
3439
3440 # if this line is not indented, we have no parameters
3441 if not self.indent.infer(line):
3442 return self.next(self.state_function_docstring, line)
3443
Larry Hastings2a727912014-01-16 11:32:01 -08003444 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003445 return self.next(self.state_parameter, line)
3446
3447
3448 def to_required(self):
3449 """
3450 Transition to the "required" parameter state.
3451 """
3452 if self.parameter_state != self.ps_required:
3453 self.parameter_state = self.ps_required
3454 for p in self.function.parameters.values():
3455 p.group = -p.group
3456
3457 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003458 if self.parameter_continuation:
3459 line = self.parameter_continuation + ' ' + line.lstrip()
3460 self.parameter_continuation = ''
3461
Larry Hastings31826802013-10-19 00:09:25 -07003462 if self.ignore_line(line):
3463 return
3464
3465 assert self.indent.depth == 2
3466 indent = self.indent.infer(line)
3467 if indent == -1:
3468 # we outdented, must be to definition column
3469 return self.next(self.state_function_docstring, line)
3470
3471 if indent == 1:
3472 # we indented, must be to new parameter docstring column
3473 return self.next(self.state_parameter_docstring_start, line)
3474
Larry Hastings2a727912014-01-16 11:32:01 -08003475 line = line.rstrip()
3476 if line.endswith('\\'):
3477 self.parameter_continuation = line[:-1]
3478 return
3479
Larry Hastings31826802013-10-19 00:09:25 -07003480 line = line.lstrip()
3481
3482 if line in ('*', '/', '[', ']'):
3483 self.parse_special_symbol(line)
3484 return
3485
3486 if self.parameter_state in (self.ps_start, self.ps_required):
3487 self.to_required()
3488 elif self.parameter_state == self.ps_left_square_before:
3489 self.parameter_state = self.ps_group_before
3490 elif self.parameter_state == self.ps_group_before:
3491 if not self.group:
3492 self.to_required()
Larry Hastingsc2047262014-01-25 20:43:29 -08003493 elif self.parameter_state in (self.ps_group_after, self.ps_optional):
Larry Hastings31826802013-10-19 00:09:25 -07003494 pass
3495 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003496 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
Larry Hastings31826802013-10-19 00:09:25 -07003497
Larry Hastings7726ac92014-01-31 22:03:12 -08003498 # handle "as" for parameters too
3499 c_name = None
3500 name, have_as_token, trailing = line.partition(' as ')
3501 if have_as_token:
3502 name = name.strip()
3503 if ' ' not in name:
3504 fields = trailing.strip().split(' ')
3505 if not fields:
3506 fail("Invalid 'as' clause!")
3507 c_name = fields[0]
3508 if c_name.endswith(':'):
3509 name += ':'
3510 c_name = c_name[:-1]
3511 fields[0] = name
3512 line = ' '.join(fields)
3513
Larry Hastings2a727912014-01-16 11:32:01 -08003514 base, equals, default = line.rpartition('=')
3515 if not equals:
3516 base = default
3517 default = None
Larry Hastingsc2047262014-01-25 20:43:29 -08003518
Larry Hastings31826802013-10-19 00:09:25 -07003519 module = None
3520 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003521 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003522 module = ast.parse(ast_input)
3523 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003524 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08003525 # the last = was probably inside a function call, like
3526 # i: int(nullable=True)
3527 # so assume there was no actual default value.
Larry Hastings2a727912014-01-16 11:32:01 -08003528 default = None
3529 ast_input = "def x({}): pass".format(line)
3530 module = ast.parse(ast_input)
3531 except SyntaxError:
3532 pass
Larry Hastings31826802013-10-19 00:09:25 -07003533 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003534 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003535
3536 function_args = module.body[0].args
3537 parameter = function_args.args[0]
3538
Larry Hastings16c51912014-01-07 11:53:01 -08003539 parameter_name = parameter.arg
3540 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3541
Larry Hastings2a727912014-01-16 11:32:01 -08003542 if not default:
Larry Hastingsc2047262014-01-25 20:43:29 -08003543 if self.parameter_state == self.ps_optional:
3544 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 -08003545 value = unspecified
3546 if 'py_default' in kwargs:
3547 fail("You can't specify py_default without specifying a default value!")
3548 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003549 if self.parameter_state == self.ps_required:
3550 self.parameter_state = self.ps_optional
Larry Hastings2a727912014-01-16 11:32:01 -08003551 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003552 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003553 ast_input = "x = {}".format(default)
Larry Hastingsc2047262014-01-25 20:43:29 -08003554 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003555 try:
3556 module = ast.parse(ast_input)
3557
Larry Hastings5c661892014-01-24 06:17:25 -08003558 if 'c_default' not in kwargs:
3559 # we can only represent very simple data values in C.
3560 # detect whether default is okay, via a blacklist
3561 # of disallowed ast nodes.
3562 class DetectBadNodes(ast.NodeVisitor):
3563 bad = False
3564 def bad_node(self, node):
3565 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003566
Larry Hastings5c661892014-01-24 06:17:25 -08003567 # inline function call
3568 visit_Call = bad_node
3569 # inline if statement ("x = 3 if y else z")
3570 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003571
Larry Hastings5c661892014-01-24 06:17:25 -08003572 # comprehensions and generator expressions
3573 visit_ListComp = visit_SetComp = bad_node
3574 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003575
Larry Hastings5c661892014-01-24 06:17:25 -08003576 # literals for advanced types
3577 visit_Dict = visit_Set = bad_node
3578 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003579
Larry Hastings5c661892014-01-24 06:17:25 -08003580 # "starred": "a = [1, 2, 3]; *a"
3581 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003582
Larry Hastings5c661892014-01-24 06:17:25 -08003583 # allow ellipsis, for now
3584 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003585
Larry Hastings5c661892014-01-24 06:17:25 -08003586 blacklist = DetectBadNodes()
3587 blacklist.visit(module)
3588 bad = blacklist.bad
3589 else:
3590 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003591 # but at least make an attempt at ensuring it's a valid expression.
3592 try:
3593 value = eval(default)
3594 if value == unspecified:
3595 fail("'unspecified' is not a legal default value!")
3596 except NameError:
3597 pass # probably a named constant
3598 except Exception as e:
3599 fail("Malformed expression given as default value\n"
3600 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003601 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003602 fail("Unsupported expression as default value: " + repr(default))
3603
3604 expr = module.body[0].value
3605 # mild hack: explicitly support NULL as a default value
3606 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3607 value = NULL
3608 py_default = 'None'
3609 c_default = "NULL"
3610 elif (isinstance(expr, ast.BinOp) or
3611 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3612 c_default = kwargs.get("c_default")
3613 if not (isinstance(c_default, str) and c_default):
3614 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3615 py_default = default
3616 value = unknown
3617 elif isinstance(expr, ast.Attribute):
3618 a = []
3619 n = expr
3620 while isinstance(n, ast.Attribute):
3621 a.append(n.attr)
3622 n = n.value
3623 if not isinstance(n, ast.Name):
3624 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3625 a.append(n.id)
3626 py_default = ".".join(reversed(a))
3627
3628 c_default = kwargs.get("c_default")
3629 if not (isinstance(c_default, str) and c_default):
3630 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3631
3632 try:
3633 value = eval(py_default)
3634 except NameError:
3635 value = unknown
3636 else:
3637 value = ast.literal_eval(expr)
3638 py_default = repr(value)
3639 if isinstance(value, (bool, None.__class__)):
3640 c_default = "Py_" + py_default
3641 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003642 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003643 else:
3644 c_default = py_default
3645
3646 except SyntaxError as e:
3647 fail("Syntax error: " + repr(e.text))
3648 except (ValueError, AttributeError):
3649 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003650 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003651 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003652 if not (isinstance(c_default, str) and c_default):
3653 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3654
Larry Hastings2a727912014-01-16 11:32:01 -08003655 kwargs.setdefault('c_default', c_default)
3656 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003657
Larry Hastings31826802013-10-19 00:09:25 -07003658 dict = legacy_converters if legacy else converters
3659 legacy_str = "legacy " if legacy else ""
3660 if name not in dict:
3661 fail('{} is not a valid {}converter'.format(name, legacy_str))
Larry Hastings7726ac92014-01-31 22:03:12 -08003662 # if you use a c_name for the parameter, we just give that name to the converter
3663 # but the parameter object gets the python name
3664 converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
Larry Hastings31826802013-10-19 00:09:25 -07003665
3666 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003667
3668 if isinstance(converter, self_converter):
3669 if len(self.function.parameters) == 1:
3670 if (self.parameter_state != self.ps_required):
3671 fail("A 'self' parameter cannot be marked optional.")
3672 if value is not unspecified:
3673 fail("A 'self' parameter cannot have a default value.")
3674 if self.group:
3675 fail("A 'self' parameter cannot be in an optional group.")
3676 kind = inspect.Parameter.POSITIONAL_ONLY
3677 self.parameter_state = self.ps_start
3678 self.function.parameters.clear()
3679 else:
3680 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3681
Larry Hastings31826802013-10-19 00:09:25 -07003682 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003683
3684 if parameter_name in self.function.parameters:
3685 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003686 self.function.parameters[parameter_name] = p
3687
3688 def parse_converter(self, annotation):
3689 if isinstance(annotation, ast.Str):
3690 return annotation.s, True, {}
3691
3692 if isinstance(annotation, ast.Name):
3693 return annotation.id, False, {}
3694
Larry Hastings4a55fc52014-01-12 11:09:57 -08003695 if not isinstance(annotation, ast.Call):
3696 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003697
3698 name = annotation.func.id
3699 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
3700 return name, False, kwargs
3701
3702 def parse_special_symbol(self, symbol):
3703 if self.parameter_state == self.ps_seen_slash:
3704 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3705
3706 if symbol == '*':
3707 if self.keyword_only:
3708 fail("Function " + self.function.name + " uses '*' more than once.")
3709 self.keyword_only = True
3710 elif symbol == '[':
3711 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3712 self.parameter_state = self.ps_left_square_before
3713 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3714 self.parameter_state = self.ps_group_after
3715 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003716 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
Larry Hastings31826802013-10-19 00:09:25 -07003717 self.group += 1
Larry Hastings2623c8c2014-02-08 22:15:29 -08003718 self.function.docstring_only = True
Larry Hastings31826802013-10-19 00:09:25 -07003719 elif symbol == ']':
3720 if not self.group:
3721 fail("Function " + self.function.name + " has a ] without a matching [.")
3722 if not any(p.group == self.group for p in self.function.parameters.values()):
3723 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3724 self.group -= 1
3725 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3726 self.parameter_state = self.ps_group_before
3727 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3728 self.parameter_state = self.ps_right_square_after
3729 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003730 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
Larry Hastings31826802013-10-19 00:09:25 -07003731 elif symbol == '/':
Larry Hastingsc2047262014-01-25 20:43:29 -08003732 # ps_required and ps_optional are allowed here, that allows positional-only without option groups
Larry Hastings31826802013-10-19 00:09:25 -07003733 # to work (and have default values!)
Larry Hastingsc2047262014-01-25 20:43:29 -08003734 if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
3735 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
Larry Hastings31826802013-10-19 00:09:25 -07003736 if self.keyword_only:
3737 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3738 self.parameter_state = self.ps_seen_slash
Berker Peksagf23530f2014-10-19 18:04:38 +03003739 # fixup preceding parameters
Larry Hastings31826802013-10-19 00:09:25 -07003740 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003741 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003742 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3743 p.kind = inspect.Parameter.POSITIONAL_ONLY
3744
3745 def state_parameter_docstring_start(self, line):
3746 self.parameter_docstring_indent = len(self.indent.margin)
3747 assert self.indent.depth == 3
3748 return self.next(self.state_parameter_docstring, line)
3749
3750 # every line of the docstring must start with at least F spaces,
3751 # where F > P.
3752 # these F spaces will be stripped.
3753 def state_parameter_docstring(self, line):
3754 stripped = line.strip()
3755 if stripped.startswith('#'):
3756 return
3757
3758 indent = self.indent.measure(line)
3759 if indent < self.parameter_docstring_indent:
3760 self.indent.infer(line)
3761 assert self.indent.depth < 3
3762 if self.indent.depth == 2:
3763 # back to a parameter
3764 return self.next(self.state_parameter, line)
3765 assert self.indent.depth == 1
3766 return self.next(self.state_function_docstring, line)
3767
3768 assert self.function.parameters
3769 last_parameter = next(reversed(list(self.function.parameters.values())))
3770
3771 new_docstring = last_parameter.docstring
3772
3773 if new_docstring:
3774 new_docstring += '\n'
3775 if stripped:
3776 new_docstring += self.indent.dedent(line)
3777
3778 last_parameter.docstring = new_docstring
3779
3780 # the final stanza of the DSL is the docstring.
3781 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003782 if self.group:
3783 fail("Function " + self.function.name + " has a ] without a matching [.")
3784
3785 stripped = line.strip()
3786 if stripped.startswith('#'):
3787 return
3788
3789 new_docstring = self.function.docstring
3790 if new_docstring:
3791 new_docstring += "\n"
3792 if stripped:
3793 line = self.indent.dedent(line).rstrip()
3794 else:
3795 line = ''
3796 new_docstring += line
3797 self.function.docstring = new_docstring
3798
3799 def format_docstring(self):
3800 f = self.function
3801
Larry Hastings5c661892014-01-24 06:17:25 -08003802 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3803 if new_or_init and not f.docstring:
3804 # don't render a docstring at all, no signature, nothing.
3805 return f.docstring
3806
Larry Hastings2623c8c2014-02-08 22:15:29 -08003807 text, add, output = _text_accumulator()
Larry Hastings7726ac92014-01-31 22:03:12 -08003808 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07003809
3810 ##
3811 ## docstring first line
3812 ##
3813
Larry Hastings2623c8c2014-02-08 22:15:29 -08003814 if new_or_init:
3815 # classes get *just* the name of the class
3816 # not __new__, not __init__, and not module.classname
3817 assert f.cls
3818 add(f.cls.name)
Larry Hastings46258262014-01-22 03:05:49 -08003819 else:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003820 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003821 add('(')
3822
3823 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003824 assert parameters, "We should always have a self parameter. " + repr(f)
3825 assert isinstance(parameters[0].converter, self_converter)
3826 parameters[0].right_bracket_count = 0
3827 parameters_after_self = parameters[1:]
3828 if parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003829 # for now, the only way Clinic supports positional-only parameters
Larry Hastings5c661892014-01-24 06:17:25 -08003830 # is if all of them are positional-only...
3831 #
3832 # ... except for self! self is always positional-only.
3833
3834 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters_after_self]
3835 if parameters_after_self[0].kind == inspect.Parameter.POSITIONAL_ONLY:
Larry Hastings31826802013-10-19 00:09:25 -07003836 assert all(positional_only_parameters)
3837 for p in parameters:
3838 p.right_bracket_count = abs(p.group)
3839 else:
3840 # don't put any right brackets around non-positional-only parameters, ever.
Larry Hastings5c661892014-01-24 06:17:25 -08003841 for p in parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003842 p.right_bracket_count = 0
3843
3844 right_bracket_count = 0
3845
3846 def fix_right_bracket_count(desired):
3847 nonlocal right_bracket_count
3848 s = ''
3849 while right_bracket_count < desired:
3850 s += '['
3851 right_bracket_count += 1
3852 while right_bracket_count > desired:
3853 s += ']'
3854 right_bracket_count -= 1
3855 return s
3856
Larry Hastings2623c8c2014-02-08 22:15:29 -08003857 need_slash = False
3858 added_slash = False
3859 need_a_trailing_slash = False
3860
3861 # we only need a trailing slash:
3862 # * if this is not a "docstring_only" signature
3863 # * and if the last *shown* parameter is
3864 # positional only
3865 if not f.docstring_only:
3866 for p in reversed(parameters):
3867 if not p.converter.show_in_signature:
3868 continue
3869 if p.is_positional_only():
3870 need_a_trailing_slash = True
3871 break
3872
3873
Larry Hastings31826802013-10-19 00:09:25 -07003874 added_star = False
Larry Hastings2623c8c2014-02-08 22:15:29 -08003875
3876 first_parameter = True
3877 last_p = parameters[-1]
3878 line_length = len(''.join(text))
3879 indent = " " * line_length
3880 def add_parameter(text):
3881 nonlocal line_length
3882 nonlocal first_parameter
3883 if first_parameter:
3884 s = text
3885 first_parameter = False
3886 else:
3887 s = ' ' + text
3888 if line_length + len(s) >= 72:
3889 add('\n')
3890 add(indent)
3891 line_length = len(indent)
3892 s = text
3893 line_length += len(s)
3894 add(s)
Larry Hastings31826802013-10-19 00:09:25 -07003895
3896 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08003897 if not p.converter.show_in_signature:
3898 continue
Larry Hastings31826802013-10-19 00:09:25 -07003899 assert p.name
3900
Larry Hastings2623c8c2014-02-08 22:15:29 -08003901 is_self = isinstance(p.converter, self_converter)
3902 if is_self and f.docstring_only:
3903 # this isn't a real machine-parsable signature,
3904 # so let's not print the "self" parameter
3905 continue
3906
3907 if p.is_positional_only():
3908 need_slash = not f.docstring_only
3909 elif need_slash and not (added_slash or p.is_positional_only()):
3910 added_slash = True
3911 add_parameter('/,')
3912
Larry Hastings31826802013-10-19 00:09:25 -07003913 if p.is_keyword_only() and not added_star:
3914 added_star = True
Larry Hastings2623c8c2014-02-08 22:15:29 -08003915 add_parameter('*,')
3916
3917 p_add, p_output = text_accumulator()
3918 p_add(fix_right_bracket_count(p.right_bracket_count))
3919
3920 if isinstance(p.converter, self_converter):
3921 # annotate first parameter as being a "self".
3922 #
3923 # if inspect.Signature gets this function,
3924 # and it's already bound, the self parameter
3925 # will be stripped off.
3926 #
3927 # if it's not bound, it should be marked
3928 # as positional-only.
3929 #
3930 # note: we don't print "self" for __init__,
3931 # because this isn't actually the signature
3932 # for __init__. (it can't be, __init__ doesn't
3933 # have a docstring.) if this is an __init__
3934 # (or __new__), then this signature is for
Berker Peksagf23530f2014-10-19 18:04:38 +03003935 # calling the class to construct a new instance.
Larry Hastings2623c8c2014-02-08 22:15:29 -08003936 p_add('$')
Larry Hastings31826802013-10-19 00:09:25 -07003937
Larry Hastings5c661892014-01-24 06:17:25 -08003938 name = p.converter.signature_name or p.name
Larry Hastings2623c8c2014-02-08 22:15:29 -08003939 p_add(name)
Larry Hastings581ee362014-01-28 05:00:08 -08003940
Larry Hastings31826802013-10-19 00:09:25 -07003941 if p.converter.is_optional():
Larry Hastings2623c8c2014-02-08 22:15:29 -08003942 p_add('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08003943 value = p.converter.py_default
3944 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08003945 value = repr(p.converter.default)
Larry Hastings2623c8c2014-02-08 22:15:29 -08003946 p_add(value)
3947
3948 if (p != last_p) or need_a_trailing_slash:
3949 p_add(',')
3950
3951 add_parameter(p_output())
Larry Hastings31826802013-10-19 00:09:25 -07003952
3953 add(fix_right_bracket_count(0))
Larry Hastings2623c8c2014-02-08 22:15:29 -08003954 if need_a_trailing_slash:
3955 add_parameter('/')
Larry Hastings31826802013-10-19 00:09:25 -07003956 add(')')
3957
Larry Hastings2a727912014-01-16 11:32:01 -08003958 # PEP 8 says:
3959 #
3960 # The Python standard library will not use function annotations
3961 # as that would result in a premature commitment to a particular
3962 # annotation style. Instead, the annotations are left for users
3963 # to discover and experiment with useful annotation styles.
3964 #
3965 # therefore this is commented out:
3966 #
3967 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003968 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08003969 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003970
Larry Hastings2623c8c2014-02-08 22:15:29 -08003971 if not f.docstring_only:
3972 add("\n--\n")
3973
Larry Hastings31826802013-10-19 00:09:25 -07003974 docstring_first_line = output()
3975
3976 # now fix up the places where the brackets look wrong
3977 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
3978
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003979 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07003980 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003981 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07003982 for p in parameters:
3983 if not p.docstring.strip():
3984 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003985 if spacer_line:
3986 add('\n')
3987 else:
3988 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07003989 add(" ")
3990 add(p.name)
3991 add('\n')
3992 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003993 parameters = output()
3994 if parameters:
3995 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07003996
3997 ##
3998 ## docstring body
3999 ##
4000
4001 docstring = f.docstring.rstrip()
4002 lines = [line.rstrip() for line in docstring.split('\n')]
4003
4004 # Enforce the summary line!
4005 # The first line of a docstring should be a summary of the function.
4006 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
4007 # by itself.
4008 #
4009 # Argument Clinic enforces the following rule:
4010 # * either the docstring is empty,
4011 # * or it must have a summary line.
4012 #
4013 # Guido said Clinic should enforce this:
4014 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
4015
4016 if len(lines) >= 2:
4017 if lines[1]:
4018 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
4019 "Every non-blank function docstring must start with\n" +
4020 "a single line summary followed by an empty line.")
4021 elif len(lines) == 1:
4022 # the docstring is only one line right now--the summary line.
4023 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004024 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07004025 lines.append('')
4026
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004027 parameters_marker_count = len(docstring.split('{parameters}')) - 1
4028 if parameters_marker_count > 1:
4029 fail('You may not specify {parameters} more than once in a docstring!')
4030
4031 if not parameters_marker_count:
4032 # insert after summary line
4033 lines.insert(2, '{parameters}')
4034
4035 # insert at front of docstring
4036 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07004037
4038 docstring = "\n".join(lines)
4039
4040 add(docstring)
4041 docstring = output()
4042
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004043 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07004044 docstring = docstring.rstrip()
4045
4046 return docstring
4047
4048 def state_terminal(self, line):
4049 """
4050 Called when processing the block is done.
4051 """
4052 assert not line
4053
4054 if not self.function:
4055 return
4056
4057 if self.keyword_only:
4058 values = self.function.parameters.values()
4059 if not values:
4060 no_parameter_after_star = True
4061 else:
4062 last_parameter = next(reversed(list(values)))
4063 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
4064 if no_parameter_after_star:
4065 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
4066
4067 # remove trailing whitespace from all parameter docstrings
4068 for name, value in self.function.parameters.items():
4069 if not value:
4070 continue
4071 value.docstring = value.docstring.rstrip()
4072
4073 self.function.docstring = self.format_docstring()
4074
4075
Larry Hastings5c661892014-01-24 06:17:25 -08004076
4077
Larry Hastings31826802013-10-19 00:09:25 -07004078# maps strings to callables.
4079# the callable should return an object
4080# that implements the clinic parser
4081# interface (__init__ and parse).
4082#
4083# example parsers:
4084# "clinic", handles the Clinic DSL
4085# "python", handles running Python code
4086#
4087parsers = {'clinic' : DSLParser, 'python': PythonParser}
4088
4089
4090clinic = None
4091
4092
4093def main(argv):
4094 import sys
4095
4096 if sys.version_info.major < 3 or sys.version_info.minor < 3:
4097 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
4098
4099 import argparse
4100 cmdline = argparse.ArgumentParser()
4101 cmdline.add_argument("-f", "--force", action='store_true')
4102 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08004103 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004104 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004105 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004106 cmdline.add_argument("filename", type=str, nargs="*")
4107 ns = cmdline.parse_args(argv)
4108
4109 if ns.converters:
4110 if ns.filename:
4111 print("Usage error: can't specify --converters and a filename at the same time.")
4112 print()
4113 cmdline.print_usage()
4114 sys.exit(-1)
4115 converters = []
4116 return_converters = []
4117 ignored = set("""
4118 add_c_converter
4119 add_c_return_converter
4120 add_default_legacy_c_converter
4121 add_legacy_c_converter
4122 """.strip().split())
4123 module = globals()
4124 for name in module:
4125 for suffix, ids in (
4126 ("_return_converter", return_converters),
4127 ("_converter", converters),
4128 ):
4129 if name in ignored:
4130 continue
4131 if name.endswith(suffix):
4132 ids.append((name, name[:-len(suffix)]))
4133 break
4134 print()
4135
4136 print("Legacy converters:")
4137 legacy = sorted(legacy_converters)
4138 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
4139 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
4140 print()
4141
4142 for title, attribute, ids in (
4143 ("Converters", 'converter_init', converters),
4144 ("Return converters", 'return_converter_init', return_converters),
4145 ):
4146 print(title + ":")
4147 longest = -1
4148 for name, short_name in ids:
4149 longest = max(longest, len(short_name))
4150 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
4151 cls = module[name]
4152 callable = getattr(cls, attribute, None)
4153 if not callable:
4154 continue
4155 signature = inspect.signature(callable)
4156 parameters = []
4157 for parameter_name, parameter in signature.parameters.items():
4158 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
4159 if parameter.default != inspect.Parameter.empty:
4160 s = '{}={!r}'.format(parameter_name, parameter.default)
4161 else:
4162 s = parameter_name
4163 parameters.append(s)
4164 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07004165 print()
Larry Hastings2a727912014-01-16 11:32:01 -08004166 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
4167 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07004168 sys.exit(0)
4169
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004170 if ns.make:
4171 if ns.output or ns.filename:
4172 print("Usage error: can't use -o or filenames with --make.")
4173 print()
4174 cmdline.print_usage()
4175 sys.exit(-1)
4176 for root, dirs, files in os.walk('.'):
Larry Hastings5c661892014-01-24 06:17:25 -08004177 for rcs_dir in ('.svn', '.git', '.hg', 'build'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004178 if rcs_dir in dirs:
4179 dirs.remove(rcs_dir)
4180 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08004181 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004182 continue
4183 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08004184 if ns.verbose:
4185 print(path)
Larry Hastings581ee362014-01-28 05:00:08 -08004186 parse_file(path, force=ns.force, verify=not ns.force)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004187 return
4188
Larry Hastings31826802013-10-19 00:09:25 -07004189 if not ns.filename:
4190 cmdline.print_usage()
4191 sys.exit(-1)
4192
4193 if ns.output and len(ns.filename) > 1:
4194 print("Usage error: can't use -o with multiple filenames.")
4195 print()
4196 cmdline.print_usage()
4197 sys.exit(-1)
4198
4199 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08004200 if ns.verbose:
4201 print(filename)
Larry Hastings581ee362014-01-28 05:00:08 -08004202 parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
Larry Hastings31826802013-10-19 00:09:25 -07004203
4204
4205if __name__ == "__main__":
4206 sys.exit(main(sys.argv[1:]))