pythonx-compose 0.1.0a2__py3-none-any.whl → 0.1.0a3__py3-none-any.whl

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 +1 @@
1
- # GENERATED by scripts/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact kotlin-stubs, workflow run 37131041879, commit 452cc807, Compose 1.11.1). Do not edit.
1
+ # GENERATED by scripts/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact ks, workflow run 42402779166, commit 9507e6dd, Compose 1.11.1-ext.2). Do not edit.
@@ -50,8 +50,10 @@ import re
50
50
  import sys
51
51
  import types
52
52
  import weakref
53
+ from collections.abc import Callable, Iterable, Mapping
53
54
  from functools import lru_cache
54
55
  from pathlib import Path
56
+ from typing import Protocol, TypedDict, cast
55
57
 
56
58
  ROOT_MODULE = "python_multiplatform"
57
59
  BINDING_MODULE = "python_multiplatform.binding"
@@ -61,6 +63,30 @@ _MANIFEST = Path(__file__).resolve().parent / "pythonx-map.toml"
61
63
  _LOWER_UPPER = re.compile(r"([a-z0-9])([A-Z])")
62
64
  _ACRONYM_WORD = re.compile(r"([A-Z]+)([A-Z][a-z])")
63
65
 
66
+ # `pythonx-map.toml`'s shape. Its tables are keyed by Kotlin and module names, so the hyphenated
67
+ # keys are spelled in the functional form.
68
+ _ValueClasses = TypedDict("_ValueClasses", {"raw-primitive-allowed": list[str]}, total=False)
69
+ Manifest = TypedDict(
70
+ "Manifest",
71
+ {
72
+ "modules": dict[str, str],
73
+ "value-classes": _ValueClasses,
74
+ "aliases": dict[str, dict[str, "list[str] | dict[str, str]"]],
75
+ },
76
+ total=False,
77
+ )
78
+
79
+
80
+ class BindingLayer(Protocol):
81
+ """What this module asks of `python_multiplatform.binding`."""
82
+
83
+ def allow_raw_primitive(self, kotlin_type: str, /) -> None: ...
84
+ def register_empty(self, kotlin_type: object, empty_factory: object, /) -> None: ...
85
+
86
+
87
+ Describe = Callable[[types.ModuleType, str], object]
88
+ """`python_multiplatform.describe(module, name)`."""
89
+
64
90
 
65
91
  def snake_case(kotlin_name: str) -> str:
66
92
  """`fillMaxWidth` -> `fill_max_width`, `toURLString` -> `to_url_string`, `zIndex` -> `z_index`."""
@@ -80,12 +106,12 @@ def python_name(kotlin_name: str) -> str:
80
106
 
81
107
 
82
108
  @lru_cache(maxsize=1)
83
- def manifest() -> dict:
109
+ def manifest() -> Manifest:
84
110
  """`pythonx-map.toml`, parsed once."""
85
111
  import tomllib
86
112
 
87
113
  with _MANIFEST.open("rb") as handle:
88
- return tomllib.load(handle)
114
+ return cast(Manifest, tomllib.load(handle))
89
115
 
90
116
 
91
117
  def kotlin_package_of(module_name: str) -> str:
@@ -97,7 +123,7 @@ def kotlin_package_of(module_name: str) -> str:
97
123
  ) from None
98
124
 
99
125
 
100
- def binding_layer():
126
+ def binding_layer() -> BindingLayer:
101
127
  """The binder's installed binding module, or a `RuntimeError` that says what did not happen."""
102
128
  binding = sys.modules.get(BINDING_MODULE)
103
129
  if binding is None:
@@ -105,34 +131,47 @@ def binding_layer():
105
131
  "the python-multiplatform binding layer is not installed: the Kotlin host must run "
106
132
  "PythonxAdapter.install() before pythonx.compose can resolve a Kotlin declaration"
107
133
  )
108
- return binding
134
+ return cast(BindingLayer, binding)
109
135
 
110
136
 
111
- _PRIMED = weakref.WeakSet()
137
+ _PRIMED: weakref.WeakSet[BindingLayer] = weakref.WeakSet()
138
+ _MODIFIER_TYPE = "androidx.compose.ui.Modifier"
112
139
 
113
140
 
