Skip to main content

kivy-garden-pyle

日本語版

pyle is an experimental library aimed at reducing the boilerplate needed to create Kivy bindings without using the Kv language.

For example, suppose you want a function that adds a solid-color background to a specific Widget instance and provides a way to revert it. Your code might look like this:

from contextlib import ExitStack

from kivy.graphics import Color, Rectangle
from kivy.clock import Clock


def add_solid_background(widget, *, color=(1., 1. , 1., .3)):
	'''
	Adds a solid-color background to widget and returns a function that reverts it.
	'''
	with ExitStack() as stack:
		defer = stack.callback

		before = widget.canvas.before
		with before:
			defer(before.remove, Color(*color))
			defer(before.remove, rect := Rectangle(pos=widget.pos, size=widget.size))

		def sync_graphics(dt, rect=rect, w=widget):
			rect.pos = w.pos
			rect.size = w.size
		t = Clock.create_trigger(sync_graphics, -1)
		defer(t.cancel)
		widget.bind(pos=t, size=t)
		defer(widget.unbind, pos=t, size=t)

		return stack.pop_all().close


revert = add_solid_background(widget)
...
revert()

Now, here is what an equivalent implementation looks like with pyle:

from contextlib import ExitStack

from kivy.graphics import Color, Rectangle

from kivy_garden import pyle


def add_solid_background(widget, *, color=(1., 1. , 1., .3)):
	with ExitStack() as stack:
		defer = stack.callback

		before = widget.canvas.before
		with before:
			defer(before.remove, Color(*color))
			defer(before.remove, rect := Rectangle(pos=widget.pos, size=widget.size))

		@pyle.throttle_rule
		def sync_graphics(dt, rect=rect, w=widget):
			rect.pos = w.pos
			rect.size = w.size
		stack.enter_context(sync_graphics)

		return stack.pop_all().close

As you can see, the binding code becomes much cleaner. And of course, if you are using an async library, you may want to implement the feature as an async function, tying the background's lifetime to the coroutine it returns:

from contextlib import ExitStack

import asynckivy as ak
from kivy.graphics import Color, Rectangle

from kivy_garden import pyle


async def enable_solid_background(widget, *, color=(1., 1. , 1., .3)):
	'''
	Enables a solid-color background for a widget until the returned coroutine is cancelled.
	'''
	with ExitStack() as stack:
		defer = stack.callback

		before = widget.canvas.before
		with before:
			defer(before.remove, Color(*color))
			defer(before.remove, rect := Rectangle(pos=widget.pos, size=widget.size))

		@pyle.throttle_rule
		def sync_graphics(dt, rect=rect, w=widget):
			rect.pos = w.pos
			rect.size = w.size
		stack.enter_context(sync_graphics)

		await ak.sleep_forever()

In the examples above, the @pyle.throttle_rule decorator turns sync_graphics into a context manager. At this point, bindings are not yet enabled; they are enabled only while the context manager is active.

The context manager is not reentrant, but it is reusable:

# error
with sync_graphics:
    with sync_graphics:
        ...

# fine
with sync_graphics:
    ...
with sync_graphics:
    ...

How does it know which Kivy properties should be observed?

It analyzes the signature and bytecode of the given function. When the function has a pre-filled argument that is an instance of EventDispatcher, any of its Kivy properties accessed via LOAD_ATTR will be observed.

Only the following types of "pre-filled" arguments are subjected to observation:

  • default values like in the sync_graphics example (w=widget)
  • values bound with functools.partial
  • self arguments bound via obj.instance_method

Any other way of filling arguments will not create bindings. For more details, please see test_detect_dependencies.py.

Tested on

  • CPython 3.11 + Kivy 2.3.1
  • CPython 3.12 + Kivy 2.3.1
  • CPython 3.13 + Kivy 2.3.1
  • CPython 3.14 + Kivy be90b9f

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kivy_garden_pyle-0.1.0.tar.gz (4.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kivy_garden_pyle-0.1.0-py3-none-any.whl (4.8 kB view details)

Uploaded Python 3

File details

Details for the file kivy_garden_pyle-0.1.0.tar.gz.

File metadata

  • Download URL: kivy_garden_pyle-0.1.0.tar.gz
  • Upload date:
  • Size: 4.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for kivy_garden_pyle-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3a66d1fdef225ad4f5e0d3642b231137ba2ffaddaca0b00853c58606c4baee16
MD5 55e426f10285ab969abedcbf034dd9c0
BLAKE2b-256 1635b1ece23ae3315408b05986297be1ee9f37fb009830a38265c564dda834c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for kivy_garden_pyle-0.1.0.tar.gz:

Publisher: release.yml on gottadiveintopython/kivy-garden-pyle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kivy_garden_pyle-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for kivy_garden_pyle-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b8a3118434125b93c93f795cd2e376f54b9905c16d46ad0ee68602e51c04684d
MD5 241cbef651a7243664ef628885d6cb4b
BLAKE2b-256 fd45b5fd9e6df43b9062043608dbc710dbfa2dc23fa3597a251e2d849a580fac

See more details on using hashes here.

Provenance

The following attestation bundles were made for kivy_garden_pyle-0.1.0-py3-none-any.whl:

Publisher: release.yml on gottadiveintopython/kivy-garden-pyle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page