Jump to content
deanishe

Automatically change themes at sunrise and sunset

Recommended Posts

I've written a command-line script that will automatically change your Alfred theme at sunrise and sunset. It's kind of a companion to F.lux and its option to turn on Yosemite's dark theme when it gets dark.
 
It requires the pytz and astral Python libraries.
 
Save the script somewhere and run it in Terminal:
 

python toggle_alfred_theme.py --dark 'My dark theme' --light 'My light theme'

 
The script will change the current theme depending on the time of day and then schedule itself to be called every sunrise and sunset (or when the computer boots/wakes) to change Alfred's theme.

Share this post


Link to post
Share on other sites

Hi Danishe,

 

I installed the script and fixed it to use my Homebrew version of Python instead of the system version. I changed the Launchd calling to use the Homebrew version as well. When ran from the command line, it runs fine. But from Launchd, it says it can not load astral, but it performs the task fine. Is there an environment variable to set inside the Launchd script? I am using LaunchControl to edit the Launchd scripts. Thanks. I really like the ability to switch the theme.

 

Richard

Share this post


Link to post
Share on other sites
Nope. You just need to make sure that astral and pytz are installed in the version of Python you're running the script with. Alternatively, you can install them in the directory alongside the script (e.g. pip install --target . astral — astral will automatically install pytz). This is probably the simplest solution (it also won't break when you upgrade your OS).

 

If it runs fine from a shell but not launchd, it's likely that you've installed the libraries to a directory in your PYTHONPATH. There is no PYTHONPATH in launchd's environment, so it won't look anywhere but the standard install directories.

Share this post


Link to post
Share on other sites

I changed the reassignment of the launchd command to point to my python in /usr/local/bin as well. Everytime it ran, it changed the lauchd back to /usr/bin/python. It seems to be working without errors now. Thanks.

Share this post


Link to post
Share on other sites

Changing the launch agent won't work because the script overwrites it every time it's called (to run itself at the next sunrise/sunset).

 

You should edit the script instead (line 333 and perhaps the hashbang, too) to use your interpreter of choice to make the change permanent.

 

I hardcoded /usr/bin/python because that's what plain "python" always resolves to from launchd's environment, and I wanted it to be explicit.

Edited by deanishe

Share this post


Link to post
Share on other sites

Ah, right. Sorry, I thought you meant you'd changed the launch agent.

 

Glad it's appears to be working now. Let me know if it's doing what it supposed to.

Share this post


Link to post
Share on other sites

Hey Deanishe

 

Got my Python stuff installed, and got this output when I fired up your script.

 

DEBUG     Started with options : {u'help': False, u'light': 'OS X Yosemite', u'quiet': False, u'times': False, u'dark': 'OS X Yosemite Dark', u'timezones': False, u'nothing': False, u'verbose': False}

DEBUG     Sunrise on 2015-02-28 : 06:19:00 UTC

DEBUG     Sunset on 2015-02-28 : 17:09:00 UTC

DEBUG     light : 09:37:40 UTC

DEBUG     Current time : 2015-02-28 09:37:40 UTC = light

INFO      Light theme : OS X Yosemite

INFO      Dark theme  : OS X Yosemite Dark

INFO      Alfred theme set to : OS X Yosemite

INFO      Next change : Theme `OS X Yosemite Dark` at sunset in 7 hours, 32 minutes at 18:09 CET

DEBUG     Forking into background ...

Traceback (most recent call last):

  File "toggle_alfred_theme.py", line 582, in <module>

    sys.exit(main())

  File "toggle_alfred_theme.py", line 564, in main

    daemonise()

  File "toggle_alfred_theme.py", line 172, in daemonise

    os.chdir(os.path.dirname(__file__))

OSError: [Errno 2] No such file or directory: ''

 

I'm on HST but this looks like it's set up for CET. Am I reading the output wrong? Did I miss a step?

Cool stuff, can't wait to get it working.

-roccit

Share this post


Link to post
Share on other sites

Inside the script, you have to set your timezone information along with longtitude, latitude, and elevation. That is for the pyhton routines to more accurately calculate your sunrise and sunset. It is documented in the script (around lines 58-67). You can also set the default theme here instead of on the command line. If you are using a different python than the system python, then you need to change the line that creates the launchd script (line 76). Deanishe is really good at python.

Share this post


Link to post
Share on other sites

Deanishe is really good at python.

Indeed!