114
- def _prime(binding) -> None:
115
- """Hand this binding layer the manifest's value-class allowlist, once.
141
+ def _modifier_companion() -> object:
142
+ """`Modifier.Companion` read live from `androidx.compose.ui.Modifier` (python-multiplatform #324)."""
143
+ return cast(object, importlib.import_module("androidx.compose.ui").Modifier.Companion)
144
+
145
+
146
+ def _prime(binding: BindingLayer) -> None:
147
+ """Hand this binding layer the manifest's value-class allowlist and the default empty `Modifier`, once.
116
148
 
117
149
  Method names and keywords on a proxy are the binder's own since python-multiplatform #131
118
- (snake_case by this package's rule); nothing is registered for them here.
150
+ (snake_case by this package's rule); nothing is registered for them here. Since
151
+ python-multiplatform #324, `Modifier.Companion` is bound as a value on the proxy class and
152
+ `register_empty` accepts a callable (`SPEC.md` S6.2, #138); if the caller has not already
153
+ registered an explicit empty factory for `androidx.compose.ui.Modifier`, `_modifier_companion`
154
+ is registered as the default.
119
155
  """
120
156
  if binding in _PRIMED:
121
157
  return
122
158
  for kotlin_type in manifest().get("value-classes", {}).get("raw-primitive-allowed", ()):
123
159
  binding.allow_raw_primitive(kotlin_type)
160
+ factories = cast("Mapping[str, object]", getattr(binding, "_EMPTY_FACTORIES", {}))
161
+ if _MODIFIER_TYPE not in factories:
162
+ binding.register_empty(_MODIFIER_TYPE, _modifier_companion)
124
163
  _PRIMED.add(binding)
125
164
 
126
165
 
127
- def kotlin_module(module_name: str):
166
+ def kotlin_module(module_name: str) -> types.ModuleType:
128
167
  """The binder's module for the Kotlin package `module_name` maps to."""
129
168
  _prime(binding_layer())
130
169
  return importlib.import_module(kotlin_package_of(module_name))
131
170
 
132
171
 
133
- def _name_table(kotlin) -> dict:
172
+ def _name_table(kotlin: types.ModuleType) -> dict[str, str]:
134
173
  """Pythonic name -> Kotlin name for everything the Kotlin module reports, with collisions refused."""
135
- table = {}
174
+ table: dict[str, str] = {}
136
175
  for kotlin_name in dir(kotlin):
137
176
  if kotlin_name.startswith("_"):
138
177
  continue
@@ -147,7 +186,7 @@ def _name_table(kotlin) -> dict:
147
186
  return table
148
187
 
149
188
 
150
- def _declared_type(kotlin, kotlin_name: str):
189
+ def _declared_type(kotlin: types.ModuleType, kotlin_name: str) -> tuple[object, str | None] | None:
151
190
  """`(kind, declared return type)` of the bound name [kotlin_name] in [kotlin], without reading it.
152
191
 
153
192
  `python_multiplatform.describe(module, name)` answers from the binder's table and never runs a
@@ -155,7 +194,7 @@ def _declared_type(kotlin, kotlin_name: str):
155
194
  that is not a single bound declaration (an overload set, a child package), answers `None`.
156
195
  """
157
196
  root = sys.modules.get(ROOT_MODULE)
158
- describe = getattr(root, "describe", None)
197
+ describe = cast("Describe | None", getattr(root, "describe", None))
159
198
  if describe is None:
160
199
  return None
161
200
  try:
@@ -164,10 +203,13 @@ def _declared_type(kotlin, kotlin_name: str):
164
203
  return None
165
204
  if not isinstance(described, dict):
166
205
  return None
167
- return described.get("kind"), described.get("returns")
206
+ # The binder's answer is a plain dict of strings; its values are only compared and sliced here.
207
+ answer = cast(dict[str, object], described)
208
+ returns = answer.get("returns")
209
+ return answer.get("kind"), returns if isinstance(returns, str) else None
168
210
 
169
211
 
170
- def _pythonic(value, name):
212
+ def _pythonic(value: object) -> object:
171
213
  if isinstance(value, types.ModuleType):
172
214
  # A Kotlin object served as a sub-package. Since python-multiplatform #35 the binder lists it
173
215
  # and exposes it as an attribute of its parent, so the name table reaches it directly.
@@ -177,7 +219,7 @@ def _pythonic(value, name):
177
219
  return value
178
220
 
179
221
 
180
- def _resolve(kotlin, name: str):
222
+ def _resolve(kotlin: types.ModuleType, name: str) -> tuple[object, bool] | None:
181
223
  """What the Pythonic [name] means in the binder's module [kotlin]: `(value, cacheable)` or `None`.
182
224
 
183
225
  A name the module lists is looked up by the rule. An upper-case name it does not list may be a
@@ -187,10 +229,10 @@ def _resolve(kotlin, name: str):
187
229
  """
188
230
  kotlin_name = _name_table(kotlin).get(name)
189
231
  if kotlin_name is not None:
190
- value = getattr(kotlin, kotlin_name)
232
+ value = cast(object, getattr(kotlin, kotlin_name))
191
233
  # The binder declined to cache it -- a live property, read again on every access -- so this
192
234
  # layer does not freeze it either.
193
- return _pythonic(value, name), kotlin_name in vars(kotlin)
235
+ return _pythonic(value), kotlin_name in cast(Mapping[str, object], vars(kotlin))
194
236
  if name[:1].isupper():
195
237
  try:
196
238
  nested = importlib.import_module(kotlin.__name__ + "." + name)
@@ -203,7 +245,7 @@ def _resolve(kotlin, name: str):
203
245
  _STATIC_GETTER = "STATIC_GETTER"
204
246
 
205
247
 
206
- def _constant_groups(kotlin) -> dict:
248
+ def _constant_groups(kotlin: types.ModuleType) -> dict[str, dict[str, str]]:
207
249
  """Group name -> {Pythonic constant name: Kotlin name}, for the Kotlin object [kotlin].
208
250
 
209
251
  A group is a type nested in the object, `P.G`, that some constant of `P` is declared as; it holds
@@ -213,12 +255,13 @@ def _constant_groups(kotlin) -> dict:
213
255
  """
214
256
  prefix = kotlin.__name__ + "."
215
257
  members = _name_table(kotlin)
216
- groups: dict = {}
258
+ groups: dict[str, dict[str, str]] = {}
217
259
  for pythonic, kotlin_name in members.items():
218
260
  declared = _declared_type(kotlin, kotlin_name)
219
261
  if declared is None or declared[0] != _STATIC_GETTER or not declared[1]:
220
262
  continue
221
- group = declared[1][len(prefix):] if declared[1].startswith(prefix) else ""
263
+ returns = declared[1]
264
+ group = returns[len(prefix):] if returns.startswith(prefix) else ""
222
265
  if not group[:1].isupper() or "." in group or group in members:
223
266
  continue
224
267
  groups.setdefault(group, {})[pythonic] = kotlin_name
@@ -236,17 +279,24 @@ class KotlinObject:
236
279
 
237
280
  __slots__ = ("_kotlin", "_cache", "_groups")
238
281
 
239
- def __init__(self, kotlin_module):
282
+ _kotlin: types.ModuleType
283
+ _cache: dict[str, object]
284
+ _groups: dict[str, dict[str, str]] | None
285
+
286
+ def __init__(self, kotlin_module: types.ModuleType) -> None:
240
287
  object.__setattr__(self, "_kotlin", kotlin_module)
241
- object.__setattr__(self, "_cache", {})
288
+ object.__setattr__(self, "_cache", dict[str, object]())
242
289
  object.__setattr__(self, "_groups", None)
243
290
 
244
- def _constant_groups(self) -> dict:
245
- if self._groups is None:
246
- object.__setattr__(self, "_groups", _constant_groups(self._kotlin))
247
- return self._groups
291
+ def _constant_groups(self) -> dict[str, dict[str, str]]:
292
+ known = self._groups
293
+ if known is not None:
294
+ return known
295
+ groups = _constant_groups(self._kotlin)
296
+ object.__setattr__(self, "_groups", groups)
297
+ return groups
248
298
 
249
- def __getattr__(self, name):
299
+ def __getattr__(self, name: str) -> object:
250
300
  if name.startswith("__") and name.endswith("__"):
251
301
  raise AttributeError(name)
252
302
  cached = self._cache.get(name)
@@ -260,19 +310,21 @@ class KotlinObject:
260
310
  f"{self._kotlin.__name__} has nothing spelled {name!r} under pythonx's naming rule"
261
311
  )
