Welcome to rumps¶
rumps is...
Ridiculously Uncomplicated Mac os x Python Statusbar apps!
rumps exposes Objective-C classes as Python classes and functions which greatly simplifies the process of creating a statusbar application.
Say you have a Python program and want to create a relatively simple interface for end user interaction on a Mac. There are a number of GUI tools available to Python programmers (PyQt, Tkinter, PyGTK, WxPython, etc.) but most are overkill if you just want to expose a few configuration options or an execution switch.
If all you want is a statusbar app, rumps makes it easy.
GitHub project: https://github.com/jaredks/rumps
Contents:
Examples¶
Sometimes the best way to learn something is by example. Form your own application based on some of these samples.
Simple subclass structure¶
Just a straightforward application,
import rumps
class AwesomeStatusBarApp(rumps.App):
def __init__(self):
super(AwesomeStatusBarApp, self).__init__("Awesome App")
self.menu = ["Preferences", "Silly button", "Say hi"]
@rumps.clicked("Preferences")
def prefs(self, _):
rumps.alert("jk! no preferences available!")
@rumps.clicked("Silly button")
def onoff(self, sender):
sender.state = not sender.state
@rumps.clicked("Say hi")
def sayhi(self, _):
rumps.notification("Awesome title", "amazing subtitle", "hi!!1")
if __name__ == "__main__":
AwesomeStatusBarApp().run()
Decorating any functions¶
The following code demonstrates how you can decorate functions with rumps.clicked()
whether or not they are inside a subclass of rumps.App
. The parameter sender
, the rumps.MenuItem
object, is correctly passed to both functions even though button
needs an instance of SomeApp
as its self
parameter.
Usually functions registered as callbacks should accept one and only one argument but an App subclass is viewed as a special case as its use can provide a simple and pythonic way to implement the logic behind an application.
from rumps import *
@clicked('Testing')
def tester(sender):
sender.state = not sender.state
class SomeApp(rumps.App):
def __init__(self):
super(SomeApp, self).__init__(type(self).__name__, menu=['On', 'Testing'])
rumps.debug_mode(True)
@clicked('On')
def button(self, sender):
sender.title = 'Off' if sender.title == 'On' else 'On'
Window("I can't think of a good example app...").run()
if __name__ == "__main__":
SomeApp().run()
New features in 0.2.0¶
Menu items can be disabled (greyed out) by passing None
to rumps.MenuItem.set_callback()
. rumps.alert()
no longer requires title (will use a default localized string) and allows for custom cancel button text. The new parameter quit_button for rumps.App
allows for custom quit button text or removal of the quit button entirely by passing None
.
Warning
By setting rumps.App.quit_button
to None
you must include another way to quit the application by somehow calling rumps.quit_application()
otherwise you will have to force quit.
import rumps
rumps.debug_mode(True)
@rumps.clicked('Print Something')
def print_something(_):
rumps.alert(message='something', ok='YES!', cancel='NO!')
@rumps.clicked('On/Off Test')
def on_off_test(_):
print_button = app.menu['Print Something']
if print_button.callback is None:
print_button.set_callback(print_something)
else:
print_button.set_callback(None)
@rumps.clicked('Clean Quit')
def clean_up_before_quit(_):
print 'execute clean up code'
rumps.quit_application()
app = rumps.App('Hallo Thar', menu=['Print Something', 'On/Off Test', 'Clean Quit'], quit_button=None)
app.run()
Creating Standalone Applications¶
If you want to create your own bundled .app you need to download py2app: https://pythonhosted.org/py2app/
For creating standalone apps, just make sure to include rumps
in the packages
list. Most simple statusbar-based
apps are just “background” apps (no icon in the dock; inability to tab to the application) so it is likely that you
would want to set 'LSUIElement'
to True
. A basic setup.py
would look like,
from setuptools import setup
APP = ['example_class.py']
DATA_FILES = []
OPTIONS = {
'argv_emulation': True,
'plist': {
'LSUIElement': True,
},
'packages': ['rumps'],
}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
With this you can then create a standalone,
python setup.py py2app
Debugging Your Application¶
When writing your application you will want to turn on debugging mode.
import rumps
rumps.debug_mode(True)
If you are running your program from the interpreter, you should see the informational messages.
python {your app name}.py
If testing the .app generated using py2app, to be able to see these messages you must not,
open {your app name}.app
but instead run the executable. While within the directory containing the .app,
./{your app name}.app/Contents/MacOS/{your app name}
And, by default, your .app will be in dist
folder after running python setup.py py2app
. So of course that would then be,
./dist/{your app name}.app/Contents/MacOS/{your app name}
rumps Classes¶
App¶
-
class
rumps.
App
(name, title=None, icon=None, template=None, menu=None, quit_button='Quit')¶ Represents the statusbar application.
Provides a simple and pythonic interface for all those long and ugly PyObjC calls.
rumps.App
may be subclassed so that the application logic can be encapsulated within a class. Alternatively, an App can be instantiated and the various callback functions can exist at module level.Changed in version 0.2.0: name parameter must be a string and title must be either a string or
None
. quit_button parameter added.Parameters: - name – the name of the application.
- title – text that will be displayed for the application in the statusbar.
- icon – file path to the icon that will be displayed for the application in the statusbar.
- menu – an iterable of Python objects or pairs of objects that will be converted into the main menu for the
application. Parsing is implemented by calling
rumps.MenuItem.update()
. - quit_button – the quit application menu item within the main menu. If
None
, the default quit button will not be added.
-
icon
¶ A path to an image representing the icon that will be displayed for the application in the statusbar. Can be
None
in which case the text fromtitle
will be used.Changed in version 0.2.0: If the icon is set to an image then changed to
None
, it will correctly be removed.
Represents the main menu of the statusbar application. Setting menu works by calling
rumps.MenuItem.update()
.
-
name
¶ The name of the application. Determines the application support folder name. Will also serve as the title text of the application if
title
is not set.
-
open
(*args)¶ Open a file within the application support folder for this application.
app = App('Cool App') with app.open('data.json') as f: pass
Is a shortcut for,
app = App('Cool App') filename = os.path.join(application_support(app.name), 'data.json') with open(filename) as f: pass
The quit application menu item within the main menu. This is a special
rumps.MenuItem
object that will both replace any function callback withrumps.quit_application()
and add itself to the end of the main menu whenrumps.App.run()
is called. If set toNone
, the default quit button will not be added.Warning
If set to
None
, some other menu item should callrumps.quit_application()
so that the application can exit gracefully.New in version 0.2.0.
-
run
(**options)¶ Performs various setup tasks including creating the underlying Objective-C application, starting the timers, and registering callback functions for click events. Then starts the application run loop.
Changed in version 0.2.1: Accepts debug keyword argument.
Parameters: debug – determines if application should log information useful for debugging. Same effect as calling rumps.debug_mode()
.
-
template
¶ Template mode for an icon. If set to
None
, the current icon (if any) is displayed as a color icon. If set toTrue
, template mode is enabled and the icon will be displayed correctly in dark menu bar mode.
-
title
¶ The text that will be displayed for the application in the statusbar. Can be
None
in which case the icon will be used or, if there is no icon set the application text will fallback on the applicationname
.Changed in version 0.2.0: If the title is set then changed to
None
, it will correctly be removed. Must be either a string orNone
.
Window¶
-
class
rumps.
Window
(message='', title='', default_text='', ok=None, cancel=None, dimensions=(320, 160))¶ Generate a window to consume user input in the form of both text and button clicked.
Changed in version 0.2.0: Providing a cancel string will set the button text rather than only using text “Cancel”. message is no longer a required parameter.
Parameters: - message – the text positioned below the title in smaller font. If not a string, will use the string representation of the object.
- title – the text positioned at the top of the window in larger font. If not a string, will use the string representation of the object.
- default_text – the text within the editable textbox. If not a string, will use the string representation of the object.
- ok – the text for the “ok” button. Must be either a string or
None
. IfNone
, a default localized button title will be used. - cancel – the text for the “cancel” button. If a string, the button will have that text. If cancel
evaluates to
True
, will create a button with text “Cancel”. Otherwise, this button will not be created. - dimensions – the size of the editable textbox. Must be sequence with a length of 2.
Create a new button.
Changed in version 0.2.0: The name parameter is required to be a string.
Parameters: name – the text for a new button. Must be a string.
Create multiple new buttons.
Changed in version 0.2.0: Since each element is passed to
rumps.Window.add_button()
, they must be strings.
-
default_text
¶ The text within the editable textbox. An example would be
“Type your message here.”If not a string, will use the string representation of the object.
-
icon
¶ The path to an image displayed for this window. If set to
None
, will default to the icon for the application usingrumps.App.icon
.Changed in version 0.2.0: If the icon is set to an image then changed to
None
, it will correctly be changed to the application icon.
-
message
¶ The text positioned below the
title
in smaller font. If not a string, will use the string representation of the object.
-
run
()¶ Launch the window.
rumps.Window
instances can be reused to retrieve user input as many times as needed.Returns: a rumps.rumps.Response
object that contains the text and the button clicked as an integer.
-
title
¶ The text positioned at the top of the window in larger font. If not a string, will use the string representation of the object.
Response¶
-
class
rumps.rumps.
Response
(clicked, text)¶ Holds information from user interaction with a
rumps.Window
after it has been closed.-
clicked
¶ Return a number representing the button pressed by the user.
The “ok” button will return
1
and the “cancel” button will return0
. This makes it convenient to write a conditional like,if response.clicked: do_thing_for_ok_pressed() else: do_thing_for_cancel_pressed()
Where response is an instance of
rumps.rumps.Response
.Additional buttons added using methods
rumps.Window.add_button()
andrumps.Window.add_buttons()
will return2
,3
, ... in the order they were added.
-
text
¶ Return the text collected from the user.
-
Timer¶
-
class
rumps.
Timer
(callback, interval)¶ Python abstraction of an Objective-C event timer in a new thread for application. Controls the callback function, interval, and starting/stopping the run loop.
Changed in version 0.2.0: Method __call__ removed.
Parameters: - callback – Function that should be called every interval seconds. It will be passed this
rumps.Timer
object as its only parameter. - interval – The time in seconds to wait before calling the callback function.
-
callback
¶ The current function specified as the callback.
-
interval
¶ The time in seconds to wait before calling the
callback
function.
-
is_alive
()¶ Whether the timer thread loop is currently running.
-
set_callback
(callback)¶ Set the function that should be called every
interval
seconds. It will be passed thisrumps.Timer
object as its only parameter.
-
start
()¶ Start the timer thread loop.
-
stop
()¶ Stop the timer thread loop.
- callback – Function that should be called every interval seconds. It will be passed this
rumps Functions¶
notifications¶
-
rumps.
notifications
(f)¶ Decorator for registering a function to serve as a “notification center” for the application. This function will receive the data associated with an incoming macOS notification sent using
rumps.notification()
. This occurs whenever the user clicks on a notification for this application in the macOS Notification Center.@rumps.notifications def notification_center(info): if 'unix' in info: print 'i know this'
clicked¶
-
rumps.
clicked
(*args, **options)¶ Decorator for registering a function as a callback for a click action on a
rumps.MenuItem
within the application. The passed args must specify an existing path in the main menu. Therumps.MenuItem
instance at the end of that path will have itsrumps.MenuItem.set_callback()
method called, passing in the decorated function.Changed in version 0.2.1: Accepts key keyword argument.
@rumps.clicked('Animal', 'Dog', 'Corgi') def corgi_button(sender): import subprocess subprocess.call(['say', '"corgis are the cutest"'])
Parameters: - args – a series of strings representing the path to a
rumps.MenuItem
in the main menu of the application. - key – a string representing the key shortcut as an alternative means of clicking the menu item.
- args – a series of strings representing the path to a
timer¶
-
rumps.
timer
(interval)¶ Decorator for registering a function as a callback in a new thread. The function will be repeatedly called every interval seconds. This decorator accomplishes the same thing as creating a
rumps.Timer
object by using the decorated function and interval as parameters and starting it on application launch.@rumps.timer(2) def repeating_function(sender): print 'hi'
Parameters: interval – a number representing the time in seconds before the decorated function should be called.
timers¶
-
rumps.
timers
()¶ Return a list of all
rumps.Timer
objects. These can be active or inactive.
application_support¶
-
rumps.
application_support
(name)¶ Return the application support folder path for the given name, creating it if it doesn’t exist.
notification¶
-
rumps.
notification
(title, subtitle, message, data=None, sound=True)¶ Send a notification to Notification Center (OS X 10.8+). If running on a version of macOS that does not support notifications, a
RuntimeError
will be raised. Apple says,“The userInfo content must be of reasonable serialized size (less than 1k) or an exception will be thrown.”So don’t do that!
Parameters: - title – text in a larger font.
- subtitle – text in a smaller font below the title.
- message – text representing the body of the notification below the subtitle.
- data – will be passed to the application’s “notification center” (see
rumps.notifications()
) when this notification is clicked. - sound – whether the notification should make a noise when it arrives.
alert¶
-
rumps.
alert
(title=None, message='', ok=None, cancel=None)¶ Generate a simple alert window.
Changed in version 0.2.0: Providing a cancel string will set the button text rather than only using text “Cancel”. title is no longer a required parameter.
Parameters: - title – the text positioned at the top of the window in larger font. If
None
, a default localized title is used. If notNone
or a string, will use the string representation of the object. - message – the text positioned below the title in smaller font. If not a string, will use the string representation of the object.
- ok – the text for the “ok” button. Must be either a string or
None
. IfNone
, a default localized button title will be used. - cancel – the text for the “cancel” button. If a string, the button will have that text. If cancel
evaluates to
True
, will create a button with text “Cancel”. Otherwise, this button will not be created.
Returns: a number representing the button pressed. The “ok” button is
1
and “cancel” is0
.- title – the text positioned at the top of the window in larger font. If