text: import sys
  import os
  import re
  
  from i18n import _
  
  from importlib.machinery import SourceFileLoader
  
  
  class RubberStamp:
  	"""Howdy rubber stamp"""
  
  	UI_TEXT = "ui_text"
  	UI_SUBTEXT = "ui_subtext"
  
  	def set_ui_text(self, text, type=None):
  		"""Convert an ui string to input howdy-gtk understands"""
  		typedec = "M"
  
  		if type == self.UI_SUBTEXT:
  			typedec = "S"
  
  		return self.send_ui_raw(typedec + "=" + text)
  
  	def send_ui_raw(self, command):
  		"""Write raw command to howdy-gtk stdin"""
  		if self.config.getboolean("debug", "verbose_stamps", fallback=False):
  			print("Sending command to howdy-gtk: " + command)
  
  		# Add a newline because the ui reads per line
  		command += " \n"
  		if self.gtk_proc:
  			# Send the command as bytes
  			self.gtk_proc.stdin.write(bytearray(command.encode("utf-8")))
  			self.gtk_proc.stdin.flush()
  
  def execute(config, gtk_proc, opencv):
  	verbose = config.getboolean("debug", "verbose_stamps", fallback=False)
  	dir_path = os.path.dirname(os.path.realpath(__file__))
  	installed_stamps = []
  
  	# Go through each file in the rubberstamp folder
  	for filename in os.listdir(dir_path):
  		# Remove non-readable file or directories
  		if not os.path.isfile(dir_path + "/" + filename):
  			continue
  
  		# Remove meta files
  		if filename in ["__init__.py", ".gitignore"]:
  			continue
  
  		# Add the found file to the list of enabled rubberstamps
  		installed_stamps.append(filename.split(".")[0])
  
  	if verbose: print("Installed rubberstamps: " + ", ".join(installed_stamps))
  
  	# Get the rules defined in the config
  	raw_rules = config.get("rubberstamps", "stamp_rules")
  	rules = raw_rules.split("\n")
  
  	# Go through the rules one by one
  	for rule in rules:
  		rule = rule.strip()
  
  		if len(rule) <= 1:
  			continue
  
  		# Parse the rule with regex
  		regex_result = re.search("^(\w+)\s+([\w\.]+)\s+([a-z]+)(.*)?$", rule, re.IGNORECASE)
  
  		# Error out if the regex did not match (invalid line)
  		if not regex_result:
  			print(_("Error parsing rubberstamp rule: {}").format(rule))
  			continue
  
  		type = regex_result.group(1)
  
  		# Error out if the stamp name in the rule is not a file
  		if type not in installed_stamps:
  			print(_("Stamp not installed: {}").format(type))
  			continue
  
  		# Load the module from file
  		module = SourceFileLoader(type, dir_path + "/" + type + ".py").load_module()
  
  		# Try to get the class with the same name
  		try:
  			constructor = getattr(module, type)
  		except AttributeError:
  			print(_("Stamp error: Class {} not found").format(type))
  			continue
  
  		# Init the class and set common values
  		instance = constructor()
  		instance.verbose = verbose
  		instance.config = config
  		instance.gtk_proc = gtk_proc
  		instance.opencv = opencv
  
  		# Set some opensv shorthands
  		instance.video_capture = opencv["video_capture"]
  		instance.face_detector = opencv["face_detector"]
  		instance.pose_predictor = opencv["pose_predictor"]
  		instance.clahe = opencv["clahe"]
  
  		# Parse and set the 2 required options for all rubberstamps
  		instance.options = {
  			"timeout": float(re.sub("[a-zA-Z]", "", regex_result.group(2))),
  			"failsafe": regex_result.group(3) != "faildeadly"
  		}
  
  		# Try to get the class do declare its other config variables
  		try:
  			instance.declare_config()
  		except Exception:
  			print(_("Internal error in rubberstamp configuration declaration:"))
  
  			import traceback
  			traceback.print_exc()
  			continue
  
  		# Split the optional arguments at the end of the rule by spaces
  		raw_options = regex_result.group(4).split()
  
  		# For each of those aoptional arguments
  		for option in raw_options:
  			# Get the key to the left, and the value to the right of the equal sign
  			key, value = option.split("=")
  
  			# Error out if a key has been set that was not declared by the module before
  			if key not in instance.options:
  				print("Unknow config option for rubberstamp " + type + ": " + key)
  				continue
  
  			# Convert the argument string to an int or float if the declared option has that type
  			if isinstance(instance.options[key], int):
  				value = int(value)
  			elif isinstance(instance.options[key], float):
  				value = float(value)
  
  			instance.options[key] = value
  
  		if verbose:
  			print("Stamp \"" + type + "\" options parsed:")
  			print(instance.options)
  			print("Executing stamp")
  
  		# Make the stamp fail by default
  		result = False
  
  		# Run the stamp code
  		try:
  			result = instance.run()
  		except Exception:
  			print(_("Internal error in rubberstamp:"))
  
  			import traceback
  			traceback.print_exc()
  			continue
  
  		if verbose: print("Stamp \"" + type + "\" returned: " + str(result))
  
  		# Abort authentication if the stamp returned false
  		if result is False:
  			if verbose: print("Authentication aborted by rubber stamp")
  			sys.exit(14)
  
  	# This is outside the for loop, so we've run all the rules
  	if verbose: print("All rubberstamps processed, authentication successful")
  
  	# Exit with no errors
  	sys.exit(0)
  