Tutorials & Tips
Posts explaining how to do something, fix something, etc. This is where you’ll find my useful posts.
Unfortunately, given how software evolves over time, I should probably say “once useful”. If you’re digging through the archives, check the dates.
Write a file as root from a non-root vim.
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
Problem
I often edit config files in vim, try to save them, and then realize that I ran vim as a normal user and the config file is in /etc. In the past I would close vim and redo all of my changes as root (using sudo). This is a real pain especially if I had made a lot of changes.
Solution
Add the following to your ~/.vimrc:
cmap w!! w !sudo tee % >/dev/null<CR>:e!<CR><CR>
A while ago I came across this post that describes how to save a file as root from a non-root vim by adding cmap w!! w !sudo tee % >/dev/null
to my .vimrc
.
The problem is that, after running this command, vim will notice that the file has changed on disk and ask the user if he or she wants to reload it. After a while this got annoying, therefore the multiple CRs (enters) and the :e! (reloads the file).
Navigate text with vi(m) keys on linux
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
Intro
Lifehacker recently posted a AutoHotkey script for windows that allows text navigation using letters instead of the arrow keys. In response to @wersdaluv’s post, I wrote a very simple script that allows users to navigate text using the standard vim keys (hjkl) when the caps-lock key is toggled. Feel free and add to my very basic script.
Steps
I stored the script referenced in this post in a paste-bin and now it’s gone. Live and learn…
- Download my script (via copy and paste) from
here. Lost (email if found). - Save the script somewhere where you will not delete it and mark it as executable (
chmod u+x /path/to/script.sh
) - Add the script to the startup programs with the argument
init
(i.e./path/to/script.sh init
). If you don’t know how to add startup programs in your Desktop Environment, Google it. - Assign F13 (the now remapped capslock key), as a hotkey in your window manager. Set the command to
'/path/to/script.sh toggle'
. Again, if you don’t know how to add a hotkey, Google it. - Now either log out and then in or run ’
/path/to/script.sh init'
in order to remap the capslock key. - Pressing the capslock key should now toggle navigation mode.
Bash completion with aptitude aliases
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
Problem
- If I used my alias for installing an application (
inst application
), I would have to know the full application name because I would not have bash completion. This was very annoying when installing libraries because they often have weird version strings tacked on to their ends. - If I used the full command (
sudo aptitude install application
), I would have bash completion and would therefore not have to know the whole application name. I could simply typelibxul
and getlibxul0d
.
On one hand, I would type a short command plus a complected application name, on the other I would type a long command and a simple application name. I wanted to be able to type a short command with a simple application name.
Solution
I wrote my own bash completion rules. They are based on the default aptitude bash completion rules but customized for aliases.
# Install Completion
#
_aptitude_all()
{
local cur dashoptions
COMPREPLY=()
cur=`_get_cword`
dashoptions='-S -u -i -h --help --version -s --simulate -d \
--download-only -P --prompt -y --assume-yes -F \
--display-format -O --sort -w --width -f -r -g \
--with-recommends --with-suggests -R -G \
--without-recommends --without-suggests -t \
--target-release -V --show-versions -D --show-deps\
-Z -v --verbose --purge-unused'
if [[ "$cur" == -* ]]; then
COMPREPLY=( $( compgen -W "$dashoptions" -- $cur ) )
else
COMPREPLY=( $( apt-cache pkgnames $cur 2> /dev/null ) )
fi
return 0
}
_aptitude_installed()
{
local cur dashoptions
COMPREPLY=()
cur=`_get_cword`
dashoptions='-S -u -i -h --help --version -s --simulate -d \
--download-only -P --prompt -y --assume-yes -F \
--display-format -O --sort -w --width -f -r -g \
--with-recommends --with-suggests -R -G \
--without-recommends --without-suggests -t \
--target-release -V --show-versions -D --show-deps\
-Z -v --verbose --purge-unused'
if [[ "$cur" == -* ]]; then
COMPREPLY=( $( compgen -W "$dashoptions" -- $cur ) )
else
COMPREPLY=( $( _comp_dpkg_installed_packages $cur ) )
fi
return 0
}
complete -F _aptitude_all $default inst
complete -F _aptitude_all $default upgrade
complete -F _aptitude_all $default apt-info
complete -F _aptitude_all $default apt-changes
complete -F _aptitude_all $default apt-download
complete -F _aptitude_installed $default uninst
complete -F _aptitude_installed $default reinst
complete -F _aptitude_installed $default purge
Just copy it into a file such as ~/.bash_completion
and source the file in your ~/.bashrc by adding “. ~/.bash_completion
”.
Change/Add/Remove the aliases at the end of the file. The lines that start with complete -F _aptitude_all
complete any available or installed package and lines that start with complete -F _aptitude_installed
complete only installed packages.
inst, upgrade, apt-info, apt-changes…. are my aliases. You must use YOUR ALIASES for this to work. To add aliases, read this.
How to invite someone to Ubuntu One
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
For anyone with an Ubuntu One account, the following are instructions for sending invites:
- Go to My Files in the web interface.
- Create a new folder (to be shared) with the person that you will be inviting
- Go to the sharing tab (on the right).
- Share the folder with the person that you want to invite (The trick is that someone does not have to have an Ubuntu One account to accept a share).
For anyone looking for an invite, just ask @bugabundo at Identi.ca.
How to record one's linux computer with pulseaudio
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
I posted a simple tip to an Identi.ca user (mxc) explaining how to record a skype conversation and felt that others might find the information useful. Here is an elaborated explanation of how to record the sound from a linux computer.
- Install pavucontrol and the gnome-sound-recorder (in the gnome-media package).
- Open the gnome-sound-recorder and start recording
- Open the pulseaudio volume control and switch to the recording tab
- Click on the down arrow of the “gnome-sound-recorder” Record Stream, Select “Move Stream” and move the stream to the “Monitor” stream for your sound card.
This should record all sound from your computer if you are using pulseaudio. I have not tested this with skype but it should work.
Change the notification icon in Mumbles without creating a plugin.
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
I have noticed that several people have asked how to change the notification icon on mumbles without creating a new plugin.This is actually very simple: use the generic DBus plugin with dbus-send. I believe that this tutorial requires the SVN version but I may be mistaken. First add a new section to your DBus plugin configuration file. If you do not have this configuration file, copy the sample one from the mumbles source tarball (found on the project’s homepage). The file is called dbus.conf.sample
. Copy this file to ~/.mumbles/dbus.conf
. The new section is as follows:
[program-or-script-name]
enabled = true
interface = org.program-or-script-name.DBus
path = /org/program-or-script-name/DBus
signal = your-signal
icon = your-icon.png
Put your-icon.png in the ~/.mumbles/plugins/icons/
folder.your-signal is your name for the alert. None of these variables are important but they must be consistent.
After doing the previous and restarting mumbles, run this command:
dbus-send /org/program-or-script-name/DBus org.`*program-or-script-name*`.DBus.your-signal string:"Title" string:"Message"
Make sure that you replace all necessary variables. This will display a mumbles popup with your custom icon, title, and message. You can also specify a click action using launch = action
.
Mumbles with gmail
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
I have been playing around with mumbles lately and have written a gmail plugin for anyone interested. Mumbles is a notification system that works very much like growl for the mac. The latest SVN version can even replace the gnome notification daemon (but not very well). While still in its infancy, this project shows a lot of promise. I based the plugin on the evolution tutorial on project’s homepage. I based the script on this script (with many modifications). When you click on the notification popup, evolution will launch (you can edit the source to change the program). The script requires python-feedparser.
Plugin, Source, and Script package: gmail-plugin_mumbles.tar.gz
Installing the precompiled plugin:
Do step 2 from the next section. Now copy the plugin to
~/.mumbles/plugins/
.
Installing the plugin from source (adapted from dot_j’s tutorial (gone)):
1. Download the source
Download the package and extract. Then open a terminal window inside the plugin-source folder.
2. Create the directory structure and choose an icon
Run the following command:
mkdir -p ~/.mumbles/plugins/icons
Then either run this to use the default evolution icon…
cp /usr/share/icons/hicolor/22×22/apps/evolution.png ~/.mumbles/plugins/icons
Or just copy your desired icon into the plugins/icons folder and rename it to
evolution.png
. This is unnecessary if you already have the evolution plugin.Build and install the plugin
cd ~/gmail_plugin python setup.py bdist_egg
This will use our
setup.py
file to create our plugin. After it runs, you should see a file namedGmailMumbles-0.1-py2.5.egg
in the dist directory that was created by the build process. Here the-py2.5
part of the filename refers to what version of python you are using (it may vary, but if you are able to start mumbles, should not matter).The .egg file is our plugin, so the only thing left to do is copy that to the mumbles plugin directory.
cp dist/GmailMumbles-0.1-py2.5.egg ~/.mumbles/plugins
Installing the script:
Find the script in the package and edit the username and password variables. Run this script with
python /path/to/gmail.py
(replace /path/to with the path to the script). By default, this script will check for new email every 2 minutes and alert the user of new mail.
BTW: This script does not safely store the username and password. I may, in the distant future, make this script work with gnome-keyring but this is not likely. I hope that mumbles will soon get better notification-daemon support so that I can go back to using mail-notification.
Running the "Ubunu System Panel" on a 64 bit machine.
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
After installing the 64 bit version of Ubuntu on my Dell Inspiron 1420n I found that the USP (Ubuntu System Panel) keybindings do not work. This is because the /usr/lib/python2.4/site-packages/usp/plugins/_keybinder.so
is compiled for a 32 bit system. After a little searching I found out that Glipper includes a _keybinder.so
file. After replacing USP’s _keybinder.so with Glipper’s version, the keybindings worked fine.
- Download glipper
aptitude download glipper
. - Extract the glipper deb with
dpkg-deb -x glipper_1.0-1ubuntu1_amd64.deb glipper
(change glipper_1.0-1ubuntu1_amd64.deb to the name of your file). - Copy in the new _keybinder.so with
sudo cp ./glipper/usr/lib/python-support/glipper/python2.5/glipper/keybinder/_keybinder.so /usr/lib/python2.4/site-packages/usp/plugins/_keybinder.so
. - Restart USP with
killall gnome-panel
and your USP shortcut keys should now work.
Edit: This is no longer necessary.
Conky: The simple system monitor
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
Conky is a simple system monitor that uses very little ram.
I have 2 conky-rc files: a system monitor and a weather display.
I wrote my system monitor from scratch and my weather display is based on this tutorial.
System Monitor conkyrc
# System Monitor
# Stebalien.com
# set to yes if you want Conky to be forked in the background
background no
# Use Xft?
use_xft yes
# Xft font when Xft is enabled
xftfont Bitstream Vera Sans Mono:size=8
# Text alpha when using Xft
xftalpha 0.8
# Update interval in seconds
update_interval 5.0
# This is the number of times Conky will update before quitting.
# Set to zero to run forever.
total_run_times 0
# Create own window instead of using desktop (required in nautilus)
own_window yes
# If own_window is yes, you may use type normal, desktop or override
own_window_type override
# Use pseudo transparency with own_window?
own_window_transparent yes
# If own_window_transparent is set to no, you can set the background colour here
own_window_colour black
# If own_window is yes, these window manager hints may be used
#own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager
# Use double buffering (reduces flicker, may not work for everyone)
double_buffer yes
# Minimum size of text area
minimum_size 280 5
# Draw shades?
draw_shades yes
# Draw outlines?
draw_outline no
# Draw borders around text
draw_borders no
# Draw borders around graphs
draw_graph_borders yes
# Stippled borders?
stippled_borders 8
# border margins
border_margin 4
# border width
border_width 1
# Default colors and also border colors
default_color white
default_shade_color black
default_outline_color black
# Text alignment, other possible values are commented
#alignment top_left
#alignment top_right
alignment bottom_left
#alignment bottom_right
#alignment none
# Gap between borders of screen and text
# same thing as passing -x at command line
gap_x 12
gap_y 12
# Subtract file system buffers from used memory?
no_buffers yes
# set to yes if you want all text to be in uppercase
uppercase no
# number of cpu samples to average
# set to 1 to disable averaging
cpu_avg_samples 2
# number of net samples to average
# set to 1 to disable averaging
net_avg_samples 2
# Force UTF8? note that UTF8 support required XFT
override_utf8_locale no
# Add spaces to keep things from moving about? This only affects certain objects.
use_spacer no
color1 SteelBlue4
TEXT
${color1}${tcp_portmon 50005 50005 lservice 0} ${color green}${tcp_portmon 50005 50005 rip 0}
${color1}Drives: ${color lightgrey}Lin:${color}${fs_used_perc /}% | ${color lightgrey}Home:${color}${fs_used_perc /home}% | ${color lightgrey}Ext:${color}${fs_used_perc /media/ext}%
${color1}Network: ${color lightgrey}Down:$color${downspeed ath0} k/s | ${color lightgrey}Up:$color${upspeed ath0} k/s
${color1}System: ${color lightgrey}CPU:$color$cpu% | ${color lightgrey}RAM:$color$memperc% | ${color lightgrey}SWAP:$color$swapperc%
Replace ath0
with the name of your network interface.
Weather Display conkyrc
# Weather display
# Stebalien.com
# set to yes if you want Conky to be forked in the background
background no
# Use Xft?
use_xft yes
# Xft font when Xft is enabled
#xftfont Bitstream Vera Sans Mono:size=8
#xftfont Terminus:size=8
xftfont Liberation Sans:size=8
# Text alpha when using Xft
xftalpha 0.8
# Print everything to console?
# out_to_console no
# mail spool
#mail_spool $MAIL
# Update interval in seconds
update_interval 5.0
# This is the number of times Conky will update before quitting.
# Set to zero to run forever.
total_run_times 0
# Create own window instead of using desktop (required in nautilus)
own_window no
# Use double buffering (reduces flicker, may not work for everyone)
double_buffer yes
# Minimum size of text area
minimum_size 100 5
maximum_width 600
# Draw shades?
draw_shades no
# Draw outlines?
draw_outline no
# Draw borders around text
draw_borders no
draw_graph_borders yes
# Stippled borders?
stippled_borders 8
# border margins
border_margin 4
# border width
border_width 1
# Default colors and also border colors
default_color white
default_shade_color black
default_outline_color white
# own window options
own_window yes
own_window_transparent yes
own_window_type override
own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager
# Text alignment, other possible values are commented
#alignment top_left
#alignment top_right
#alignment bottom_left
alignment bottom_right
# Gap between borders of screen and text
# same thing as passing -x at command line
gap_x 10
gap_y -10
# Subtract file system buffers from used memory?
no_buffers yes
# set to yes if you want all text to be in uppercase
uppercase no
# number of cpu samples to average
# set to 1 to disable averaging
cpu_avg_samples 2
# number of net samples to average
# set to 1 to disable averaging
net_avg_samples 2
# Force UTF8? note that UTF8 support required XFT
override_utf8_locale yes
# Add spaces to keep things from moving about? This only affects certain objects.
use_spacer yes
# colors
color1 white
# light blue
color2 6892C6
# orange
color3 E77320
# green
color4 78BF39
# red
color5 CC0000
# Steel blue
color6 SteelBlue4
# variable is given either in format $variable or in ${variable}. Latter
# allows characters right after the variable and must be used in network
# stuff because of an argument
# stuff after 'TEXT' will be formatted on screen
TEXT
$color6${hr 1}
${voffset -2}Now:
${voffset -6}${hr 1}
${voffset -8}$color${font weather:size=64}${execi 3600 python ~/.conky/conkyForecast.py --location=USCA0638 --datatype=WF}${font}
${voffset -66}Conditions: ${execi 3600 python ~/.conky/conkyForecast.py --location=USCA0638 --datatype=CC}
Temp: ${execi 3600 python ~/.conky/conkyForecast.py -i --location=USCA0638 --datatype=HT}
Wind: ${execi 3600 python ~/.conky/conkyForecast.py -i --location=USCA0638 --datatype=WS} ${execi 3600 python ~/.conky/conkyForecast.py --location=USCA0638 --datatype=WD}
Humidity: ${execi 3600 python ~/.conky/conkyForecast.py --location=USCA0638 --datatype=HM}
${voffset -4}$color6${hr 1}
${voffset -2}${execi 3600 python ~/.conky/conkyForecast.py --location=USCA0638 --datatype=DW --shortweekday --startday=0 --spaces=9 --endday=4}
${voffset -6}${hr 1}
$color${voffset 4}${font weather:size=24}${execi 3600 python ~/.conky/conkyForecast.py --location=USCA0638 --datatype=WF --startday=0 --endday=4 --spaces=1}${font}
${font Liberation Sans:size=6}${voffset -36}${execi 3600 python ~/.conky/conkyForecast.py -i --location=USCA0638 --datatype=HT --startday=0 --endday=4 --spaces=18}
${execi 3600 python ~/.conky/conkyForecast.py -i --location=USCA0638 --datatype=LT --startday=0 --endday=4 --spaces=17}
${execi 3600 python ~/.conky/conkyForecast.py --location=USCA0638 --datatype=PC --startday=0 --endday=4 --spaces=19}
Replace ~/.conky/conkyForecast.py
with the location of your weather
script. Replace USCA0638
with your city code (see the tutorial link at
the beginning of this post).
Conky weather script
#!/usr/bin/python
# -*- coding: utf-8 -*-
###############################################################################
# conkyForecast.py is a (not so) simple (anymore) python script to gather
# details of the current weather for use in conky.
#
# Author: Kaivalagi
# Created: 13/04/2008
# Modifications:
# 14/04/2008 Allow day ranges for forecast data
# 14/04/2008 Check for connectivity to xoap service
# 18/04/2008 Allow the setting of spaces for ranged output
# 18/04/2008 Allow Night and Day forecast output
# 18/04/2008 Support locale for condition code text "CC" option, awaiting spanish language translation
# 18/04/2008 Use pickling for class data rather than opening xml, this bypasses the need to interrogate cached data
# 19/04/2008 Added spanish condition text - Thanks Bruce M
# 19/04/2008 Added isnumeric check on all numeric output with units suffix
# 19/04/2008 Altered pickle file naming to include location code
# 19/04/2008 Added spanish week days conversion via locale
# 20/04/2008 Added decent command argument parser
# 20/04/2008 Added --shortweekday option, if given the day of week data type is shortened to 3 characters
# 21/04/2008 Fixed locale options for forecast output
# 21/04/2008 Added --template option to allow custom output using a single exec call :)
# 21/04/2008 Added --hideunits option to remove, for example, mph and C from output
# 23/04/2008 Removed --imperial option from template, this MUST be set as a standard option on the script call and not used in the template file.
# 23/04/2008 Readded --imperial option to template, enabling metric or imperial values per datatype. Note when using templates command line option will not work.
# 23/04/2008 Added output notifying user if the location given is bad
# 24/04/2008 Added handling for no connectivity, will revert to cached data now (erroring if no cache exists). Tests by trying to open xoap.weather.com
# 24/04/2008 Fixed Celsius to fahrenheit conversion
# 06/05/2008 Updated url used after webservice was updated
# 09/05/2008 Consolidated current condition and forecast data fetch into one call
# 09/05/2008 Added Sunrise and sunset to datatypes, these are specific to both current conditions and forecast data
# 09/05/2008 Added moon phase, barometer reading and barometer description to datatypes, these are only specific to current conditions and so are N/A in forecasted output
# 09/05/2008 Added unit conversions for barometer from mb to inches (imperial)
# 09/05/2008 Updated spanish condition text - Thanks Bruce M
# 10/05/2008 Added french locale data - Thanks benpaka
# 12/05/2008 Added new BF (bearing font) datatype to provide an arrow character (use with Arrow.ttf font) instead of NSEW output from WD (wind direction)
# 12/05/2008 Updated WD output to be locale specific, currently supports default english and spanish - Thanks Bruce M
# 18/05/2008 Added new MF (moon font) datatype to provide a moon font character (characters incorrect and no dedicated font yet).
# 21/05/2008 For current conditions the --datatype=LT option now displays "feels like" temperature rather than the current temperature
#
# TODO:
# Consolidate pkl files into one file/class
# Add a weather font based moon phase output based on moon icon data
# ??? Any more requirements out there?
import sys, os, socket, urllib2, datetime, time
from xml.dom import minidom
from stat import *
from optparse import OptionParser
import locale
import gettext
import pickle
from math import *
APP="conkyForecast.py"
DIR=os.path.dirname (__file__) + '/locale'
gettext.bindtextdomain(APP, DIR)
gettext.textdomain(APP)
_ = gettext.gettext
class CommandLineParser:
parser = None
def __init__(self):
self.parser = OptionParser()
self.parser.add_option("-l","--location", dest="location", default="UKXX0103", type="string", metavar="CODE", help=u"location code for weather data [default: %default],Use the following url to determine your location code by city name: http://xoap.weather.com/search/search?where=Norwich")
self.parser.add_option("-d","--datatype",dest="datatype", default="HT", type="string", metavar="DATATYPE", help=u"[default: %default] The data type options are: DW (Day Of Week), WF (Weather Font Output), LT (Forecast:Low Temp,Current:Feels Like Temp), HT (Forecast:High Temp,Current:Current Temp), CC (Current Conditions), CT (Conditions Text), PC (Precipitation Chance), HM (Humidity), WD (Wind Direction), WS (Wind Speed), WG (Wind Gusts), CN (City Name), SR (sunrise), SS (sunset), MP (moon phase), MF (moon font), BR (barometer reading), BD (barometer description). Not applicable at command line when using templates.")
self.parser.add_option("-s","--startday",dest="startday", type="int", metavar="NUMBER", help=u"define the starting day number, if omitted current conditions are output. Not applicable at command line when using templates.")
self.parser.add_option("-e","--endday",dest="endday", type="int", metavar="NUMBER", help=u"define the ending day number, if omitted only starting day data is output. Not applicable at command line when using templates.")
self.parser.add_option("-S","--spaces",dest="spaces", type="int", default=1, metavar="NUMBER", help=u"[default: %default] Define the number of spaces between ranged output. Not applicable at command line when using templates.")
self.parser.add_option("-t","--template",dest="template", type="string", metavar="FILE", help=u"define a template file to generate output in one call. A displayable item in the file is in the form {--datatype=HT --startday=1}. The following are possible options within each item: --datatype,--startday,--endday,--night,--shortweekday,--imperial,--hideunits,--spaces . Note that the short forms of the options are not currently supported! None of these options are applicable at command line when using templates.")
self.parser.add_option("-L","--locale",dest="locale", type="string", help=u"override the system locale for language output (en=english, es=spanish, fr=french, more to come)")
self.parser.add_option("-i","--imperial",dest="imperial", default=False, action="store_true", help=u"request imperial units, if omitted output is in metric. Not applicable at command line when using templates.")
self.parser.add_option("-n","--night",dest="night", default=False, action="store_true", help=u"switch output to night data, if omitted day output will be output. Not applicable at command line when using templates.")
self.parser.add_option("-w","--shortweekday",dest="shortweekday", default=False, action="store_true", help=u"Shorten the day of week data type to 3 characters. Not applicable at command line when using templates.")
self.parser.add_option("-u","--hideunits",dest="hideunits", default=False, action="store_true", help=u"Hide units such as mph or C, degree symbols (°) are still shown. Not applicable at command line when using templates.")
self.parser.add_option("-v","--verbose",dest="verbose", default=False, action="store_true", help=u"request verbose output, no a good idea when running through conky!")
self.parser.add_option("-r","--refetch",dest="refetch", default=False, action="store_true", help=u"fetch data regardless of data expiry")
def parse_args(self):
(options, args) = self.parser.parse_args()
return (options, args)
def print_help(self):
return self.parser.print_help()
class WeatherData:
def __init__(self, day_of_week, low, high, condition_code, condition_text, precip, humidity, wind_dir, wind_speed, wind_gusts, city, sunrise, sunset, moon_phase, moon_icon, bar_read, bar_desc):
self.day_of_week = u""+day_of_week
self.low = u""+low
self.high = u""+high
self.condition_code = u""+condition_code
self.condition_text = u""+condition_text
self.precip = u""+precip
self.humidity = u""+humidity
self.wind_dir = u""+wind_dir
self.wind_speed = u""+wind_speed
self.wind_gusts = u""+wind_gusts
self.city = u""+city
self.sunrise = u""+sunrise
self.sunset = u""+sunset
self.moon_phase = u""+moon_phase
self.moon_icon = u""+moon_icon
self.bar_read = u""+bar_read
self.bar_desc = u""+bar_desc
class WeatherText:
conditions_text = {
"0": _(u"Tornado"),
"1": _(u"Tropical Storm"),
"2": _(u"Hurricane"),
"3": _(u"Severe Thunderstorms"),
"4": _(u"Thunderstorms"),
"5": _(u"Mixed Rain and Snow"),
"6": _(u"Mixed Rain and Sleet"),
"7": _(u"Mixed Precipitation"),
"8": _(u"Freezing Drizzle"),
"9": _(u"Drizzle"),
"10": _(u"Freezing Rain"),
"11": _(u"Showers"),
"12": _(u"Showers"),
"13": _(u"Snow Flurries"),
"14": _(u"Light Snow Showers"),
"15": _(u"Blowing Snow"),
"16": _(u"Snow"),
"17": _(u"Hail"),
"18": _(u"Sleet"),
"19": _(u"Dust"),
"20": _(u"Fog"),
"21": _(u"Haze"),
"22": _(u"Smoke"),
"23": _(u"Blustery"),
"24": _(u"Windy"),
"25": _(u"Cold"),
"26": _(u"Cloudy"),
"27": _(u"Mostly Cloudy"),
"28": _(u"Mostly Cloudy"),
"29": _(u"Partly Cloudy"),
"30": _(u"Partly Cloudy"),
"31": _(u"Clear"),
"32": _(u"Clear"),
"33": _(u"Fair"),
"34": _(u"Fair"),
"35": _(u"Mixed Rain and Hail"),
"36": _(u"Hot"),
"37": _(u"Isolated Thunderstorms"),
"38": _(u"Scattered Thunderstorms"),
"39": _(u"Scattered Thunderstorms"),
"40": _(u"Scattered Showers"),
"41": _(u"Heavy Snow"),
"42": _(u"Scattered Snow Showers"),
"43": _(u"Heavy Snow"),
"44": _(u"Partly Cloudy"),
"45": _(u"Thunder Showers"),
"46": _(u"Snow Showers"),
"47": _(u"Isolated Thunderstorms"),
"na": _(u"N/A"),
"-": _(u"N/A")
}
conditions_text_es = {
"0": _(u"Tornado"),
"1": _(u"Tormenta Tropical"),
"2": _(u"Huracá¡n"),
"3": _(u"Tormentas Fuertes"),
"4": _(u"Tormentas"),
"5": _(u"Lluvia y Nieve Mezclada"),
"6": _(u"Lluvia y Aguanieve Mezclada"),
"7": _(u"Aguanieve"),
"8": _(u"Llovizna Helada"),
"9": _(u"Llovizna"),
"10": _(u"Lluvia Engelante"), # o lluvia helada
"11": _(u"Chaparrones"),
"12": _(u"Chaparrones"),
"13": _(u"Nieve Ligera"),
"14": _(u"Nieve Ligera"),
"15": _(u"Ventisca de Nieve"),
"16": _(u"Nieve"),
"17": _(u"Granizo"),
"18": _(u"Aguanieve"),
"19": _(u"Polvo"),
"20": _(u"Niebla"),
"21": _(u"Bruma"),
"22": _(u"Humo"),
"23": _(u"Tempestad"),
"24": _(u"Ventoso"),
"25": _(u"Fráo"),
"26": _(u"Muy Nublado"),
"27": _(u"Principalmente Nublado"),
"28": _(u"Principalmente Nublado"),
"29": _(u"Parcialmente Nublado"),
"30": _(u"Parcialmente Nublado"),
"31": _(u"Despejado"),
"32": _(u"Despejado"),
"33": _(u"Algo Nublado"),
"34": _(u"Algo Nublado"),
"35": _(u"Lluvia con Granizo"),
"36": _(u"Calor"),
"37": _(u"Tormentas Aisladas"),
"38": _(u"Tormentas Dispersas"),
"39": _(u"Tormentas Dispersas"),
"40": _(u"Chubascos Dispersos"),
"41": _(u"Nieve Pesada"),
"42": _(u"Nevadas Débiles y Dispersas"),
"43": _(u"Nevada Intensa"),
"44": _(u"Nubes Dispersas"),
"45": _(u"Tormentas"),
"46": _(u"Nevadas Dispersas"),
"47": _(u"Tormentas Aisladas"),
"na": _(u"N/A"),
"-": _(u"N/A")
}
conditions_text_fr = {
"0": _(u"Tornade"),
"1": _(u"Tempête Tropicale"),
"2": _(u"Ouragan"),
"3": _(u"Orages Violents"),
"4": _(u"Orageux"),
"5": _(u"Pluie et Neige"),
"6": _(u"Pluie et Neige Mouillée"),
"7": _(u"Variable avec averses"),
"8": _(u"Bruine Givrante"),
"9": _(u"Bruine"),
"10": _(u"Pluie Glacante"),
"11": _(u"Averses"),
"12": _(u"Averses"),
"13": _(u"Légère Neige"),
"14": _(u"Forte Neige"),
"15": _(u"Tempête de Neige"),
"16": _(u"Neige"),
"17": _(u"Grêle"),
"18": _(u"Pluie/Neige"),
"19": _(u"Nuage de poussière"),
"20": _(u"Brouillard"),
"21": _(u"Brume"),
"22": _(u"Fumée"),
"23": _(u"Tres Venteux"),
"24": _(u"Venteux"),
"25": _(u"Froid"),
"26": _(u"Nuageux"),
"27": _(u"Tres Nuageux"),
"28": _(u"Tres Nuageux"),
"29": _(u"Nuages Disséminés"),
"30": _(u"Nuages Disséminés"),
"31": _(u"Beau"),
"32": _(u"Beau"),
"33": _(u"Belles Éclaircies"),
"34": _(u"Belles Éclaircies"),
"35": _(u"Pluie avec Grêle"),
"36": _(u"Chaleur"),
"37": _(u"Orages Isolés"),
"38": _(u"Orages Localisés"),
"39": _(u"Orages Localisés"),
"40": _(u"Averses Localisées"),
"41": _(u"Neige Lourde"),
"42": _(u"Tempête de Neige Localisées"),
"43": _(u"Neige Lourde"),
"44": _(u"Nuages Disséminés"),
"45": _(u"Orages"),
"46": _(u"Tempête de Neige"),
"47": _(u"Orages Isolés"),
"na": _(u"N/A"),
"-": _(u"N/A")
}
conditions_weather_font = {
"0": _(u"W"),
"1": _(u"V"),
"2": _(u"W"),
"3": _(u"s"),
"4": _(u"p"),
"5": _(u"k"),
"6": _(u"k"),
"7": _(u"g"),
"8": _(u"g"),
"9": _(u"g"),
"10": _(u"h"),
"11": _(u"g"),
"12": _(u"g"),
"13": _(u"k"),
"14": _(u"k"),
"15": _(u"k"),
"16": _(u"k"),
"17": _(u"k"),
"18": _(u"k"),
"19": _(u"e"),
"20": _(u"e"),
"21": _(u"a"),
"22": _(u"d"),
"23": _(u"d"),
"24": _(u"d"),
"25": _(u"d"),
"26": _(u"e"),
"27": _(u"e"),
"28": _(u"e"),
"29": _(u"c"),
"30": _(u"c"),
"31": _(u"a"),
"32": _(u"a"),
"33": _(u"b"),
"34": _(u"b"),
"35": _(u"k"),
"36": _(u"a"),
"37": _(u"f"),
"38": _(u"f"),
"39": _(u"f"),
"40": _(u"g"),
"41": _(u"k"),
"42": _(u"k"),
"43": _(u"k"),
"44": _(u"b"),
"45": _(u"g"),
"46": _(u"k"),
"47": _(u"f"),
"na": _(u""),
"-": _(u"")
}
conditions_moon_font = {
"0": _(u"0"),
"1": _(u"1"),
"2": _(u"2"),
"3": _(u"3"),
"4": _(u"4"),
"5": _(u"5"),
"6": _(u"6"),
"7": _(u"7"),
"8": _(u"8"),
"9": _(u"9"),
"10": _(u"10"),
"11": _(u"11"),
"12": _(u"12"),
"13": _(u"13"),
"14": _(u"14"),
"15": _(u"15"),
"16": _(u"16"),
"17": _(u"17"),
"18": _(u"18"),
"19": _(u"19"),
"20": _(u"20"),
"21": _(u"21"),
"22": _(u"22"),
"23": _(u"23"),
"24": _(u"24"),
"25": _(u"25"),
"na": _(u""),
"-": _(u"")
}
day_of_week = {
"Today": _(u"Today"),
"Monday": _(u"Monday"),
"Tuesday": _(u"Tuesday"),
"Wednesday": _(u"Wednesday"),
"Thursday": _(u"Thursday"),
"Friday": _(u"Friday"),
"Saturday": _(u"Saturday"),
"Sunday": _(u"Sunday")
}
day_of_week_short = {
"Today": _(u"Now"),
"Monday": _(u"Mon"),
"Tuesday": _(u"Tue"),
"Wednesday": _(u"Wed"),
"Thursday": _(u"Thu"),
"Friday": _(u"Fri"),
"Saturday": _(u"Sat"),
"Sunday": _(u"Sun")
}
day_of_week_es = {
"Today": _(u"hoy"),
"Monday": _(u"lunes"),
"Tuesday": _(u"martes"),
"Wednesday": _(u"miércoles"),
"Thursday": _(u"jueves"),
"Friday": _(u"viernes"),
"Saturday": _(u"sábado"),
"Sunday": _(u"domingo")
}
day_of_week_short_es = {
"Today": _(u"hoy"),
"Monday": _(u"lun"),
"Tuesday": _(u"mar"),
"Wednesday": _(u"mié"),
"Thursday": _(u"jue"),
"Friday": _(u"vie"),
"Saturday": _(u"sáb"),
"Sunday": _(u"dom")
}
day_of_week_fr = {
"Today": _(u"Aujourd'hui"),
"Monday": _(u"Lundi"),
"Tuesday": _(u"Mardi"),
"Wednesday": _(u"Mercredi"),
"Thursday": _(u"Jeudi"),
"Friday": _(u"Vendredi"),
"Saturday": _(u"Samedi"),
"Sunday": _(u"Dimanche")
}
day_of_week_short_fr = {
"Today": _(u"Auj"),
"Monday": _(u"Lun"),
"Tuesday": _(u"Mar"),
"Wednesday": _(u"Mer"),
"Thursday": _(u"Jeu"),
"Friday": _(u"Ven"),
"Saturday": _(u"Sam"),
"Sunday": _(u"Dim")
}
bearing_arrow_font = {
"N": _(u"i"),
"NNE": _(u"j"),
"NE": _(u"k"),
"ENE": _(u"l"),
"E": _(u"m"),
"ESE": _(u"n"),
"SE": _(u"o"),
"SSE": _(u"p"),
"S": _(u"a"),
"SSW": _(u"b"),
"SW": _(u"c"),
"WSW": _(u"d"),
"W": _(u"e"),
"WNW": _(u"f"),
"NW": _(u"g"),
"NNW": _(u"h"),
"N/A": _(u" ")
}
bearing_text_es = {
"N": _(u"N"),
"NNE": _(u"NNE"),
"NE": _(u"NE"),
"ENE": _(u"ENE"),
"E": _(u"E"),
"ESE": _(u"ESE"),
"SE": _(u"SE"),
"SSE": _(u"SSE"),
"S": _(u"S"),
"SSW": _(u"SSO"),
"SW": _(u"SO"),
"WSW": _(u"WOW"),
"W": _(u"O"),
"WNW": _(u"ONO"),
"NW": _(u"NO"),
"NNW": _(u"NNO"),
"N/A": _(u"N\A")
}
bearing_text_fr = {
"N": _(u"N"),
"NNE": _(u"NNE"),
"NE": _(u"NE"),
"ENE": _(u"ENE"),
"E": _(u"E"),
"ESE": _(u"ESE"),
"SE": _(u"SE"),
"SSE": _(u"SSE"),
"S": _(u"S"),
"SSW": _(u"SSO"),
"SW": _(u"SO"),
"WSW": _(u"WOW"),
"W": _(u"O"),
"WNW": _(u"ONO"),
"NW": _(u"NO"),
"NNW": _(u"NNO"),
"N/A": _(u"N\A")
}
class GlobalWeather:
current_conditions = []
day_forecast = []
night_forecast = []
locale = "en"
options = None
weatherxmldoc = ""
TEMP_FILEPATH_CURRENT = "/tmp/conkyForecast-c-LOCATION.pkl"
TEMP_FILEPATH_DAYFORECAST = "/tmp/conkyForecast-df-LOCATION.pkl"
TEMP_FILEPATH_NIGHTFORECAST = "/tmp/conkyForecast-nf-LOCATION.pkl"
EXPIRY_MINUTES = 30
DEFAULT_SPACING = u" "
def __init__(self,options):
self.options = options
if self.options.locale == None:
try:
self.locale = locale.getdefaultlocale()[0][0:2]
#self.locale = "es" #uncomment this line to force Spanish locale
#self.locale = "fr" #uncomment this line to force French locale
except:
print "locale not set"
else:
self.locale = self.options.locale
#self.locale = "es" #uncomment this line to force Spanish locale
#self.locale = "fr" #uncomment this line to force French locale
if self.options.verbose == True:
print >> sys.stdout, "locale set to ",self.locale
def getText(self,nodelist):
rc = ""
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
rc = rc + node.data
return rc
def getSpaces(self,spaces):
string = u""
if spaces == None:
string = self.DEFAULT_SPACING
else:
for i in range(0, spaces+1):
string = string + u" "
return string
def isNumeric(self,string):
try:
dummy = float(string)
return True
except:
return False
def isConnectionAvailable(self):
# ensure we can access weather.com's server by opening the url
try:
usock = urllib2.urlopen('http://xoap.weather.com')
usock.close()
return True
except:
return False
def getBearingText(self,bearing):
bearing = float(bearing)
if bearing 11.25:
return u"N"
elif bearing 33.75:
return u"NNE"
elif bearing 56.25:
return u"NE"
elif bearing 78.75:
return u"ENE"
elif bearing 101.25:
return u"E"
elif bearing 123.75:
return u"ESE"
elif bearing 146.25:
return u"SE"
elif bearing 168.75:
return u"SSE"
elif bearing 191.25:
return u"S"
elif bearing 213.75:
return u"SSW"
elif bearing 236.25:
return u"SW"
elif bearing 258.75:
return u"WSW"
elif bearing 281.25:
return u"W"
elif bearing 303.75:
return u"WNW"
elif bearing 326.25:
return u"NW"
elif bearing 348.75:
return u"NNW"
else:
return "N/A"
def convertCelsiusToFahrenheit(self,temp):
return str(int(floor(((float(temp)*9.0)/5.0)+32)))
def convertKilometresToMiles(self,dist):
return str(int(floor(float(dist)*0.621371192)))
def convertMillibarsToInches(self,mb):
return str(int(floor(float(mb)/33.8582)))
def getTemplateList(self,template):
templatelist = []
for template_part in template.split("{"):
if template_part != "":
for template_part in template_part.split("}"):
if template_part != "":
templatelist.append(u""+template_part)
return templatelist
def getOutputText(self,datatype,startday,endday,night,shortweekday,imperial,hideunits,spaces):
#try:
output = u""
# define current units for output
if hideunits == False:
if imperial == False:
tempunit = u"°C"
speedunit = u"kph"
pressureunit = u"mb"
else:
tempunit = u"°F"
speedunit = u"mph"
pressureunit = u"in"
else:
tempunit = u"°"
speedunit = u""
pressureunit = u""
if startday == None: # current conditions
if datatype == "DW":
if self.locale == "es":
if shortweekday == True:
output = WeatherText.day_of_week_short_es[self.current_conditions[0].day_of_week]
else:
output = WeatherText.day_of_week_es[self.current_conditions[0].day_of_week]
elif self.locale == "fr":
if shortweekday == True:
output = WeatherText.day_of_week_short_fr[self.current_conditions[0].day_of_week]
else:
output = WeatherText.day_of_week_fr[self.current_conditions[0].day_of_week]
else:
if shortweekday == True:
output = WeatherText.day_of_week_short[self.current_conditions[0].day_of_week]
else:
output = WeatherText.day_of_week[self.current_conditions[0].day_of_week]
elif datatype == "WF": # weather font
output = WeatherText.conditions_weather_font[self.current_conditions[0].condition_code]
elif datatype == "LT":
string = self.current_conditions[0].low
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertCelsiusToFahrenheit(string)
string = string + tempunit
output = string
elif datatype == "HT":
string = self.current_conditions[0].high
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertCelsiusToFahrenheit(string)
string = string + tempunit
output = string
elif datatype == "CC":
if self.locale == "es":
output = WeatherText.conditions_text_es[self.current_conditions[0].condition_code]
elif self.locale == "fr":
output = WeatherText.conditions_text_fr[self.current_conditions[0].condition_code]
else:
output = WeatherText.conditions_text[self.current_conditions[0].condition_code]
elif datatype == "CT":
output = self.current_conditions[0].condition_text
elif datatype == "PC":
string = self.current_conditions[0].precip
if self.isNumeric(string) == True:
string = string + u"%"
output = string
elif datatype == "HM":
string = self.current_conditions[0].humidity
if self.isNumeric(string) == True:
string = string + u"%"
output = string
elif datatype == "WD":
string = self.current_conditions[0].wind_dir
if self.isNumeric(string) == True:
string = self.getBearingText(string)
if self.locale == "es":
output = WeatherText.bearing_text_es[string]
elif self.locale == "fr":
output = WeatherText.bearing_text_fr[string]
else:
output = string
elif datatype == "BF":
string = self.current_conditions[0].wind_dir
if self.isNumeric(string) == True:
string = WeatherText.bearing_arrow_font[self.getBearingText(string)]
output = string
elif datatype == "WS":
string = self.current_conditions[0].wind_speed
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertKilometresToMiles(string)
string = string + speedunit
output = string
elif datatype == "WG":
string = self.current_conditions[0].wind_gusts
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertKilometresToMiles(string)
string = string + speedunit
output = string
elif datatype == "CN":
output = self.current_conditions[0].city
elif datatype == "SR":
output = self.current_conditions[0].sunrise
elif datatype == "SS":
output = self.current_conditions[0].sunset
elif datatype == "MP":
output = self.current_conditions[0].moon_phase
elif datatype == "MF":
output = WeatherText.conditions_moon_font[self.current_conditions[0].moon_icon]
elif datatype == "BR":
string = self.current_conditions[0].bar_read
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertMillibarsToInches(string)
string = string + pressureunit
output = string
elif datatype == "BD":
output = self.current_conditions[0].bar_desc
else:
output = "\nERROR:Unknown data type requested"
else: # forecast data
if endday == None: # if no endday was set use startday
endday = startday
if night == True: # night forecast required
for day_number in range(startday, endday+1):
if datatype == "DW":
if self.locale == "es":
if shortweekday == True:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_short_es[self.night_forecast[day_number].day_of_week]
else:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_es[self.night_forecast[day_number].day_of_week]
elif self.locale == "fr":
if shortweekday == True:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_short_fr[self.night_forecast[day_number].day_of_week]
else:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_fr[self.night_forecast[day_number].day_of_week]
else:
if shortweekday == True:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_short[self.night_forecast[day_number].day_of_week]
else:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week[self.night_forecast[day_number].day_of_week]
elif datatype == "WF": # weather font
output = output + self.getSpaces(spaces) + WeatherText.conditions_weather_font[self.night_forecast[day_number].condition_code]
elif datatype == "LT":
string = self.night_forecast[day_number].low
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertCelsiusToFahrenheit(string)
string = string + tempunit
output = output + self.getSpaces(spaces) + string
elif datatype == "HT":
string = self.night_forecast[day_number].high
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertCelsiusToFahrenheit(string)
string = string + tempunit
output = output + self.getSpaces(spaces) + string
elif datatype == "CC":
if self.locale == "es":
output = output + self.getSpaces(spaces) + WeatherText.conditions_text_es[self.night_forecast[day_number].condition_code]
elif self.locale == "fr":
output = output + self.getSpaces(spaces) + WeatherText.conditions_text_fr[self.night_forecast[day_number].condition_code]
else:
output = output + self.getSpaces(spaces) + WeatherText.conditions_text[self.night_forecast[day_number].condition_code]
elif datatype == "CT":
output = output + self.getSpaces(spaces) + self.night_forecast[day_number].condition_text
elif datatype == "PC":
string = self.night_forecast[day_number].precip
if self.isNumeric(string) == True:
string = string + u"%"
output = output + self.getSpaces(spaces) + string
elif datatype == "HM":
string = self.night_forecast[day_number].humidity
if self.isNumeric(string) == True:
string = string + u"%"
output = output + self.getSpaces(spaces) + string
elif datatype == "WD":
string = self.night_forecast[day_number].wind_dir
if self.locale == "es":
output = output + self.getSpaces(spaces) + WeatherText.bearing_text_es[string]
elif self.locale == "fr":
output = output + self.getSpaces(spaces) + WeatherText.bearing_text_fr[string]
else:
output = output + self.getSpaces(spaces) + string
elif datatype == "BF":
output = output + self.getSpaces(spaces) + WeatherText.bearing_arrow_font[self.night_forecast[day_number].wind_dir]
elif datatype == "WS":
string = self.night_forecast[day_number].wind_speed
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertKilometresToMiles(string)
string = string + speedunit
output = output + self.getSpaces(spaces) + string
elif datatype == "WG":
string = self.night_forecast[day_number].wind_gusts
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertKilometresToMiles(string)
string = string + speedunit
output = output + self.getSpaces(spaces) + string
elif datatype == "CN":
output = output + self.getSpaces(spaces) + self.night_forecast[day_number].city
elif datatype == "SR":
output = output + self.getSpaces(spaces) + self.night_forecast[day_number].sunrise
elif datatype == "SS":
output = output + self.getSpaces(spaces) + self.night_forecast[day_number].sunset
elif datatype == "MP":
output = output + self.getSpaces(spaces) + self.night_forecast[day_number].moon_phase
elif datatype == "MF":
output = output + self.getSpaces(spaces) + WeatherText.conditions_moon_font[self.night_forecast[day_number].moon_icon]
elif datatype == "BR":
output = output + self.getSpaces(spaces) + self.night_forecast[day_number].bar_read
elif datatype == "BD":
output = output + self.getSpaces(spaces) + self.night_forecast[day_number].bar_desc
else:
output = "\nERROR:Unknown data type requested"
break
else: # day forecast wanted
for day_number in range(startday, endday+1):
if datatype == "DW":
if self.locale == "es":
if shortweekday == True:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_short_es[self.day_forecast[day_number].day_of_week]
else:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_es[self.day_forecast[day_number].day_of_week]
elif self.locale == "fr":
if shortweekday == True:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_short_fr[self.day_forecast[day_number].day_of_week]
else:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_fr[self.day_forecast[day_number].day_of_week]
else:
if shortweekday == True:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week_short[self.day_forecast[day_number].day_of_week]
else:
output = output + self.getSpaces(spaces) + WeatherText.day_of_week[self.day_forecast[day_number].day_of_week]
elif datatype == "WF": # weather font
output = output + self.getSpaces(spaces) + WeatherText.conditions_weather_font[self.day_forecast[day_number].condition_code]
elif datatype == "LT":
string = self.day_forecast[day_number].low
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertCelsiusToFahrenheit(string)
string = string + tempunit
output = output + self.getSpaces(spaces) + string
elif datatype == "HT":
string = self.day_forecast[day_number].high
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertCelsiusToFahrenheit(string)
string = string + tempunit
output = output + self.getSpaces(spaces) + string
elif datatype == "CC":
if self.locale == "es":
output = output + self.getSpaces(spaces) + WeatherText.conditions_text_es[self.day_forecast[day_number].condition_code]
elif self.locale == "fr":
output = output + self.getSpaces(spaces) + WeatherText.conditions_text_fr[self.day_forecast[day_number].condition_code]
else:
output = output + self.getSpaces(spaces) + WeatherText.conditions_text[self.day_forecast[day_number].condition_code]
elif datatype == "CT":
output = output + self.getSpaces(spaces) + self.day_forecast[day_number].condition_text
elif datatype == "PC":
string = self.day_forecast[day_number].precip
if self.isNumeric(string) == True:
string = string + u"%"
output = output + self.getSpaces(spaces) + string
elif datatype == "HM":
string = self.day_forecast[day_number].humidity
if self.isNumeric(string) == True:
string = string + u"%"
output = output + self.getSpaces(spaces) + string
elif datatype == "WD":
string = self.day_forecast[day_number].wind_dir
if self.locale == "es":
output = output + self.getSpaces(spaces) + WeatherText.bearing_text_es[string]
elif self.locale == "fr":
output = output + self.getSpaces(spaces) + WeatherText.bearing_text_fr[string]
else:
output = output + self.getSpaces(spaces) + string
elif datatype == "BF":
output = output + self.getSpaces(spaces) + WeatherText.bearing_arrow_font[self.day_forecast[day_number].wind_dir]
elif datatype == "WS":
string = self.day_forecast[day_number].wind_speed
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertKilometresToMiles(string)
string = string + speedunit
output = output + self.getSpaces(spaces) + string
elif datatype == "WG":
string = self.day_forecast[day_number].wind_gusts
if self.isNumeric(string) == True:
if imperial == True:
string = self.convertKilometresToMiles(string)
string = string + speedunit
output = output + self.getSpaces(spaces) + string
elif datatype == "CN":
output = output + self.getSpaces(spaces) + self.day_forecast[day_number].city
elif datatype == "SR":
output = output + self.getSpaces(spaces) + self.day_forecast[day_number].sunrise
elif datatype == "SS":
output = output + self.getSpaces(spaces) + self.day_forecast[day_number].sunset
elif datatype == "MP":
output = output + self.getSpaces(spaces) + self.day_forecast[day_number].moon_phase
elif datatype == "MF":
output = output + self.getSpaces(spaces) + WeatherText.conditions_moon_font[self.day_forecast[day_number].moon_icon]
elif datatype == "BR":
output = output + self.getSpaces(spaces) + self.day_forecast[day_number].bar_read
elif datatype == "BD":
output = output + self.getSpaces(spaces) + self.day_forecast[day_number].bar_desc
else:
output = u"\nERROR:Unknown data type requested"
break
output = u""+output.strip(u" ") # lose leading/trailing spaces
return output
#except:
#print "getOutputText:Unexpected error: ", sys.exc_info()[0]
def getOutputTextFromTemplate(self,template):
#try:
# keys to template data
DATATYPE_KEY = "--datatype="
STARTDAY_KEY = "--startday="
ENDDAY_KEY = "--endday="
NIGHT_KEY = "--night"
SHORTWEEKDAY_KEY = "--shortweekday"
IMPERIAL_KEY = "--imperial"
HIDEUNITS_KEY = "--hideunits"
SPACES_KEY = "--spaces="
output = u""
optionfound = False
#load the file
try:
fileinput = open(self.options.template)
template = fileinput.read()
fileinput.close()
except:
output = u"Template file no found!"
templatelist = self.getTemplateList(template)
# lets walk through the template list and determine the output for each item found
for i in range(0,len(templatelist)-1):
pos = templatelist[i].find(DATATYPE_KEY)
if pos != -1:
optionfound = True
pos = pos + len(DATATYPE_KEY)
datatype = templatelist[i][pos:pos+4].strip("}").strip("{").strip("-").strip(" ")
else:
datatype = None
pos = templatelist[i].find(STARTDAY_KEY)
if pos != -1:
optionfound = True
pos = pos + len(STARTDAY_KEY)
startday = int(templatelist[i][pos:pos+4].strip("}").strip("{").strip("-").strip(" "))
else:
startday = None
pos = templatelist[i].find(ENDDAY_KEY)
if pos != -1:
optionfound = True
pos = pos + len(ENDDAY_KEY)
endday = int(templatelist[i][pos:pos+4].strip("}").strip("{").strip("-").strip(" "))
else:
endday = None
pos = templatelist[i].find(NIGHT_KEY)
if pos != -1:
optionfound = True
night = True
else:
night = False
pos = templatelist[i].find(SHORTWEEKDAY_KEY)
if pos != -1:
optionfound = True
shortweekday = True
else:
shortweekday = False
pos = templatelist[i].find(IMPERIAL_KEY)
if pos != -1:
optionfound = True
imperial = True
else:
imperial = False
pos = templatelist[i].find(HIDEUNITS_KEY)
if pos != -1:
optionfound = True
hideunits = True
else:
hideunits = False
pos = templatelist[i].find(SPACES_KEY)
if pos != -1:
optionfound = True
pos = pos + len(SPACES_KEY)
spaces = int(templatelist[i][pos:pos+4].strip("}").strip("{").strip("-").strip(" "))
else:
spaces = 1
if optionfound == True:
templatelist[i] = self.getOutputText(datatype,startday,endday,night,shortweekday,imperial,hideunits,spaces)
optionfound = False
# go through the list concatenating the output now that it's been populated
for item in templatelist:
output = output + item
return output
#except:
#print "getOutputTextFromTemplate:Unexpected error: ", sys.exc_info()[0]
def fetchData(self):
# always fetch metric data, use conversation functions on this data
file_path_current = self.TEMP_FILEPATH_CURRENT.replace("LOCATION",self.options.location)
file_path_dayforecast = self.TEMP_FILEPATH_DAYFORECAST.replace("LOCATION",self.options.location)
file_path_nightforecast = self.TEMP_FILEPATH_NIGHTFORECAST.replace("LOCATION",self.options.location)
if self.isConnectionAvailable() == False:
if os.path.exists(file_path_current):
RefetchData = False
else: # no connection, no cache, bang!
print "No internet connection is available and no cached weather data exists."
elif self.options.refetch == True:
RefetchData = True
else:
# does the data need retrieving again?
if os.path.exists(file_path_current):
lastmodDate = time.localtime(os.stat(file_path_current)[ST_MTIME])
expiryDate = (datetime.datetime.today() - datetime.timedelta(minutes=self.EXPIRY_MINUTES)).timetuple()
if expiryDate > lastmodDate:
RefetchData = True
else:
RefetchData = False
else:
RefetchData = True
# fetch the current conditions data, either from the website or by 'unpickling'
if RefetchData == True:
# obtain current conditions data from xoap service
try:
# http://xoap.weather.com/weather/local/UKXX0103?cc=*=5=xoap=xoap=1061785028=e374effbfd74930b
url = 'http://xoap.weather.com/weather/local/' + self.options.location + '?cc=*=8=xoap=xoap=1061785028=e374effbfd74930b=m'
if self.options.verbose == True:
print >> sys.stdout, "fetching weather data from ",url
usock = urllib2.urlopen(url)
xml = usock.read()
usock.close()
self.weatherxmldoc = minidom.parseString(xml)
except:
print "fetchData:Unexpected error: ", sys.exc_info()[0]
print "Unable to contact weather source for current conditions"
# tell the user if the location is bad...
found = xml.find("Invalid location provided")
if found != -1:
print "Invalid location provided"
# interrogate weather data, load into class structure and pickle it
try:
# prepare weather data lists
self.current_conditions = []
self.day_forecast = []
self.night_forecast = []
# collect general data
weather_n = self.weatherxmldoc.documentElement
location_n = weather_n.getElementsByTagName('loc')[0]
city_n = location_n.getElementsByTagName('dnam')[0]
city = self.getText(city_n.childNodes)
# collect current conditions data
day_of_week = u"Today"
precip = u"N/A"
sunrise_n = location_n.getElementsByTagName('sunr')[0]
sunrise = self.getText(sunrise_n.childNodes)
sunset_n = location_n.getElementsByTagName('suns')[0]
sunset = self.getText(sunset_n.childNodes)
current_condition_n = weather_n.getElementsByTagName('cc')[0]
current_desc_n = current_condition_n.getElementsByTagName('t')[0]
current_desc = self.getText(current_desc_n.childNodes)
current_code_n = current_condition_n.getElementsByTagName('icon')[0]
current_code = self.getText(current_code_n.childNodes)
current_temp_n = current_condition_n.getElementsByTagName('tmp')[0]
current_temp = self.getText(current_temp_n.childNodes)
current_temp_feels_n = current_condition_n.getElementsByTagName('flik')[0]
current_temp_feels = self.getText(current_temp_feels_n.childNodes)
bar_n = current_condition_n.getElementsByTagName('bar')[0]
bar_read_n = bar_n.getElementsByTagName('r')[0]
bar_read = self.getText(bar_read_n.childNodes)
bar_desc_n = bar_n.getElementsByTagName('d')[0]
bar_desc = self.getText(bar_desc_n.childNodes)
wind_n = current_condition_n.getElementsByTagName('wind')[0]
wind_speed_n = wind_n.getElementsByTagName('s')[0]
wind_speed = self.getText(wind_speed_n.childNodes)
wind_gust_n = wind_n.getElementsByTagName('gust')[0]
wind_gusts = self.getText(wind_gust_n.childNodes)
wind_dir_n = wind_n.getElementsByTagName('d')[0]
wind_direction = self.getText(wind_dir_n.childNodes)
humidity_n = current_condition_n.getElementsByTagName('hmid')[0]
humidity = self.getText(humidity_n.childNodes)
moon_n = current_condition_n.getElementsByTagName('moon')[0]
moon_icon_n = moon_n.getElementsByTagName('icon')[0]
moon_icon = self.getText(moon_icon_n.childNodes)
moon_phase_n = moon_n.getElementsByTagName('t')[0]
moon_phase = self.getText(moon_phase_n.childNodes)
current_conditions_data = WeatherData(day_of_week, current_temp_feels, current_temp, current_code, current_desc, precip, humidity, wind_direction, wind_speed, wind_gusts, city, sunrise, sunset, moon_phase, moon_icon, bar_read, bar_desc)
self.current_conditions.append(current_conditions_data)
# collect forecast data
bar_read = u"N/A"
bar_desc = u"N/A"
moon_phase = u"N/A"
moon_icon = u"na"
forecast_n = weather_n.getElementsByTagName('dayf')[0]
day_nodes = forecast_n.getElementsByTagName('day')
for day in day_nodes:
day_of_week = day.getAttribute('t')
day_of_year = day.getAttribute('dt')
high_temp_n = day.getElementsByTagName('hi')[0]
high_temp = self.getText(high_temp_n.childNodes)
low_temp_n = day.getElementsByTagName('low')[0]
low_temp = self.getText(low_temp_n.childNodes)
sunrise_n = day.getElementsByTagName('sunr')[0]
sunrise = self.getText(sunrise_n.childNodes)
sunset_n = day.getElementsByTagName('suns')[0]
sunset = self.getText(sunset_n.childNodes)
# day forecast specific data
daytime_n = day.getElementsByTagName('part')[0] # day
condition_code_n = daytime_n.getElementsByTagName('icon')[0]
condition_code = self.getText(condition_code_n.childNodes)
condition_n = daytime_n.getElementsByTagName('t')[0]
condition = self.getText(condition_n.childNodes)
precip_n = daytime_n.getElementsByTagName('ppcp')[0]
precip = self.getText(precip_n.childNodes)
humidity_n = daytime_n.getElementsByTagName('hmid')[0]
humidity = self.getText(humidity_n.childNodes)
wind_n = daytime_n.getElementsByTagName('wind')[0]
wind_speed_n = wind_n.getElementsByTagName('s')[0]
wind_speed = self.getText(wind_speed_n.childNodes)
wind_direction_n = wind_n.getElementsByTagName('t')[0]
wind_direction = self.getText(wind_direction_n.childNodes)
wind_gusts_n = wind_n.getElementsByTagName('gust')[0]
wind_gusts = self.getText(wind_gusts_n.childNodes)
day_forecast_data = WeatherData(day_of_week, low_temp, high_temp, condition_code, condition, precip, humidity, wind_direction, wind_speed, wind_gusts, city, sunrise, sunset, moon_phase, moon_icon, bar_read, bar_desc)
self.day_forecast.append(day_forecast_data)
# night forecast specific data
daytime_n = day.getElementsByTagName('part')[1] # night
condition_code_n = daytime_n.getElementsByTagName('icon')[0]
condition_code = self.getText(condition_code_n.childNodes)
condition_n = daytime_n.getElementsByTagName('t')[0]
condition = self.getText(condition_n.childNodes)
precip_n = daytime_n.getElementsByTagName('ppcp')[0]
precip = self.getText(precip_n.childNodes)
humidity_n = daytime_n.getElementsByTagName('hmid')[0]
humidity = self.getText(humidity_n.childNodes)
wind_n = daytime_n.getElementsByTagName('wind')[0]
wind_speed_n = wind_n.getElementsByTagName('s')[0]
wind_speed = self.getText(wind_speed_n.childNodes)
wind_direction_n = wind_n.getElementsByTagName('t')[0]
wind_direction = self.getText(wind_direction_n.childNodes)
wind_gusts_n = wind_n.getElementsByTagName('gust')[0]
wind_gusts = self.getText(wind_gusts_n.childNodes)
night_forecast_data = WeatherData(day_of_week, low_temp, high_temp, condition_code, condition, precip, humidity, wind_direction, wind_speed, wind_gusts, city, sunrise, sunset, moon_phase, moon_icon, bar_read, bar_desc)
self.night_forecast.append(night_forecast_data)
# pickle the data for next time!
fileoutput = open(file_path_current, 'w')
pickle.dump(self.current_conditions,fileoutput)
fileoutput.close()
fileoutput = open(file_path_dayforecast, 'w')
pickle.dump(self.day_forecast,fileoutput)
fileoutput.close()
fileoutput = open(file_path_nightforecast, 'w')
pickle.dump(self.night_forecast,fileoutput)
fileoutput.close()
except:
print "fetchData:Unexpected error: ", sys.exc_info()[0]
print "Unable to interrogate the weather data"
else: # fetch weather data from pickled class files
if self.options.verbose == True:
print >> sys.stdout, "fetching weather data from file: ",file_path_current
fileinput = open(file_path_current, 'r')
self.current_conditions = pickle.load(fileinput)
fileinput.close()
if self.options.verbose == True:
print >> sys.stdout, "fetching day forecast data from files: ",file_path_dayforecast, file_path_nightforecast
fileinput = open(file_path_dayforecast, 'r')
self.day_forecast = pickle.load(fileinput)
fileinput.close()
if self.options.verbose == True:
print >> sys.stdout, "fetching day forecast data from files: ",file_path_nightforecast, file_path_nightforecast
fileinput = open(file_path_nightforecast, 'r')
self.night_forecast = pickle.load(fileinput)
fileinput.close()
def outputData(self):
#try:
if self.options.template != None:
output = self.getOutputTextFromTemplate(self.options.template)
else:
output = self.getOutputText(self.options.datatype,self.options.startday,self.options.endday,self.options.night,self.options.shortweekday,self.options.imperial,self.options.hideunits,self.options.spaces)
print output.encode("utf-8")
#except:
#print "outputData:Unexpected error: ", sys.exc_info()[0]
if __name__ == "__main__":
parser = CommandLineParser()
(options, args) = parser.parse_args()
if options.verbose == True:
print >> sys.stdout, "location:",options.location
print >> sys.stdout, "imperial:",options.imperial
print >> sys.stdout, "datatype:",options.datatype
print >> sys.stdout, "night:",options.night
print >> sys.stdout, "start day:",options.startday
print >> sys.stdout, "end day:",options.endday
print >> sys.stdout, "spaces:",options.spaces
print >> sys.stdout, "verbose:",options.verbose
print >> sys.stdout, "refetch:",options.refetch
# create new global weather object
weather = GlobalWeather(options)
weather.fetchData()
weather.outputData()
Save this script as conkyForecast.py
and make it executable.
Install fonts using nautilus-actions
Caveat lector: I wrote this post in high school; it’s likely outdated and poorly written.
Nautilus-Actions installs custom entries in the context menu in nautilus. I needed a simple way to install fonts so I wrote a command for nautilus-actions.
Set “Path:” to bash
Set Parameters to
-c "if zenity --question --text=\"Would you like to install the font system wide?\" --title=\"Install to System\"; then gksudo cp %M /usr/share/fonts/truetype/local/%m; else cp %M ~/.fonts/%m; fi; exit 0;"
.
If you do not want to install nautilus actions you can simply create a Nautilus script.
The contents of the script should be:
#!/bin/bash
if zenity --question --text="Would you like to install the font system wide?" --title="Install to System"; then
for $i in $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS; do
gksudo cp $i /usr/share/fonts/truetype/local/$(basename $i)
done
else
for $i in $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS; do
cp $i ~/.fonts/$(basename $i)
done
fi
exit 0
Save this script in ‘~/.gnome2/nautilus-scripts’ and make it executable (chmod u+x
).