Skip to content

Commit

Permalink
Merge pull request #468 from hpyproject/topic/GR-51605
Browse files Browse the repository at this point in the history
Enable slot HPy_tp_descr_get.
  • Loading branch information
fangerer authored Jan 29, 2024
2 parents db95cfd + 6971991 commit 7bee0ac
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 38 deletions.
8 changes: 0 additions & 8 deletions docs/api-reference/builder.rst

This file was deleted.

23 changes: 23 additions & 0 deletions docs/api-reference/hpy-sequence.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
HPy Lists and Tuples
====================

Building Tuples and Lists
-------------------------

.. autocmodule:: autogen/public_api.h
:members: HPyTupleBuilder_New,HPyTupleBuilder_Set,HPyTupleBuilder_Build,HPyTupleBuilder_Cancel

.. autocmodule:: autogen/public_api.h
:members: HPyListBuilder_New,HPyListBuilder_Set,HPyListBuilder_Build,HPyListBuilder_Cancel

Tuples
------

.. autocmodule:: autogen/public_api.h
:members: HPyTuple_Check,HPyTuple_FromArray

Lists
-----

.. autocmodule:: autogen/public_api.h
:members: HPyList_Check,HPyList_New,HPyList_Append,HPyList_Insert
2 changes: 1 addition & 1 deletion docs/api-reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ between the modes.
hpy-field
hpy-global
hpy-dict
hpy-sequence
hpy-gil
hpy-err
builder
hpy-eval
public-api

Expand Down
3 changes: 2 additions & 1 deletion docs/porting-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,8 @@ If an error occurs during building the list or tuple, it is necessary to call
:c:func:`HPyListBuilder_Cancel` or :c:func:`HPyTupleBuilder_Cancel`,
respectively, to avoid memory leaks.

For details, see the API reference documentation :doc:`api-reference/builder`.
For details, see the API reference documentation
:doc:`api-reference/hpy-sequence`.

Buffers
-------
Expand Down
2 changes: 2 additions & 0 deletions hpy/devel/include/hpy/autogen_hpyslot.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions hpy/tools/autogen/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pycparser
from packaging import version

if version.parse(pycparser.__version__) < version.parse('2.21'):
raise ImportError('You need pycparser>=2.21 to run autogen')

from .parse import HPyAPI, AUTOGEN_H


def generate(generators, *gen_args):
"""
Takes a sequence of autogen generators that will have access to the parse
tree of 'public_api.c' and can then generate files or whatever.
:param generators: A sequence (e.g. tuple) of classes or callables that
will produce objects with a 'write' method. The 'gen_args' will be passed
to the 'write' method on invocation.
:param gen_args: Arguments for the autogen generator instances.
"""
api = HPyAPI.parse(AUTOGEN_H)
for cls in generators:
cls(api).write(*gen_args)
50 changes: 24 additions & 26 deletions hpy/tools/autogen/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
import py
import pycparser
from packaging import version

if version.parse(pycparser.__version__) < version.parse('2.21'):
raise ImportError('You need pycparser>=2.21 to run autogen')

from .parse import HPyAPI, AUTOGEN_H
from . import generate
from .ctx import (autogen_ctx_h,
autogen_ctx_def_h,
cpython_autogen_ctx_h)
Expand All @@ -30,38 +31,35 @@
from .doc import (autogen_function_index,
autogen_doc_api_mapping)

DEFAULT_GENERATORS = (autogen_ctx_h,
autogen_ctx_def_h,
cpython_autogen_ctx_h,
autogen_trampolines_h,
cpython_autogen_api_impl_h,
universal_autogen_ctx_impl_h,
autogen_hpyfunc_declare_h,
autogen_hpyfunc_trampoline_h,
autogen_ctx_call_i,
autogen_cpython_hpyfunc_trampoline_h,
autogen_hpyslot_h,
autogen_debug_ctx_init_h,
autogen_debug_wrappers,
autogen_debug_ctx_call_i,
autogen_tracer_ctx_init_h,
autogen_tracer_wrappers,
autogen_trace_func_table_c,
autogen_pypy_txt,
autogen_function_index,
autogen_doc_api_mapping)


def main():
if len(sys.argv) != 2:
print('Usage: python -m hpy.tools.autogen OUTDIR')
sys.exit(1)
outdir = py.path.local(sys.argv[1])

api = HPyAPI.parse(AUTOGEN_H)
## for func in api.functions:
## print(func)

for cls in (autogen_ctx_h,
autogen_ctx_def_h,
cpython_autogen_ctx_h,
autogen_trampolines_h,
cpython_autogen_api_impl_h,
universal_autogen_ctx_impl_h,
autogen_hpyfunc_declare_h,
autogen_hpyfunc_trampoline_h,
autogen_ctx_call_i,
autogen_cpython_hpyfunc_trampoline_h,
autogen_hpyslot_h,
autogen_debug_ctx_init_h,
autogen_debug_wrappers,
autogen_debug_ctx_call_i,
autogen_tracer_ctx_init_h,
autogen_tracer_wrappers,
autogen_trace_func_table_c,
autogen_pypy_txt,
autogen_function_index,
autogen_doc_api_mapping):
cls(api).write(outdir)
generate(DEFAULT_GENERATORS, outdir)