262
312
  # The grouping is metadata and is kept; the constants inside are read on each access.
263
- resolved = ConstantGroup(self, f"{self._kotlin.__name__}.{name}", members), True
313
+ group = ConstantGroup(self, f"{self._kotlin.__name__}.{name}", members)
314
+ self._cache[name] = group
315
+ return group
264
316
  value, cacheable = resolved
265
317
  if cacheable:
266
318
  self._cache[name] = value
267
319
  return value
268
320
 
269
- def __setattr__(self, name, value):
321
+ def __setattr__(self, name: str, value: object) -> None:
270
322
  raise AttributeError(f"{self._kotlin.__name__} is a Kotlin object; its members are read-only here")
271
323
 
272
- def __dir__(self):
324
+ def __dir__(self) -> list[str]:
273
325
  return sorted(set(_name_table(self._kotlin)) | set(self._constant_groups()))
274
326
 
275
- def __repr__(self):
327
+ def __repr__(self) -> str:
276
328
  return f"<pythonx view of Kotlin object {self._kotlin.__name__}>"
277
329
 
278
330
 
@@ -286,11 +338,11 @@ class CallableKotlinObject(KotlinObject):
286
338
 
287
339
  __slots__ = ()
288
340
 
289
- def __call__(self, *args, **kwargs):
290
- return self._kotlin(*args, **kwargs)
341
+ def __call__(self, *args: object, **kwargs: object) -> object:
342
+ return cast("Callable[..., object]", self._kotlin)(*args, **kwargs)
291
343
 
