What are Fabricators?
Fabricators are special classes that can grab you info from external shell commands or internal Python functions. Fabricators can also read streams of data like a shell command that stays running or a Python generator function.
Fabricators give you some important options during initalization, including:
- The initial value the fabricator should be initialized with
- Where to poll the data from, whether it is a Python function/generator or a shell command
- The poll frequency: how often you want the fabricator to poll the function or command in milliseconds
- Whether you want data as a stream (for polling data from generators and stream shell commands)
So, let's look at some examples of using fabricators!
Media Player State
This example utilizes a fabricator to read a stream from an external command (playerctl -f status
) and print the current media status when it changes.
import fabric
from fabric.utils.fabricator import Fabricator
# create a fabricator to continuously monitor player state using the command
player_fabricator = Fabricator(poll_from="playerctl -F status", stream=True)
# define a function to handle state changes
def print_state_change(fabricator, value): # notice that the first argument is the fabricator itself
print(f"player state changed: {value}")
# connect the fabricator to the "changed" signal and register the handler
player_fabricator.connect("changed", print_state_change)
# start the main loop
fabric.start()
# output (may vary)
# player state changed: playing
# player state changed: paused
# player state changed: playing
# ...
Periodic Date Updates
in this example, we use a fabricator to poll data from the shell command date
every 500ms and print the output of it.
import fabric
from fabric.utils.fabricator import Fabricator
# create a fabricator to periodically retrieve the date and time
date_fabricator = Fabricator(poll_from="date", interval=500) # 500 milliseconds
# define a function to handle date updates
def print_date(fabricator, value):
print(f"current date and time: {value.strip()}")
# connect the fabricator to the "changed" signal and register the handler
date_fabricator.connect("changed", print_date)
# start the main loop
fabric.start()
# output (may vary)
# current date and time: Mon Mar 4 02:50:10 AM EET 2024
# current date and time: Mon Mar 4 02:50:10 AM EET 2024
# current date and time: Mon Mar 4 02:50:11 AM EET 2024
# current date and time: Mon Mar 4 02:50:11 AM EET 2024
# current date and time: Mon Mar 4 02:50:12 AM EET 2024
# ...
Advanced Polling
In this example we fabricate a function instead of a shell command, and demonstrate how to use a stopping condition.
import fabric
from fabric.utils.fabricator import Fabricator
# global variable to track the counter
number = 0
def generate_number(fabricator):
global number
number += 1
return number
# create a fabricator to poll the number generation function
function_fabricator = Fabricator(poll_from=generate_number, interval=300) # 300 milliseconds
def handle_number(fabricator, value):
if value == 43:
fabricator.stop_polling()
print("fabricator stopped")
else:
print(f"generated number: {value}")
# connect the fabricator to the "changed" signal and register the handler
function_fabricator.connect("changed", handle_number)
# start the main loop
fabric.start()
# output
# generated number: 1
# generated number: 2
# generated number: 3
# ...
# generated number: 42
# fabricator stopped