if __name__ == '__main__':
Expand Down
76 changes: 74 additions & 2 deletions hpy/tools/autogen/public_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,10 +666,52 @@ HPy_ID(256)
HPy HPyUnicode_Substring(HPyContext *ctx, HPy str, HPy_ssize_t start, HPy_ssize_t end);

/* listobject.h */

/**
* Tests if an object is an instance of a Python list.
*
* :param ctx:
* The execution context.
* :param h:
* A handle to an arbitrary object (must not be ``HPy_NULL``).
*
* :returns:
* Non-zero if object ``h`` is an instance of type ``list`` or an instance
* of a subtype of ``list``, and ``0`` otherwise.
*/
HPy_ID(198)
int HPyList_Check(HPyContext *ctx, HPy h);

/**
* Creates a new list instance with length ``len``.
*
* :param ctx:
* The execution context.
* :param len:
* A Python list object (must not be ``HPy_NULL``). Otherwise, a
* ``SystemError`` will be raised.
*
* :returns:
* The new list instance on success, or ``HPy_NULL`` on failure.
*/
HPy_ID(199)
HPy HPyList_New(HPyContext *ctx, HPy_ssize_t len);

/**
* Append item ``h_item`` to list ``h_list``.
*
* :param ctx:
* The execution context.
* :param h_list:
* A Python list object (must not be ``HPy_NULL``). Otherwise, a
* ``SystemError`` will be raised.
* :param h_item:
* The item to append (must not be ``HPy_NULL``).
*
* :returns:
* Return ``0`` if successful; return ``-1`` and set an exception if
* unsuccessful.
*/
HPy_ID(200)
int HPyList_Append(HPyContext *ctx, HPy h_list, HPy h_item);

Expand Down Expand Up @@ -763,11 +805,41 @@ HPy_ID(258)
HPy HPyDict_Copy(HPyContext *ctx, HPy h);

/* tupleobject.h */

/**
* Tests if an object is an instance of a Python tuple.
*
* :param ctx:
* The execution context.
* :param h:
* A handle to an arbitrary object (must not be ``HPy_NULL``).
*
* :returns:
* Non-zero if object ``h`` is an instance of type ``tuple`` or an instance
* of a subtype of ``tuple``, and ``0`` otherwise.
*/
HPy_ID(203)
int HPyTuple_Check(HPyContext *ctx, HPy h);

/**
* Create a tuple from an array.
*
* Note: Consider to use the convenience function :c:func:`HPyTuple_Pack` to
* create a tuple.
*
* :param ctx:
* The execution context.
* :param items:
* An array of items to use for initialization of the tuple.
* :param n:
* The number of elements in array ``items``.
*
* :return:
* A new tuple with ``n`` elements or ``HPy_NULL`` in case of an error
* occurred.
*/
HPy_ID(204)
HPy HPyTuple_FromArray(HPyContext *ctx, const HPy items[], HPy_ssize_t n);
// note: HPyTuple_Pack is implemented as a macro in common/macros.h

/* sliceobject.h */

Expand Down Expand Up @@ -1299,7 +1371,7 @@ typedef enum {
//HPy_tp_clear = SLOT(51, HPyFunc_X), NOT SUPPORTED, use tp_traverse
//HPy_tp_dealloc = SLOT(52, HPyFunc_X), NOT SUPPORTED
//HPy_tp_del = SLOT(53, HPyFunc_X),
//HPy_tp_descr_get = SLOT(54, HPyFunc_X),
HPy_tp_descr_get = SLOT(54, HPyFunc_TERNARYFUNC),
//HPy_tp_descr_set = SLOT(55, HPyFunc_X),
//HPy_tp_doc = SLOT(56, HPyFunc_X),
//HPy_tp_getattr = SLOT(57, HPyFunc_X),
Expand Down
24 changes: 24 additions & 0 deletions test/test_slots.py
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,27 @@ def test_tp_richcompare(self):
#
assert not p1 >= p2
assert p1 >= p1

def test_tp_descr_get(self):
mod = self.make_module("""
@DEFINE_PointObject
@DEFINE_Point_new
HPyDef_SLOT(Point_get, HPy_tp_descr_get);
static HPy
Point_get_impl(HPyContext *ctx, HPy self, HPy obj, HPy type)
{
if (HPy_IsNull(obj) || HPy_Is(ctx, self, ctx->h_None)) {
return HPy_Dup(ctx, self);
}
return HPyLong_FromLong(ctx, 123);
}
@EXPORT_POINT_TYPE(&Point_new, &Point_get)
@INIT
""")
p = mod.Point(10, 10)
class Dummy:
point_func = p
assert Dummy.point_func is p
assert Dummy().point_func == 123

0 comments on commit 7bee0ac

Please sign in to comment.