292
344
 
293
- def _kotlin_object(kotlin_module):
345
+ def _kotlin_object(kotlin_module: types.ModuleType) -> KotlinObject:
294
346
  """The namespace for a Kotlin object module: callable only when the binder made the module callable."""
295
347
  return CallableKotlinObject(kotlin_module) if callable(kotlin_module) else KotlinObject(kotlin_module)
296
348
 
@@ -305,12 +357,16 @@ class ConstantGroup:
305
357
 
306
358
  __slots__ = ("_owner", "_kotlin_type", "_members")
307
359
 
308
- def __init__(self, owner, kotlin_type, members):
360
+ _owner: KotlinObject
361
+ _kotlin_type: str
362
+ _members: dict[str, str]
363
+
364
+ def __init__(self, owner: KotlinObject, kotlin_type: str, members: Mapping[str, str]) -> None:
309
365
  object.__setattr__(self, "_owner", owner)
310
366
  object.__setattr__(self, "_kotlin_type", kotlin_type)
311
367
  object.__setattr__(self, "_members", dict(members))
312
368
 
313
- def __getattr__(self, name):
369
+ def __getattr__(self, name: str) -> object:
314
370
  if name.startswith("__") and name.endswith("__"):
315
371
  raise AttributeError(name)
316
372
  if name not in self._members:
@@ -319,33 +375,36 @@ class ConstantGroup:
319
375
  f"{self._owner._kotlin.__name__} declared as {self._kotlin_type}: "
320
376
  + ", ".join(sorted(self._members))
321
377
  )
322
- return getattr(self._owner, name)
378
+ # The owner's own resolver, by name: a constant is never an attribute of `KotlinObject` itself.
379
+ return self._owner.__getattr__(name)
323
380
 
324
- def __setattr__(self, name, value):
381
+ def __setattr__(self, name: str, value: object) -> None:
325
382
  raise AttributeError(f"{self._kotlin_type} is a group of Kotlin constants; they are read-only here")
326
383
 
327
- def __dir__(self):
384
+ def __dir__(self) -> list[str]:
328
385
  return sorted(self._members)
329
386
 
330
- def __repr__(self):
387
+ def __repr__(self) -> str:
331
388
  return f"<pythonx group of {self._owner._kotlin.__name__} constants declared {self._kotlin_type}>"
332
389
 
333
390
 
334
- def _aliases(module_name: str) -> dict:
391
+ def _aliases(module_name: str) -> dict[str, tuple[str, str]]:
335
392
  """Name -> `(source module, attribute path in it)`, per the manifest's `[aliases]`.
336
393
 
337
394
  An entry under a source module is a list of names (lent under the same name, path = the name) or
338
395
  a table `{ lent = "Path.To.Attr" }` (a different name, through an attribute path).
339
396
  """
340
- borrowed = {}
397
+ borrowed: dict[str, tuple[str, str]] = {}
341
398
  for source, lent in manifest().get("aliases", {}).get(module_name, {}).items():
342
- pairs = ((name, name) for name in lent) if isinstance(lent, list) else lent.items()
399
+ pairs: Iterable[tuple[str, str]] = (
400
+ ((name, name) for name in lent) if isinstance(lent, list) else lent.items()
401
+ )
343
402
  for name, path in pairs:
344
403
  borrowed[name] = (source, path)
345
404
  return borrowed
346
405
 
347
406
 
348
- def _borrow(module_name: str, name: str, source: str, path: str):
407
+ def _borrow(module_name: str, name: str, source: str, path: str) -> object:
349
408
  """The value of the alias [name]: [path] read in [source].
350
409
 
351
410
  A bare name is resolved once and kept in the owner's namespace. A path with attribute steps is
@@ -353,22 +412,22 @@ def _borrow(module_name: str, name: str, source: str, path: str):
353
412
  serves `Icons.Default` afresh on every read and this layer does not freeze it either.
354
413
  """
