diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -574,14 +574,16 @@ parser_definition_no_positional - if (!_PyArg_NoPositional("{name}", args)) + if (({self_name} == {self_type_object}) && + !_PyArg_NoPositional("{name}", args)) goto exit; __________________________________________________ parser_definition_no_keywords - if (!_PyArg_NoKeywords("{name}", kwargs)) + if (({self_name} == {self_type_object}) && + !_PyArg_NoKeywords("{name}", kwargs)) goto exit; __________________________________________________ @@ -690,7 +692,7 @@ impl_definition = templates['impl_definition'] impl_prototype = parser_prototype = parser_definition = None - parser_body_fields = None + parser_body_fields = () def parser_body(prototype, *fields): nonlocal parser_body_fields add, output = text_accumulator() @@ -1475,7 +1477,7 @@ self.add_destination("buffer", "buffer") self.add_destination("two-pass", "two-pass") if filename: - self.add_destination("file", "file", "{basename}.clinic{extension}") + self.add_destination("file", "file", "clinic/{filename}.h") d = self.destinations.get self.field_destinations = collections.OrderedDict(( @@ -1571,6 +1573,12 @@ if destination.type == 'file': try: + dirname = os.path.basename(destination.filename) + try: + os.makedirs(dirname) + except FileExistsError: + if not os.path.isdir(dirname): + fail("Can't write to destination " + repr(destination.filename) + ", can't make directory " + repr(dirname)) with open(destination.filename, "rt") as f: parser_2 = BlockParser(f.read(), language=self.language) blocks = list(parser_2) @@ -1695,10 +1703,12 @@ return "" class Class: - def __init__(self, name, module=None, cls=None): + def __init__(self, name, module=None, cls=None, typedef=None, type_object=None): self.name = name self.module = module self.cls = cls + self.typedef = typedef + self.type_object = type_object self.parent = cls or module self.classes = collections.OrderedDict() @@ -2553,6 +2563,7 @@ def set_template_dict(self, template_dict): template_dict['self_name'] = self.name template_dict['self_type'] = self.parser_type + template_dict['self_type_object'] = self.function.cls.type_object @@ -2828,7 +2839,7 @@ module.modules[name] = m self.block.signatures.append(m) - def directive_class(self, name): + def directive_class(self, name, typedef, type_object): fields = name.split('.') in_classes = False parent = self @@ -2836,7 +2847,7 @@ so_far = [] module, cls = self.clinic._module_and_class(fields) - c = Class(name, module, cls) + c = Class(name, module, cls, typedef, type_object) if cls: cls.classes[name] = c else: @@ -3113,7 +3124,10 @@ # insert a self converter automatically _, name = correct_name_for_self(self.function) - sc = self.function.self_converter = self_converter(name, self.function) + kwargs = {} + if cls: + kwargs['type'] = cls.typedef + sc = self.function.self_converter = self_converter(name, self.function, **kwargs) p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc) self.function.parameters[sc.name] = p_self @@ -3253,12 +3267,16 @@ if not equals: base = default default = None + module = None try: ast_input = "def x({}): pass".format(base) module = ast.parse(ast_input) except SyntaxError: try: + # the last = was probably inside a function call, like + # i: int(nullable=True) + # so assume there was no actual default value. default = None ast_input = "def x({}): pass".format(line) module = ast.parse(ast_input) @@ -3280,10 +3298,10 @@ else: default = default.strip() ast_input = "x = {}".format(default) + bad = False try: module = ast.parse(ast_input) - bad = False if 'c_default' not in kwargs: # we can only represent very simple data values in C. # detect whether default is okay, via a blacklist @@ -3318,7 +3336,15 @@ else: # if they specify a c_default, we can be more lenient about the default value. # but at least ensure that we can turn it into text and reconstitute it correctly. - bad = default != repr(eval(default)) + try: + value = eval(default) + if value == unspecified: + fail("'unspecified' is not a legal default value!") + bad = default != repr(value) + except SyntaxError: + bad = True + except NameError: + pass # probably an unrecognized name constant, that's okay if bad: fail("Unsupported expression as default value: " + repr(default))