aboutsummaryrefslogtreecommitdiffstats
path: root/python/servo/build_commands.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/servo/build_commands.py')
-rw-r--r--python/servo/build_commands.py162
1 files changed, 53 insertions, 109 deletions
diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py
index a3875e2c679..8bf3d1fa8a1 100644
--- a/python/servo/build_commands.py
+++ b/python/servo/build_commands.py
@@ -23,6 +23,8 @@ import stat
from time import time
+import notifypy
+
from mach.decorators import (
CommandArgument,
CommandProvider,
@@ -36,113 +38,6 @@ from servo.gstreamer import windows_dlls, windows_plugins, macos_dylibs, macos_p
from servo.util import host_triple
-def format_duration(seconds):
- return str(datetime.timedelta(seconds=int(seconds)))
-
-
-def notify_linux(title, text):
- try:
- import dbus
- bus = dbus.SessionBus()
- notify_obj = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
- method = notify_obj.get_dbus_method("Notify", "org.freedesktop.Notifications")
- method(title, 0, "", text, "", [], {"transient": True}, -1)
- except ImportError:
- raise Exception("Optional Python module 'dbus' is not installed.")
-
-
-def notify_win(title, text):
- try:
- from servo.win32_toast import WindowsToast
- w = WindowsToast()
- w.balloon_tip(title, text)
- except WindowsError:
- from ctypes import Structure, windll, POINTER, sizeof
- from ctypes.wintypes import DWORD, HANDLE, WINFUNCTYPE, BOOL, UINT
-
- class FLASHWINDOW(Structure):
- _fields_ = [("cbSize", UINT),
- ("hwnd", HANDLE),
- ("dwFlags", DWORD),
- ("uCount", UINT),
- ("dwTimeout", DWORD)]
-
- FlashWindowExProto = WINFUNCTYPE(BOOL, POINTER(FLASHWINDOW))
- FlashWindowEx = FlashWindowExProto(("FlashWindowEx", windll.user32))
- FLASHW_CAPTION = 0x01
- FLASHW_TRAY = 0x02
- FLASHW_TIMERNOFG = 0x0C
-
- params = FLASHWINDOW(sizeof(FLASHWINDOW),
- windll.kernel32.GetConsoleWindow(),
- FLASHW_CAPTION | FLASHW_TRAY | FLASHW_TIMERNOFG, 3, 0)
- FlashWindowEx(params)
-
-
-def notify_darwin(title, text):
- try:
- import Foundation
-
- bundleDict = Foundation.NSBundle.mainBundle().infoDictionary()
- bundleIdentifier = 'CFBundleIdentifier'
- if bundleIdentifier not in bundleDict:
- bundleDict[bundleIdentifier] = 'mach'
-
- note = Foundation.NSUserNotification.alloc().init()
- note.setTitle_(title)
- note.setInformativeText_(text)
-
- now = Foundation.NSDate.dateWithTimeInterval_sinceDate_(0, Foundation.NSDate.date())
- note.setDeliveryDate_(now)
-
- centre = Foundation.NSUserNotificationCenter.defaultUserNotificationCenter()
- centre.scheduleNotification_(note)
- except ImportError:
- raise Exception("Optional Python module 'pyobjc' is not installed.")
-
-
-def notify_with_command(command):
- def notify(title, text):
- if call([command, title, text]) != 0:
- raise Exception("Could not run '%s'." % command)
- return notify
-
-
-def notify_build_done(config, elapsed, success=True):
- """Generate desktop notification when build is complete and the
- elapsed build time was longer than 30 seconds."""
- if elapsed > 30:
- notify(config, "Servo build",
- "%s in %s" % ("Completed" if success else "FAILED", format_duration(elapsed)))
-
-
-def notify(config, title, text):
- """Generate a desktop notification using appropriate means on
- supported platforms Linux, Windows, and Mac OS. On unsupported
- platforms, this function acts as a no-op.
-
- If notify-command is set in the [tools] section of the configuration,
- that is used instead."""
- notify_command = config["tools"].get("notify-command")
- if notify_command:
- func = notify_with_command(notify_command)
- else:
- platforms = {
- "linux": notify_linux,
- "linux2": notify_linux,
- "win32": notify_win,
- "darwin": notify_darwin
- }
- func = platforms.get(sys.platform)
-
- if func is not None:
- try:
- func(title, text)
- except Exception as e:
- extra = getattr(e, "message", "")
- print("[Warning] Could not generate notification! %s" % extra, file=sys.stderr)
-
-
@CommandProvider
class MachCommands(CommandBase):
@Command('build',
@@ -752,9 +647,12 @@ class MachCommands(CommandBase):
pass
# Generate Desktop Notification if elapsed-time > some threshold value
- notify_build_done(self.config, elapsed, status == 0)
- print("Build %s in %s" % ("Completed" if status == 0 else "FAILED", format_duration(elapsed)))
+ elapsed_delta = datetime.timedelta(seconds=int(elapsed))
+ build_message = f"{'Succeeded' if status == 0 else 'Failed'} in {elapsed_delta}"
+ self.notify("Servo build", build_message)
+ print(build_message)
+
return status
@Command('clean',
@@ -814,6 +712,52 @@ class MachCommands(CommandBase):
else:
os.remove(artifact)
+ def notify(self, title: str, message: str):
+ """Generate desktop notification when build is complete and the
+ elapsed build time was longer than 30 seconds.
+
+ If notify-command is set in the [tools] section of the configuration,
+ that is used instead."""
+ notify_command = self.config["tools"].get("notify-command")
+
+ # notifypy does not know how to send transient notifications, so we use a custom
+ # notifier on Linux. If transient notifications are not used, then notifications
+ # pile up in the notification center and must be cleared manually.
+ class LinuxNotifier(notifypy.BaseNotifier):
+ def __init__(self, **kwargs):
+ pass
+
+ def send_notification(self, **kwargs):
+ try:
+ import dbus
+ bus = dbus.SessionBus()
+ notify_obj = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
+ method = notify_obj.get_dbus_method("Notify", "org.freedesktop.Notifications")
+ method(
+ kwargs.get("application_name"),
+ 0, # Don't replace previous notification.
+ kwargs.get("notification_icon", ""),
+ kwargs.get("notification_title"),
+ kwargs.get("notification_subtitle"),
+ [], # actions
+ {"transient": True}, # hints
+ -1 # timeout
+ )
+ except ImportError:
+ raise Exception("Optional Python module 'dbus' is not installed.")
+ return True
+
+ if notify_command:
+ if call([notify_command, title, message]) != 0:
+ raise Exception("Could not run '%s'." % notify_command)
+ else:
+ notifier = LinuxNotifier if sys.platform.startswith("linux") else None
+ notification = notifypy.Notify(use_custom_notifier=notifier)
+ notification.title = title
+ notification.message = message
+ notification.icon = path.join(self.get_top_dir(), "resources", "servo_64.png")
+ notification.send(block=False)
+
def angle_root(target, nuget_env):
arch = {