355
414
  head, *rest = path.split(".")
356
- value = getattr(importlib.import_module(source), head)
415
+ value = cast(object, getattr(importlib.import_module(source), head))
357
416
  for step in rest:
358
- value = getattr(value, step)
417
+ value = cast(object, getattr(value, step))
359
418
  if not rest:
360
419
  setattr(sys.modules[module_name], name, value)
361
420
  return value
362
421
 
363
422
 
364
- def reexport(module_name: str):
423
+ def reexport(module_name: str) -> tuple[Callable[[str], object], Callable[[], list[str]]]:
365
424
  """The module-level `__getattr__` and `__dir__` for the mapped package `module_name`.
366
425
 
367
426
  Nothing is resolved here, only when a name is first read, so importing a `pythonx.compose`
368
427
  module needs neither the manifest row's Kotlin package nor an installed binder.
369
428
  """
370
429
 
371
- def __getattr__(name):
430
+ def __getattr__(name: str) -> object:
372
431
  if name.startswith("__") and name.endswith("__"):
373
432
  raise AttributeError(name)
374
433
  if importlib.util.find_spec(module_name + "." + name) is not None:
@@ -396,8 +455,8 @@ def reexport(module_name: str):
396
455
  setattr(sys.modules[module_name], name, value)
397
456
  return value
398
457
 
399
- def __dir__():
400
- own = set(vars(sys.modules[module_name])) | set(_aliases(module_name))
458
+ def __dir__() -> list[str]:
459
+ own = set(cast(Mapping[str, object], vars(sys.modules[module_name]))) | set(_aliases(module_name))
401
460
  try:
402
461
  own.update(_name_table(kotlin_module(module_name)))
403
462
  except (RuntimeError, ImportError):
@@ -1,4 +1,4 @@
1
- # GENERATED by scripts/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact kotlin-stubs, workflow run 37131041879, commit 452cc807, Compose 1.11.1). Do not edit.
1
+ # GENERATED by scripts/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact ks, workflow run 42402779166, commit 9507e6dd, Compose 1.11.1-ext.2). Do not edit.
2
2
  import typing as _t
3
3
 
4
4
  class BorderStroke:
@@ -1,2 +1,2 @@
1
- # GENERATED by scripts/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact kotlin-stubs, workflow run 37131041879, commit 452cc807, Compose 1.11.1). Do not edit.
1
+ # GENERATED by scripts/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact ks, workflow run 42402779166, commit 9507e6dd, Compose 1.11.1-ext.2). Do not edit.
2
2
  from pythonx.compose.layout import *
@@ -1,4 +1,4 @@
1
- # GENERATED by scripts/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact kotlin-stubs, workflow run 37131041879, commit 452cc807, Compose 1.11.1). Do not edit.
1
+ # GENERATED by scripts/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact ks, workflow run 42402779166, commit 9507e6dd, Compose 1.11.1-ext.2). Do not edit.
2
2
  import typing as _t
3
3
 
4
4
  class _TextFieldState_clearText(_t.Protocol):
@@ -25,6 +25,9 @@ class OutputTransformation:
25
25
  class TextFieldBuffer:
26
26
  """Kotlin: androidx.compose.foundation.text.input.TextFieldBuffer"""
27
27
 
28
+ class TextFieldDecorator:
29
+ """Kotlin: androidx.compose.foundation.text.input.TextFieldDecorator"""
30
+
28
31
  class TextFieldLineLimits:
29
32
  """Kotlin: androidx.compose.foundation.text.input.TextFieldLineLimits"""
30
33
 
@@ -37,6 +40,9 @@ class TextFieldState:
37
40
  set_text_and_place_cursor_at_end: _t.ClassVar[_TextFieldState_setTextAndPlaceCursorAtEnd]
38
41
  set_text_and_select_all: _t.ClassVar[_TextFieldState_setTextAndSelectAll]
39
42
  to_text_field_buffer: _t.ClassVar[_TextFieldState_toTextFieldBuffer]
43
+ def edit(self, block: _t.Callable[[TextFieldBuffer], None]) -> None:
44
+ """Kotlin member: androidx.compose.foundation.text.input.TextFieldState.edit"""
45
+ ...
40
46
  @property
41
47
  def composition(self) -> _t.Any | None:
42
48
  """Kotlin property: androidx.compose.foundation.text.input.TextFieldState.composition (androidx.compose.foundation.text.input.TextFieldState.composition: androidx.compose.ui.text.TextRange?)"""