omlish-cext 0.0.0.dev458__tar.gz → 0.0.0.dev491__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish-cext
3
- Version: 0.0.0.dev458
3
+ Version: 0.0.0.dev491
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: omlish==0.0.0.dev458
17
+ Requires-Dist: omlish==0.0.0.dev491
18
18
  Dynamic: license-file
19
19
 
20
20
  # Overview
@@ -77,7 +77,7 @@ dependencies of any kind**.
77
77
  - An optional [metaclass](https://github.com/wrmsr/omlish/blob/master/omlish/dataclasses/metaclass) which removes the
78
78
  need for re-decorating subclasses (with support for inheritance of dataclass parameters like `frozen`), and some
79
79
  basic [base classes](https://github.com/wrmsr/omlish/blob/master/omlish/dataclasses/metaclass/bases.py).
80
- - (Nearly finished) support for ahead-of-time / build-time code generation, greatly reducing import times.
80
+ - Support for ahead-of-time / build-time code generation, significantly reducing import times.
81
81
 
82
82
  The stdlib-equivalent api is exported in such a way as to appear to be direct aliases for the stdlib api itself,
83
83
  simplifying tool support.
@@ -144,7 +144,8 @@ dependencies of any kind**.
144
144
  - **[queries](https://github.com/wrmsr/omlish/blob/master/omlish/sql/queries)** - A SQL query builder with a fluent
145
145
  interface.
146
146
  - **[alchemy](https://github.com/wrmsr/omlish/blob/master/omlish/sql/alchemy)** - SQLAlchemy utilities. The codebase
147
- is moving away from SQLAlchemy however in favor of its own internal SQL api.
147
+ has moved away from SQLAlchemy in favor of its own internal SQL api, but it will likely still remain as an optional
148
+ dep for the api adapter.
148
149
 
149
150
  - **[testing](https://github.com/wrmsr/omlish/blob/master/omlish/testing)** - Test - primarily pytest - helpers,
150
151
  including:
@@ -156,6 +157,10 @@ dependencies of any kind**.
156
157
  *any-future-event-loop-impl* without having multiple fighting plugins (*[I know, I know](https://xkcd.com/927/)*).
157
158
  - **[plugins](https://github.com/wrmsr/omlish/blob/master/omlish/testing/pytest/plugins)** - Various other plugins.
158
159
 
160
+ - **[typedvalues](https://github.com/wrmsr/omlish/blob/master/omlish/typedvalues)** - A little toolkit around 'boxed'
161
+ values, whose 'box' types convey more information than the bare values themselves. A rebellion against kwargs and env
162
+ vars: instead of `foo(bar=1, baz=2)`, you do `foo(Bar(1), Baz(2))`.
163
+
159
164
  - **[lite](https://github.com/wrmsr/omlish/blob/master/omlish/lite)** - The standard library of 'lite' code. This is the
160
165
  only package beneath `lang`, and parts of it are re-exported by it for deduplication. On top of miscellaneous
161
166
  utilities it contains a handful of independent, self-contained, significantly simplified 'lite' equivalents of some
@@ -204,8 +209,8 @@ examples are:
204
209
  - **pytest** - What is used for all standard testing - as lite code has no dependencies of any kind its testing uses
205
210
  stdlib's [unittest](https://docs.python.org/3/library/unittest.html).
206
211
  - **wrapt** - For (optionally-enabled) injector circular proxies.
207
- - **sqlalchemy** - Parts of the codebase use SQLAlchemy for db stuff, but it is being migrated away from in favor of the
208
- internal api. It will however likely still remain as an optional dep for the api adapter.
212
+ - **sqlalchemy** - The codebase has migrated away from SQLAlchemy in favor of the internal api but it retains it as an
213
+ optional dep to support adapting the internal api to it.
209
214
 
210
215
  Additionally, some catchall dep categories include:
211
216
 
@@ -58,7 +58,7 @@ dependencies of any kind**.
58
58
  - An optional [metaclass](https://github.com/wrmsr/omlish/blob/master/omlish/dataclasses/metaclass) which removes the
59
59
  need for re-decorating subclasses (with support for inheritance of dataclass parameters like `frozen`), and some
60
60
  basic [base classes](https://github.com/wrmsr/omlish/blob/master/omlish/dataclasses/metaclass/bases.py).
61
- - (Nearly finished) support for ahead-of-time / build-time code generation, greatly reducing import times.
61
+ - Support for ahead-of-time / build-time code generation, significantly reducing import times.
62
62
 
63
63
  The stdlib-equivalent api is exported in such a way as to appear to be direct aliases for the stdlib api itself,
64
64
  simplifying tool support.
@@ -125,7 +125,8 @@ dependencies of any kind**.
125
125
  - **[queries](https://github.com/wrmsr/omlish/blob/master/omlish/sql/queries)** - A SQL query builder with a fluent
126
126
  interface.
127
127
  - **[alchemy](https://github.com/wrmsr/omlish/blob/master/omlish/sql/alchemy)** - SQLAlchemy utilities. The codebase
128
- is moving away from SQLAlchemy however in favor of its own internal SQL api.
128
+ has moved away from SQLAlchemy in favor of its own internal SQL api, but it will likely still remain as an optional
129
+ dep for the api adapter.
129
130
 
130
131
  - **[testing](https://github.com/wrmsr/omlish/blob/master/omlish/testing)** - Test - primarily pytest - helpers,
131
132
  including:
@@ -137,6 +138,10 @@ dependencies of any kind**.
137
138
  *any-future-event-loop-impl* without having multiple fighting plugins (*[I know, I know](https://xkcd.com/927/)*).
138
139
  - **[plugins](https://github.com/wrmsr/omlish/blob/master/omlish/testing/pytest/plugins)** - Various other plugins.
139
140
 
141
+ - **[typedvalues](https://github.com/wrmsr/omlish/blob/master/omlish/typedvalues)** - A little toolkit around 'boxed'
142
+ values, whose 'box' types convey more information than the bare values themselves. A rebellion against kwargs and env
143
+ vars: instead of `foo(bar=1, baz=2)`, you do `foo(Bar(1), Baz(2))`.
144
+
140
145
  - **[lite](https://github.com/wrmsr/omlish/blob/master/omlish/lite)** - The standard library of 'lite' code. This is the
141
146
  only package beneath `lang`, and parts of it are re-exported by it for deduplication. On top of miscellaneous
142
147
  utilities it contains a handful of independent, self-contained, significantly simplified 'lite' equivalents of some
@@ -185,8 +190,8 @@ examples are:
185
190
  - **pytest** - What is used for all standard testing - as lite code has no dependencies of any kind its testing uses
186
191
  stdlib's [unittest](https://docs.python.org/3/library/unittest.html).
187
192
  - **wrapt** - For (optionally-enabled) injector circular proxies.
188
- - **sqlalchemy** - Parts of the codebase use SQLAlchemy for db stuff, but it is being migrated away from in favor of the
189
- internal api. It will however likely still remain as an optional dep for the api adapter.
193
+ - **sqlalchemy** - The codebase has migrated away from SQLAlchemy in favor of the internal api but it retains it as an
194
+ optional dep to support adapting the internal api to it.
190
195
 
191
196
  Additionally, some catchall dep categories include:
192
197
 
@@ -0,0 +1,186 @@
1
+ // @omlish-cext
2
+ #define PY_SSIZE_T_CLEAN
3
+ #include <Python.h>
4
+
5
+ //
6
+
7
+ #define _MODULE_NAME "_asyncs"
8
+ #define _PACKAGE_NAME "omlish.lang"
9
+ #define _MODULE_FULL_NAME _PACKAGE_NAME "." _MODULE_NAME
10
+
11
+ //
12
+
13
+ typedef struct {
14
+ PyObject *SyncAwaitCoroutineNotTerminatedError;
15
+ PyObject *str_close;
16
+ PyObject *str___await__;
17
+ } module_state;
18
+
19
+ static module_state *
20
+ get_module_state(PyObject *module)
21
+ {
22
+ return (module_state *) PyModule_GetState(module);
23
+ }
24
+
25
+ //
26
+
27
+ static void
28
+ suppress_close(PyObject *iter, module_state *state)
29
+ {
30
+ PyObject *res = PyObject_CallMethodNoArgs(iter, state->str_close);
31
+ if (!res) {
32
+ PyErr_Clear();
33
+ } else {
34
+ Py_DECREF(res);
35
+ }
36
+ }
37
+
38
+ static PyObject *
39
+ sync_await(PyObject *module, PyObject *aw)
40
+ {
41
+ module_state *state = get_module_state(module);
42
+ PyObject *await_meth = NULL;
43
+ PyObject *iter = NULL;
44
+ PyObject *result = NULL;
45
+ PySendResult sres;
46
+
47
+ await_meth = PyObject_GetAttr(aw, state->str___await__);
48
+ if (await_meth == NULL) {
49
+ if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
50
+ PyErr_SetString(PyExc_TypeError, "object is not awaitable (no __await__)");
51
+ }
52
+ goto error;
53
+ }
54
+
55
+ iter = PyObject_CallNoArgs(await_meth);
56
+ Py_DECREF(await_meth);
57
+ await_meth = NULL;
58
+
59
+ if (iter == NULL) {
60
+ goto error;
61
+ }
62
+
63
+ if (!PyIter_Check(iter)) {
64
+ Py_DECREF(iter);
65
+ PyErr_SetString(PyExc_TypeError, "__await__() must return an iterator");
66
+ goto error;
67
+ }
68
+
69
+ sres = PyIter_Send(iter, Py_None, &result);
70
+ if (sres == PYGEN_ERROR) {
71
+ Py_DECREF(iter);
72
+ goto error;
73
+ }
74
+ if (sres == PYGEN_NEXT) {
75
+ Py_XDECREF(result);
76
+ suppress_close(iter, state);
77
+ Py_DECREF(iter);
78
+ PyErr_SetString(state->SyncAwaitCoroutineNotTerminatedError, "Not terminated");
79
+ goto error;
80
+ }
81
+
82
+ Py_DECREF(iter);
83
+ return result;
84
+
85
+ error:
86
+ return NULL;
87
+ }
88
+
89
+ //
90
+
91
+ static PyMethodDef mod_methods[] = {
92
+ {"sync_await", sync_await, METH_O, "sync_await"},
93
+ {NULL, NULL, 0, NULL}
94
+ };
95
+
96
+ static int
97
+ module_traverse(PyObject *module, visitproc visit, void *arg)
98
+ {
99
+ module_state *state = get_module_state(module);
100
+ Py_VISIT(state->SyncAwaitCoroutineNotTerminatedError);
101
+ Py_VISIT(state->str_close);
102
+ Py_VISIT(state->str___await__);
103
+ return 0;
104
+ }
105
+
106
+ static int
107
+ module_clear(PyObject *module)
108
+ {
109
+ module_state *state = get_module_state(module);
110
+ Py_CLEAR(state->SyncAwaitCoroutineNotTerminatedError);
111
+ Py_CLEAR(state->str_close);
112
+ Py_CLEAR(state->str___await__);
113
+ return 0;
114
+ }
115
+
116
+ static void
117
+ module_free(void *module)
118
+ {
119
+ module_clear((PyObject *) module);
120
+ }
121
+
122
+ static int
123
+ module_exec(PyObject *module)
124
+ {
125
+ module_state *state = get_module_state(module);
126
+
127
+ state->str_close = PyUnicode_InternFromString("close");
128
+ if (!state->str_close) {
129
+ return -1;
130
+ }
131
+
132
+ state->str___await__ = PyUnicode_InternFromString("__await__");
133
+ if (!state->str___await__) {
134
+ return -1;
135
+ }
136
+
137
+ PyObject *asyncs_module = PyImport_ImportModule("omlish.lite.asyncs");
138
+ if (!asyncs_module) {
139
+ return -1;
140
+ }
141
+
142
+ state->SyncAwaitCoroutineNotTerminatedError = PyObject_GetAttrString(
143
+ asyncs_module,
144
+ "SyncAwaitCoroutineNotTerminatedError"
145
+ );
146
+ Py_DECREF(asyncs_module);
147
+
148
+ if (!state->SyncAwaitCoroutineNotTerminatedError) {
149
+ return -1;
150
+ }
151
+
152
+ return 0;
153
+ }
154
+
155
+ //
156
+
157
+ PyDoc_STRVAR(module_doc, _MODULE_NAME);
158
+
159
+ static PyModuleDef_Slot module_slots[] = {
160
+ {Py_mod_exec, (void *) module_exec},
161
+ {Py_mod_gil, Py_MOD_GIL_NOT_USED},
162
+ {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
163
+ {0, NULL}
164
+ };
165
+
166
+ static PyModuleDef module_def = {
167
+ .m_base = PyModuleDef_HEAD_INIT,
168
+ .m_name = _MODULE_NAME,
169
+ .m_doc = module_doc,
170
+ .m_size = sizeof(module_state),
171
+ .m_methods = mod_methods,
172
+ .m_slots = module_slots,
173
+ .m_traverse = module_traverse,
174
+ .m_clear = module_clear,
175
+ .m_free = module_free,
176
+ };
177
+
178
+ extern "C" {
179
+
180
+ PyMODINIT_FUNC
181
+ PyInit__asyncs(void)
182
+ {
183
+ return PyModuleDef_Init(&module_def);
184
+ }
185
+
186
+ }
@@ -5,10 +5,13 @@
5
5
  #define Py_BUILD_CORE 1
6
6
  #include "Python.h"
7
7
  #include "internal/pycore_frame.h"
8
+ #if PY_VERSION_HEX >= 0x030E0000
9
+ #include "internal/pycore_interpframe.h"
10
+ #endif
8
11
  #undef Py_BUILD_CORE
9
12
 
10
13
  #if PY_VERSION_HEX < 0x030D0000
11
- # error "This extension requires CPython 3.13+"
14
+ #error "This extension requires CPython 3.13+"
12
15
  #endif
13
16
 
14
17
  //
@@ -50,14 +53,12 @@ _set_frame_builtins(PyObject *self, PyObject *args)
50
53
 
51
54
  std::atomic_ref<PyObject*> builtins_ref(iframe->f_builtins);
52
55
  PyObject* expected = old_builtins;
53
- bool success = builtins_ref.compare_exchange_strong(
56
+ if (builtins_ref.compare_exchange_strong(
54
57
  expected,
55
58
  new_builtins,
56
59
  std::memory_order_acq_rel,
57
60
  std::memory_order_acquire
58
- );
59
-
60
- if (success) {
61
+ )) {
61
62
  Py_RETURN_TRUE;
62
63
  } else {
63
64
  Py_RETURN_FALSE;
@@ -73,13 +74,13 @@ static PyMethodDef capture_methods[] = {
73
74
  {NULL, NULL, 0, NULL}
74
75
  };
75
76
 
76
- static struct PyModuleDef_Slot capture_slots[] = {
77
+ static PyModuleDef_Slot capture_slots[] = {
77
78
  {Py_mod_gil, Py_MOD_GIL_NOT_USED},
78
- {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED},
79
+ {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
79
80
  {0, NULL}
80
81
  };
81
82
 
82
- static struct PyModuleDef capture_module = {
83
+ static PyModuleDef capture_module = {
83
84
  .m_base = PyModuleDef_HEAD_INIT,
84
85
  .m_name = _MODULE_NAME,
85
86
  .m_doc = capture_doc,
@@ -93,7 +94,8 @@ static struct PyModuleDef capture_module = {
93
94
 
94
95
  extern "C" {
95
96
 
96
- PyMODINIT_FUNC PyInit__capture(void)
97
+ PyMODINIT_FUNC
98
+ PyInit__capture(void)
97
99
  {
98
100
  return PyModuleDef_Init(&capture_module);
99
101
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish-cext
3
- Version: 0.0.0.dev458
3
+ Version: 0.0.0.dev491
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: omlish==0.0.0.dev458
17
+ Requires-Dist: omlish==0.0.0.dev491
18
18
  Dynamic: license-file
19
19
 
20
20
  # Overview
@@ -77,7 +77,7 @@ dependencies of any kind**.
77
77
  - An optional [metaclass](https://github.com/wrmsr/omlish/blob/master/omlish/dataclasses/metaclass) which removes the
78
78
  need for re-decorating subclasses (with support for inheritance of dataclass parameters like `frozen`), and some
79
79
  basic [base classes](https://github.com/wrmsr/omlish/blob/master/omlish/dataclasses/metaclass/bases.py).
80
- - (Nearly finished) support for ahead-of-time / build-time code generation, greatly reducing import times.
80
+ - Support for ahead-of-time / build-time code generation, significantly reducing import times.
81
81
 
82
82
  The stdlib-equivalent api is exported in such a way as to appear to be direct aliases for the stdlib api itself,
83
83
  simplifying tool support.
@@ -144,7 +144,8 @@ dependencies of any kind**.
144
144
  - **[queries](https://github.com/wrmsr/omlish/blob/master/omlish/sql/queries)** - A SQL query builder with a fluent
145
145
  interface.
146
146
  - **[alchemy](https://github.com/wrmsr/omlish/blob/master/omlish/sql/alchemy)** - SQLAlchemy utilities. The codebase
147
- is moving away from SQLAlchemy however in favor of its own internal SQL api.
147
+ has moved away from SQLAlchemy in favor of its own internal SQL api, but it will likely still remain as an optional
148
+ dep for the api adapter.
148
149
 
149
150
  - **[testing](https://github.com/wrmsr/omlish/blob/master/omlish/testing)** - Test - primarily pytest - helpers,
150
151
  including:
@@ -156,6 +157,10 @@ dependencies of any kind**.
156
157
  *any-future-event-loop-impl* without having multiple fighting plugins (*[I know, I know](https://xkcd.com/927/)*).
157
158
  - **[plugins](https://github.com/wrmsr/omlish/blob/master/omlish/testing/pytest/plugins)** - Various other plugins.
158
159
 
160
+ - **[typedvalues](https://github.com/wrmsr/omlish/blob/master/omlish/typedvalues)** - A little toolkit around 'boxed'
161
+ values, whose 'box' types convey more information than the bare values themselves. A rebellion against kwargs and env
162
+ vars: instead of `foo(bar=1, baz=2)`, you do `foo(Bar(1), Baz(2))`.
163
+
159
164
  - **[lite](https://github.com/wrmsr/omlish/blob/master/omlish/lite)** - The standard library of 'lite' code. This is the
160
165
  only package beneath `lang`, and parts of it are re-exported by it for deduplication. On top of miscellaneous
161
166
  utilities it contains a handful of independent, self-contained, significantly simplified 'lite' equivalents of some
@@ -204,8 +209,8 @@ examples are:
204
209
  - **pytest** - What is used for all standard testing - as lite code has no dependencies of any kind its testing uses
205
210
  stdlib's [unittest](https://docs.python.org/3/library/unittest.html).
206
211
  - **wrapt** - For (optionally-enabled) injector circular proxies.
207
- - **sqlalchemy** - Parts of the codebase use SQLAlchemy for db stuff, but it is being migrated away from in favor of the
208
- internal api. It will however likely still remain as an optional dep for the api adapter.
212
+ - **sqlalchemy** - The codebase has migrated away from SQLAlchemy in favor of the internal api but it retains it as an
213
+ optional dep to support adapting the internal api to it.
209
214
 
210
215
  Additionally, some catchall dep categories include:
211
216
 
@@ -2,6 +2,7 @@ LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
4
  setup.py
5
+ omlish/lang/_asyncs.cc
5
6
  omlish/lang/imports/_capture.cc
6
7
  omlish_cext.egg-info/PKG-INFO
7
8
  omlish_cext.egg-info/SOURCES.txt
@@ -0,0 +1 @@
1
+ omlish==0.0.0.dev491
@@ -13,7 +13,7 @@ urls = {source = 'https://github.com/wrmsr/omlish'}
13
13
  license = 'BSD-3-Clause'
14
14
  readme = 'README.md'
15
15
  requires-python = '>=3.13'
16
- version = '0.0.0.dev458'
16
+ version = '0.0.0.dev491'
17
17
  classifiers = [
18
18
  'Development Status :: 2 - Pre-Alpha',
19
19
  'Intended Audience :: Developers',
@@ -24,7 +24,7 @@ classifiers = [
24
24
  ]
25
25
  description = 'omlish'
26
26
  dependencies = [
27
- 'omlish == 0.0.0.dev458',
27
+ 'omlish == 0.0.0.dev491',
28
28
  ]
29
29
 
30
30
  [tool.setuptools]
@@ -3,6 +3,11 @@ import setuptools as st
3
3
 
4
4
  st.setup(
5
5
  ext_modules=[
6
+ st.Extension(
7
+ name='omlish.lang._asyncs',
8
+ sources=['omlish/lang/_asyncs.cc'],
9
+ extra_compile_args=['-std=c++20'],
10
+ ),
6
11
  st.Extension(
7
12
  name='omlish.lang.imports._capture',
8
13
  sources=['omlish/lang/imports/_capture.cc'],
@@ -1 +0,0 @@
1
- omlish==0.0.0.dev458