I am very much a beginner with command line stuff so thanks for your patience. Looks like all the variables are happy now:

INFO      Next change : Theme `OS X Yosemite Dark` at sunset in 7 hours, 17 minutes at 18:40 HST

Share this post


Link to post
Share on other sites

Inside the script, you have to set your timezone information along with longtitude, latitude, and elevation. That is for the pyhton routines to more accurately calculate your sunrise and sunset. It is documented in the script (around lines 58-67). You can also set the default theme here instead of on the command line. If you are using a different python than the system python, then you need to change the line that creates the launchd script (line 76). Deanishe is really good at python.

 

I updated the script again so you can now set your Python interpreter in a configuration variable at the top of the script.

Share this post


Link to post
Share on other sites

Hey Gents

 

Not smart enough to know this, is the error at the end of this output saying that something didn't go right?

DEBUG     Started with options : {u'help': False, u'light': 'OS X Yosemite', u'quiet': False, u'times': False, u'dark': 'OS X Yosemite Dark', u'timezones': False, u'nothing': False, u'verbose': False}
DEBUG     Sunrise on 2015-03-02 : 16:57:00 UTC
DEBUG     Sunset on 2015-03-03 : 04:41:00 UTC
DEBUG     dark : 04:49:05 UTC
DEBUG     Current time : 2015-03-02 04:49:05 UTC = dark
INFO      Light theme : OS X Yosemite
INFO      Dark theme  : OS X Yosemite Dark
INFO      Alfred theme set to : OS X Yosemite Dark
INFO      Next change : Theme `OS X Yosemite` at sunrise in 12 hours, 8 minutes at 06:57 HST
DEBUG     Forking into background ...
Traceback (most recent call last):
  File "toggle_alfred_theme.py", line 582, in <module>
    sys.exit(main())
  File "toggle_alfred_theme.py", line 564, in main
    daemonise()
  File "toggle_alfred_theme.py", line 172, in daemonise
    os.chdir(os.path.dirname(__file__))
OSError: [Errno 2] No such file or directory: ''

Share this post


Link to post
Share on other sites

Congratulations, you've found a bug!

 

:(

 

It's fixed now, update the script (don't forget to change the location info again) and try it again. Should work.

Share this post


Link to post
Share on other sites

Heh, happy to help :)

 

OK, yeah. Output looks perfect now

INFO      Light theme : OS X Yosemite
INFO      Dark theme  : OS X Yosemite Dark
INFO      Alfred theme set to `OS X Yosemite`
INFO      Next change : Theme `OS X Yosemite Dark` at sunset in 9 hours, 57 minutes at 18:41 HST

Share this post


Link to post
Share on other sites

It shouldn't do that. One of the main selling points of launchd vs cron is that it is supposed to run missed jobs on boot/wake, so the script should get run on wake.

 

I'll be sure to sleep my Mac before dark and wake it up again afterwards to see what it does.

Share this post


Link to post
Share on other sites

[ETA astral and pytz versions]

 

I gotta be missing something. More questions from me, sorry! 

 

I sat and watched this morning but the theme never changed from dark to light. I do see there is a plist file in the ~/user/library/launchagents/ and it does seem to know when the sunrise is/was but the them never changed.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>Toggle Alfred theme at sunrise and sunset</string>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/bin/python</string>
		<string>/Users/roccoapril/Documents/_home/toggle_alfred_theme.py</string>
		<string>--dark</string>
		<string>OS X Yosemite Dark</string>
		<string>--light</string>
		<string>OS X Yosemite</string>
	</array>
	<key>StartCalendarInterval</key>
	<dict>
		<key>Day</key>
		<integer>3</integer>
		<key>Hour</key>
		<integer>6</integer>
		<key>Minute</key>
		<integer>57</integer>
		<key>Month</key>
		<integer>3</integer>
	</dict>
</dict>
</plist>

Do I have something set up wrong? If I rerun the script right now it will change the theme immediately. I ran it last night about an hour after sunset and it changed it to dark. 

 

Just ran it again, and ...

INFO      Light theme : OS X Yosemite
INFO      Dark theme  : OS X Yosemite Dark
INFO      Alfred theme set to `OS X Yosemite`
INFO      Next change : Theme `OS X Yosemite Dark` at sunset in 10 hours, 55 minutes at 18:42 HST

Looks right. It's 7:47 and sunset should be around 18:30.

 

