| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| :ref:`Argument Clinic <howto-clinic>` now has a partial support of the | ||
| :ref:`Limited API <limited-c-api>`. Patch by Victor Stinner. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| // For now, only limited C API 3.13 is supported | ||
| #define Py_LIMITED_API 0x030d0000 | ||
|
|
||
| /* Always enable assertions */ | ||
| #undef NDEBUG | ||
|
|
||
| #include "Python.h" | ||
|
|
||
|
|
||
| #include "clinic/_testclinic_limited.c.h" | ||
|
|
||
|
|
||
| /*[clinic input] | ||
| module _testclinic_limited | ||
| [clinic start generated code]*/ | ||
| /*[clinic end generated code: output=da39a3ee5e6b4b0d input=dd408149a4fc0dbb]*/ | ||
|
|
||
|
|
||
| /*[clinic input] | ||
| test_empty_function | ||
|
|
||
| [clinic start generated code]*/ | ||
|
|
||
| static PyObject * | ||
| test_empty_function_impl(PyObject *module) | ||
| /*[clinic end generated code: output=0f8aeb3ddced55cb input=0dd7048651ad4ae4]*/ | ||
| { | ||
| Py_RETURN_NONE; | ||
| } | ||
|
|
||
|
|
||
| /*[clinic input] | ||
| my_int_func -> int | ||
|
|
||
| arg: int | ||
| / | ||
|
|
||
| [clinic start generated code]*/ | ||
|
|
||
| static int | ||
| my_int_func_impl(PyObject *module, int arg) | ||
| /*[clinic end generated code: output=761cd54582f10e4f input=16eb8bba71d82740]*/ | ||
| { | ||
| return arg; | ||
| } | ||
|
|
||
|
|
||
| static PyMethodDef tester_methods[] = { | ||
| TEST_EMPTY_FUNCTION_METHODDEF | ||
| MY_INT_FUNC_METHODDEF | ||
| {NULL, NULL} | ||
| }; | ||
|
|
||
| static struct PyModuleDef _testclinic_module = { | ||
| PyModuleDef_HEAD_INIT, | ||
| .m_name = "_testclinic_limited", | ||
| .m_size = 0, | ||
| .m_methods = tester_methods, | ||
| }; | ||
|
|
||
| PyMODINIT_FUNC | ||
| PyInit__testclinic_limited(void) | ||
| { | ||
| PyObject *m = PyModule_Create(&_testclinic_module); | ||
| if (m == NULL) { | ||
| return NULL; | ||
| } | ||
| return m; | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| Expand Up | @@ -63,6 +63,7 @@ | |
|
|
||
| version = '1' | ||
|
|
||
| DEFAULT_LIMITED_CAPI = False | ||
| NO_VARARG = "PY_SSIZE_T_MAX" | ||
| CLINIC_PREFIX = "__clinic_" | ||
| CLINIC_PREFIXED_ARGS = { | ||
| Expand Down Expand Up | @@ -1360,7 +1361,21 @@ def parser_body( | |
| vararg | ||
| ) | ||
| nargs = f"Py_MIN(nargs, {max_pos})" if max_pos else "0" | ||
| if not new_or_init: | ||
|
|
||
| if clinic.limited_capi: | ||
| # positional-or-keyword arguments | ||
| flags = "METH_VARARGS|METH_KEYWORDS" | ||
|
|
||
| parser_prototype = self.PARSER_PROTOTYPE_KEYWORD | ||
| parser_code = [normalize_snippet(""" | ||
| if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords, | ||
| {parse_arguments})) | ||
| goto exit; | ||
| """, indent=4)] | ||
| argname_fmt = 'args[%d]' | ||
|
Comment thread
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityI do not think that it is correct. args is a Python tuple object here.
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityOh ok, so I suppose that it can be removed.
Sorry, something went wrong.
All reactions
|
||
| declarations = "" | ||
|
|
||
| elif not new_or_init: | ||
| flags = "METH_FASTCALL|METH_KEYWORDS" | ||
| parser_prototype = self.PARSER_PROTOTYPE_FASTCALL_KEYWORDS | ||
| argname_fmt = 'args[%d]' | ||
| Expand Down Expand Up | @@ -2111,7 +2126,8 @@ def print_block( | |
| self, | ||
| block: Block, | ||
| *, | ||
| core_includes: bool = False | ||
| core_includes: bool = False, | ||
| clinic: Clinic | None = None, | ||
| ) -> None: | ||
| input = block.input | ||
| output = block.output | ||
| Expand Down Expand Up | @@ -2140,7 +2156,11 @@ def print_block( | |
| write("\n") | ||
|
|
||
| output = '' | ||
| if core_includes: | ||
| if clinic: | ||
| limited_capi = clinic.limited_capi | ||
| else: | ||
| limited_capi = DEFAULT_LIMITED_CAPI | ||
| if core_includes and not limited_capi: | ||
| output += textwrap.dedent(""" | ||
| #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) | ||
| # include "pycore_gc.h" // PyGC_Head | ||
| Expand Down Expand Up | @@ -2344,6 +2364,7 @@ def __init__( | |
| *, | ||
| filename: str, | ||
| verify: bool = True, | ||
| limited_capi: bool = False, | ||
| ) -> None: | ||
| # maps strings to Parser objects. | ||
| # (instantiated from the "parsers" global.) | ||
| Expand All | @@ -2353,6 +2374,7 @@ def __init__( | |
| fail("Custom printers are broken right now") | ||
| self.printer = printer or BlockPrinter(language) | ||
| self.verify = verify | ||
| self.limited_capi = limited_capi | ||
| self.filename = filename | ||
| self.modules: ModuleDict = {} | ||
| self.classes: ClassDict = {} | ||
| Expand Down Expand Up | @@ -2450,7 +2472,7 @@ def parse(self, input: str) -> str: | |
| self.parsers[dsl_name] = parsers[dsl_name](self) | ||
| parser = self.parsers[dsl_name] | ||
| parser.parse(block) | ||
| printer.print_block(block) | ||
| printer.print_block(block, clinic=self) | ||
|
|
||
| # these are destinations not buffers | ||
| for name, destination in self.destinations.items(): | ||
| Expand All | @@ -2465,7 +2487,7 @@ def parse(self, input: str) -> str: | |
| block.input = "dump " + name + "\n" | ||
| warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.") | ||
| printer.write("\n") | ||
| printer.print_block(block) | ||
| printer.print_block(block, clinic=self) | ||
| continue | ||
|
|
||
| if destination.type == 'file': | ||
| Expand All | @@ -2490,7 +2512,7 @@ def parse(self, input: str) -> str: | |
|
|
||
| block.input = 'preserve\n' | ||
| printer_2 = BlockPrinter(self.language) | ||
| printer_2.print_block(block, core_includes=True) | ||
| printer_2.print_block(block, core_includes=True, clinic=self) | ||
| write_file(destination.filename, printer_2.f.getvalue()) | ||
| continue | ||
|
|
||
| Expand Down Expand Up | @@ -2536,9 +2558,15 @@ def __repr__(self) -> str: | |
| def parse_file( | ||
| filename: str, | ||
| *, | ||
| verify: bool = True, | ||
| output: str | None = None | ||
| ns: argparse.Namespace, | ||
|
Comment thread
Copy link
Copy Markdown
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityI'm replying here since I dislike comments lost on a commit, I don't think that many people will notice it. I'm fine with people doing reviews after I merged changes (I like them!).
Free feel to change it in a follow-up PR. Your rationale makes sense and I don't have a strong preference for passing arguments here. Or I can do it if you prefer. I'm still struggling a lot with this code base and I tried to write the minimum working change without touching too many parts of the code. The problem is that I'm not used with the AC design, so I'm not sure if it's the right place to add code...
I understand your frustration. I didn't expect any review at all in fact. I'm always happy to get reviews, even if it's after I merge my change. Today I wanted to push multiple changes to unblock my work on removing private functions: see PR #108499 which kind-of the end of my "PR serie". I'm frequently frustrated by the fact that GitHub doesn't let me create a "patch serie" (multiple PRs depending on each others). So I have to merge my changes one by one, but I'm always bitten by a CI which dislike my change, then I have to wait 30 min for the next issue... On the AC changes, I didn't expect that make check-c-globals would fail for example. I wanted to push the basis on AC work to add #include and to support the limited C API. For following changes, it should easier to work on multiple PRs at the same time. I'm glad that other people are now working on AC. Adding #include and supporting the limited C API was a long awaited feature for me, I started working on that in 2020 :-)
Sorry, something went wrong.
AlexWaygood reacted with heart emoji
All reactions
Copy link
Copy Markdown
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityFollow-up PR: #108504
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality
Oops, I didn't mean to add a comment on the commit — I meant to comment on the PR. Thanks!
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality
Come on, you know that both Alex and I are active on a daily basis on CPython ;)
Sorry, something went wrong.
All reactions
|
||
| output: str | None = None, | ||
| ) -> None: | ||
| verify = not ns.force | ||
| limited_capi = ns.limited_capi | ||
| # XXX Temporary solution | ||
| if os.path.basename(filename) == '_testclinic_limited.c': | ||
| print(f"{filename} uses limited C API") | ||
| limited_capi = True | ||
| if not output: | ||
| output = filename | ||
|
|
||
| Expand All | @@ -2560,7 +2588,10 @@ def parse_file( | |
| return | ||
|
|
||
| assert isinstance(language, CLanguage) | ||
| clinic = Clinic(language, verify=verify, filename=filename) | ||
| clinic = Clinic(language, | ||
| verify=verify, | ||
| filename=filename, | ||
| limited_capi=limited_capi) | ||
| cooked = clinic.parse(raw) | ||
|
|
||
| write_file(output, cooked) | ||
| Expand Down Expand Up | @@ -5987,6 +6018,8 @@ def create_cli() -> argparse.ArgumentParser: | |
| cmdline.add_argument("--exclude", type=str, action="append", | ||
| help=("a file to exclude in --make mode; " | ||
| "can be given multiple times")) | ||
| cmdline.add_argument("--limited", dest="limited_capi", action='store_true', | ||
| help="use the Limited C API") | ||
| cmdline.add_argument("filename", metavar="FILE", type=str, nargs="*", | ||
| help="the list of files to process") | ||
| return cmdline | ||
| Expand Down Expand Up | @@ -6077,7 +6110,7 @@ def run_clinic(parser: argparse.ArgumentParser, ns: argparse.Namespace) -> None: | |
| continue | ||
| if ns.verbose: | ||
| print(path) | ||
| parse_file(path, verify=not ns.force) | ||
| parse_file(path, ns=ns) | ||
| return | ||
|
|
||
| if not ns.filename: | ||
| Expand All | @@ -6089,7 +6122,7 @@ def run_clinic(parser: argparse.ArgumentParser, ns: argparse.Namespace) -> None: | |
| for filename in ns.filename: | ||
| if ns.verbose: | ||
| print(filename) | ||
| parse_file(filename, output=ns.output, verify=not ns.force) | ||
| parse_file(filename, output=ns.output, ns=ns) | ||
|
|
||
|
|
||
| def main(argv: list[str] | None = None) -> NoReturn: | ||
| Expand Down | ||
| Back | FazBrowse Home | New Git URL |
Uh oh!
There was an error while loading. Please reload this page.