And it looks like the plist file was edited correctly

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>Toggle Alfred theme at sunrise and sunset</string>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/bin/python</string>
		<string>/Users/roccoapril/Documents/_home/toggle_alfred_theme.py</string>
		<string>--dark</string>
		<string>OS X Yosemite Dark</string>
		<string>--light</string>
		<string>OS X Yosemite</string>
	</array>
	<key>StartCalendarInterval</key>
	<dict>
		<key>Day</key>
		<integer>3</integer>
		<key>Hour</key>
		<integer>18</integer>
		<key>Minute</key>
		<integer>43</integer>
		<key>Month</key>
		<integer>3</integer>
	</dict>
</dict>
</plist>

I gotta be missing something. Astral version

>>> astral.__version__

'0.8.1'

Updated pytz to 2014.10 (from 2013.7). Can't imagine that was a problem, but IDK.

>>> pytz.__version__

'2014.10'

 

-newbie out!

Edited by roccitman

Share this post


Link to post
Share on other sites

It's hard to say what the problem is because it's working just fine for me and I can't replicate the problem. I mean, I did have that problem, but I fixed that bug…
 
A couple of things we can try:
 
1. Make sure you're using the latest version of the script. I tinker with it quite a lot, and Sublime Text appears to upload a new version every time I hit save (634 revisions so far).
 
2. Ensure you're running the script with the same Python as the Launch Agent is (/usr/bin/python), by running /usr/bin/python toggle_alfred_theme.py in Terminal and checking if the script still works.
 
3. Assuming you have the latest version of the script, could you try setting DEBUG to True around line 133? (It's currently True in the Gist, but who knows for how long…)
 
That'll turn on the log file and STDOUT & STDERR capture for the Launch Agent, and also set the script to run when the Launch Agent is loaded. Once DEBUG is True, load and unload the Launch Agent a couple of times, then open Console.app and check the log file and the STDOUT and STDERR capture files.
 
You can load/unload the Launch Agent with: 

# load
launchctl load ~/Library/LaunchAgents/net.deanishe.alfred-toggle-theme.plist
 
# unload
launchctl unload ~/Library/LaunchAgents/net.deanishe.alfred-toggle-theme.plist

  
A very handy tool for working with Launch Agents is LaunchControl, without which I probably wouldn't have even tried to write this script.
 
These are in ~/Library/Logs (they'll be shown in Console.app) and their names start with net.deanishe.alfred-toggle-theme.
 
It might be that launchd can't run the script because it can't see astral or something. In particular, look at the STDERR capture file, net.deanishe.alfred-toggle-theme.launch-agent.stderr.log. It will contain the output you'd normally see in the Terminal, so any errors will be in there.

 

I'm thinking I'm going to have to turn this into a proper program or workflow. Can't be asking people to update it every day when they have to edit the script each time…

Share this post


Link to post
Share on other sites

Thanks for taking the time! Learning a lot here.

 

1) Grabbed the latest just now. 635 :)

 

2) Still works, but may have found out what's wrong. I had to run it twice for it to catch the themes I was asking for:

before...

INFO      Light theme : Light
INFO      Dark theme  : Dark

after...

INFO      Light theme : OS X Yosemite
INFO      Dark theme  : OS X Yosemite Dark

Can't explain that one, just hit the up arrow and did it again. Shrug.

 

3) Perhaps some more goodies here:

DEBUG     Started with options : {u'help': False, u'light': 'OS X Yosemite', u'quiet': False, u'times': False, u'dark': 'OS X Yosemite Dark', u'timezones': False, u'nothing': False, u'verbose': False}
DEBUG     Deleted stale PID file : /tmp/net.deanishe.alfred-toggle-theme.pid
DEBUG     light at 2015-03-03 21:00:34 UTC
INFO      Light theme : OS X Yosemite
INFO      Dark theme  : OS X Yosemite Dark
INFO      Alfred theme set to `OS X Yosemite`
INFO      Next change : Theme `OS X Yosemite Dark` at sunset in 7 hours, 41 minutes at 18:42 HST
DEBUG     Forking into background ...

As always, thanks for your patience here! Looks like it was simple thing, we'll see in 7 hours 40 minutes...

Share this post


Link to post
Share on other sites

Darn, it didn't. The themes got reset back to 'light' and 'dark' again. Not sure what's going on. Machine was sleeping during the change so might be the same thing that Richard was seeing. We'll try again in the morning, heh.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×