changeset 3:a754b01955c7

1st stage of work for final 0.2.0
author Vlad Glagolev <enqlave@gmail.com>
date Mon, 27 Jul 2009 00:02:10 +0400
parents bf34534a0acd
children fd9d81f66ff7
files ChangeLog LICENSE pycweather/__init__.py pycweather/dmanager.py pycweather/template.py pycweather/weather.py setup.py share/template.xsl
diffstat 8 files changed, 223 insertions(+), 169 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Nov 06 23:02:41 2008 +0300
+++ b/ChangeLog	Mon Jul 27 00:02:10 2009 +0400
@@ -1,3 +1,9 @@
+2009-07-26 Vlad Glagolev <enqlave@gmail.com>
+	* version 0.2.0
+	* fixed max-day limit to 5 as supported by weather.com
+	* added missing parameters in request (needed since 2009-07-07)
+	* rewritten the engine in OOP
+
 2008-11-06 Vlad Glagolev <enqlave@gmail.com>
 	* bump to 0.1.2
 	* removed useless installation of text files for now
--- a/LICENSE	Thu Nov 06 23:02:41 2008 +0300
+++ b/LICENSE	Mon Jul 27 00:02:10 2009 +0400
@@ -1,4 +1,5 @@
-Copyright (c) 2008 Vlad Glagolev <enqlave@gmail.com>. All rights reserved.
+Copyright (c) 2008-2009 Vlad Glagolev <enqlave@gmail.com>
+All rights reserved.
 
 Permission to use, copy, modify, and distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
--- a/pycweather/__init__.py	Thu Nov 06 23:02:41 2008 +0300
+++ b/pycweather/__init__.py	Mon Jul 27 00:02:10 2009 +0400
@@ -2,7 +2,8 @@
 #
 # This file is part of PycWeather
 #
-# Copyright (c) 2008 Vlad Glagolev <enqlave@gmail.com>. All rights reserved.
+# Copyright (c) 2008-2009 Vlad Glagolev <enqlave@gmail.com>
+# All rights reserved.
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -18,4 +19,4 @@
 
 """ pycweather/__init__.py: initialization script """
 
-__version__ = "0.1.2"
+__version__ = "0.2.0"
--- a/pycweather/dmanager.py	Thu Nov 06 23:02:41 2008 +0300
+++ b/pycweather/dmanager.py	Mon Jul 27 00:02:10 2009 +0400
@@ -2,7 +2,8 @@
 #
 # This file is part of PycWeather
 #
-# Copyright (c) 2008 Vlad Glagolev <enqlave@gmail.com>. All rights reserved.
+# Copyright (c) 2008-2009 Vlad Glagolev <enqlave@gmail.com>
+# All rights reserved.
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -18,38 +19,33 @@
 
 """ pycweather/dmanager.py: weather display manager """
 
-from cStringIO import StringIO
 import getopt
 import os
 import sys
-import urllib2
-
-from lxml.etree import parse, tostring, fromstring, XMLSyntaxError
 
 from pycweather import __version__
-from pycweather.template import XSL
+from pycweather import weather
 
 
-# correct url to the XOAP service
-XOAP_URL = "http://xoap.weather.com/"
-
-# default values stay for Moscow (RU) location, 0 days to display (means only
+# default values stay for Moscow (RU) location, 1 days to display (means only
 # current day), metric measurement system and internal XSL stylesheet usage
 _CODE = "RSXX0063"
 _DAYS = 1
 _UNIT = "m"
-_XSL = None
+
+# TODO: default XSL template
+_TEMPLATE = os.path.join(os.path.dirname(__file__), "template.xsl")
 
 
 def usage():
     print """Usage: %s [options]\n
     -h, --help		show this help
     -v, --version	version information
+    -a, --auth <id:key> authority data in format: partner-id:license-key
     -c, --code <code>	location ID code (default is %s)
-    -d, --days <days>	number of days to display [1-10] (default is %d)
+    -d, --days <days>	number of days to display [1-5] (default is %d)
     -u, --unit <unit>	measurement system [m]etric|[i]mperial (default is %s)
     -s, --search <word>	search for the specified location (city, state, etc.)
-    -i, --int		dump internal XSL stylesheet to stdout
     -x, --xsl <file>	custom XSL file\n""" % (sys.argv[0], _CODE, _DAYS, _UNIT)
 
 
@@ -61,59 +57,26 @@
     exit(0)
 
 
-def search(location):
-    data = urllib2.urlopen(XOAP_URL + "search/search?where=%s" % location)
-
-    tree = data.read()
-
-    try:
-        xml = fromstring(tree)
-    except XMLSyntaxError:
-        print "XML syntax error occured while parsing content: ", tree
-        exit(2)
-
-    if not xml.getchildren():
-        print "No location has been found!"
-    elif xml.tag == "error":
-        print "Error: %s" % xml.getchildren()[0].text
-    else:
-        print "Code    | Location\n--------+----------"
-        for loc in xml.xpath("loc"):
-            print loc.get("id") + ": " + loc.text
-
-        print "--\nTo catch weather information use: %s -c <code>" % sys.argv[0]
-
-    exit(0)
-
-
-def preview(xml, xsl):
-    try:
-        xsl_file = parse(xsl) if xsl else fromstring(XSL)
-    except XMLSyntaxError:
-        print "XML syntax error occured while parsing XSL stylesheet"
-        exit(2)
-
-    document = parse(StringIO(tostring(xml)))
-
-    print document.xslt(xsl_file)
-
-
 def main():
     try:
-        opts, args = getopt.getopt(sys.argv[1:], "hvc:d:u:s:ix:", ["help", \
-                                   "version", "code=", "days=", "unit=", \
-                                   "search=", "int", "xsl="])
+        opts, args = getopt.getopt(sys.argv[1:], "hva:c:d:u:s:x:", ["help", \
+                                   "version", "auth=", "code=", "days=", \
+                                   "unit=", "search=", "xsl="])
     except getopt.error, msg:
         print msg
         usage()
         exit(2)
 
+    forecast = weather.Weather()
+
     for o, a in opts:
         if o in ("-h", "--help"):
             usage()
             exit(0)
         elif o in ("-v", "--version"):
             version()
+        elif o in ("-a", "--auth"):
+            forecast.auth(a)
         elif o in ("-c", "--code"):
             code = a
         elif o in ("-d", "--days"):
@@ -121,9 +84,7 @@
         elif o in ("-u", "--unit"):
             unit = a
         elif o in ("-s", "--search"):
-            search(a)
-        elif o in ("-i", "--int"):
-            print XSL
+            forecast.search(a)
             exit(0)
         elif o in ("-x", "--xsl"):
             xsl = a
@@ -145,30 +106,12 @@
 
     try:
         xsl
+    except NameError:
+        xsl = _TEMPLATE
 
-        if not os.access(xsl, os.R_OK):
-            print "Error reading custom XSL file, using internal stylesheet..."
-            xsl = _XSL
-    except NameError:
-        xsl = _XSL
+    forecast.load(xsl)
 
-    try:
-        data = urllib2.urlopen(XOAP_URL + \
-                               "weather/local/%s?cc=*&dayf=%d&unit=%s" % (code,
-                               days, unit))
-    except:
-        print "Unable to connect to %s" % XOAP_URL
-        exit(2)
-
-    tree = data.read()
-
-    try:
-        xml = fromstring(tree)
-    except XMLSyntaxError:
-        print "XML syntax error occured while parsing content: ", tree
-        exit(2)
-
-    if xml.tag == "error":
-        print "Error: %s" % xml.xpath("err")[0].text
+    if forecast.id and forecast.key:
+        forecast.preview(code, days, unit)
     else:
-        preview(xml, xsl)
+        print "Look at http://registration.weather.com/ursa/xmloap/step1"
--- a/pycweather/template.py	Thu Nov 06 23:02:41 2008 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of PycWeather
-#
-# Copyright (c) 2008 Vlad Glagolev <enqlave@gmail.com>. All rights reserved.
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-""" pycweather/template.py: XSL stylesheet for displaying weather """
-
-from pycweather import __version__
-
-
-XSL = """<xsl:stylesheet xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
-	<xsl:output method="text" disable-output-escaping="yes"/>
-	<xsl:variable name="nl">
-		<xsl:text>&#10;</xsl:text>
-	</xsl:variable>
-	<xsl:template match="weather">
-		<xsl:apply-templates select="cc"/>
-		<xsl:apply-templates select="dayf"/>
-		<xsl:comment>PycWeather %s</xsl:comment>
-	</xsl:template>
-	<xsl:template match="cc">
-		<xsl:text>Location: </xsl:text><xsl:value-of select="obst"/><xsl:text> (</xsl:text><xsl:value-of select="../loc/lat"/><xsl:text>, </xsl:text><xsl:value-of select="../loc/lon"/><xsl:text>)</xsl:text><xsl:value-of select="$nl"/>
-		<xsl:text>Temperature: </xsl:text><xsl:value-of select="tmp"/>°<xsl:value-of select="../head/ut"/><xsl:value-of select="$nl"/>
-		<xsl:if test="tmp != flik">
-			<xsl:text>Windchill: </xsl:text><xsl:value-of select="flik"/>°<xsl:value-of select="../head/ut"/><xsl:value-of select="$nl"/>
-		</xsl:if>
-		<xsl:text>Conditions: </xsl:text><xsl:value-of select="t"/><xsl:value-of select="$nl"/>
-		<xsl:text>Wind: </xsl:text>
-		<xsl:choose>
-			<xsl:when test="wind/s = 'calm'">
-				<xsl:text>0</xsl:text>
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:value-of select="wind/s"/>
-			</xsl:otherwise>
-		</xsl:choose>
-		<xsl:value-of select="../head/us"/>
-		<xsl:text> (</xsl:text><xsl:value-of select="wind/t"/><xsl:text>)</xsl:text>
-	</xsl:template>
-	<!-- MULTIPLE DAYS DISPLAY -->
-	<xsl:template match="dayf">
-		<!-- don't repeat the first one -->
-		<xsl:apply-templates select="child::day[position() > 1]"/>
-	</xsl:template>
-	<xsl:template match="day">
-		<xsl:value-of select="$nl"/>
-		<xsl:value-of select="@dt"/><xsl:text>, </xsl:text><xsl:value-of select="@t"/>
-		<xsl:if test="@d = 1">
-			<xsl:text> (Tomorrow)</xsl:text>
-		</xsl:if>
-		<xsl:text>: </xsl:text>
-		<xsl:apply-templates select="part"/>
-	</xsl:template>
-	<xsl:template match="part">
-		<xsl:choose>
-			<xsl:when test="@p = 'd'">
-				<xsl:text>Day (</xsl:text>
-				<xsl:value-of select="../hi"/>°<xsl:value-of select="../../../head/ut"/>
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:text>Night (</xsl:text>
-				<xsl:value-of select="../low"/>°<xsl:value-of select="../../../head/ut"/>
-			</xsl:otherwise>
-		</xsl:choose>
-		<xsl:text>, </xsl:text>
-		<xsl:apply-templates select="t"/>
-		<xsl:text>)</xsl:text>
-		<xsl:if test="@p = 'd'">
-			<xsl:text>; </xsl:text>
-		</xsl:if>
-	</xsl:template>
-</xsl:stylesheet>""" % __version__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pycweather/weather.py	Mon Jul 27 00:02:10 2009 +0400
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of PycWeather
+#
+# Copyright (c) 2009 Vlad Glagolev <enqlave@gmail.com>
+# All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+""" pycweather/weather.py: Weather class """
+
+from cStringIO import StringIO
+from urllib2 import urlopen
+
+from lxml.etree import parse, tostring, fromstring, XMLSyntaxError
+
+from pycweather import __version__
+
+
+# correct url to the XOAP service
+XOAP_URL = "http://xoap.weather.com/"
+
+
+class Weather:
+
+    def __init__(self):
+        self.xsl = None
+        self.id = None
+        self.key = None
+
+    def auth(self, credentials):
+        try:
+            self.id, self.key = credentials.split(":")
+        except:
+            print "Invalid credentials"
+
+    def search(self, location):
+        data = urlopen(XOAP_URL + "search/search?where=%s" % location)
+
+        tree = data.read()
+
+        try:
+            xml = fromstring(tree)
+        except XMLSyntaxError:
+            print "XML syntax error occured while parsing content: ", tree
+
+            return -1
+
+        if not xml.getchildren():
+            print "No location has been found!"
+        elif xml.tag == "error":
+            print "Error: %s" % xml.getchildren()[0].text
+        else:
+            print "Code    | Location\n--------+----------"
+            for loc in xml.xpath("loc"):
+                print loc.get("id") + ": " + loc.text
+
+            print "--\nTo catch weather information use: pycweather -c <code>"
+
+    def load(self, xsl_file):
+        try:
+            self.xsl = parse(xsl_file)
+        except XMLSyntaxError:
+            print "XML syntax error occured while parsing XSL stylesheet"
+        except:
+            print "Unable to read XSL file"
+
+    def preview(self, code, days, unit):
+        try:
+            data = urlopen(XOAP_URL + \
+                   "weather/local/%s?cc=*&dayf=%d&unit=%s&par=%s&key=%s" % \
+                   (code, days, unit, self.id, self.key))
+        except:
+            print "Unable to connect to %s" % XOAP_URL
+
+            return -1
+
+        tree = data.read()
+
+        try:
+            xml = fromstring(tree)
+        except XMLSyntaxError:
+            print "XML syntax error occured while parsing content: ", tree
+
+            return -1
+
+        if xml.tag == "error":
+            print "Error: %s" % xml.xpath("err")[0].text
+
+            return -1
+        else:
+            document = parse(StringIO(tostring(xml)))
+
+        print document.xslt(self.xsl)
--- a/setup.py	Thu Nov 06 23:02:41 2008 +0300
+++ b/setup.py	Mon Jul 27 00:02:10 2009 +0400
@@ -3,7 +3,8 @@
 #
 # This file is part of PycWeather
 #
-# Copyright (c) 2008 Vlad Glagolev <enqlave@gmail.com>. All rights reserved.
+# Copyright (c) 2008-2009 Vlad Glagolev <enqlave@gmail.com>
+# All rights reserved.
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -32,6 +33,7 @@
     author_email = "enqlave@gmail.com",
     packages = ["pycweather"],
     scripts = ["bin/pycweather"],
+    data_files = [('share/pycweather', ["share/template.xsl"])],
     description = "Weather display manager for conky",
     platforms = ["Linux", "Unix"],
     long_description = "PycWeather is pure-pythonic weather display manager \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/template.xsl	Mon Jul 27 00:02:10 2009 +0400
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- pycweather/template.xsl: XSL stylesheet for displaying weather
+
+This file is part of PycWeather
+
+Copyright (c) 2009 Vlad Glagolev <enqlave@gmail.com>. All rights reserved.
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-->
+<xsl:stylesheet xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+	<xsl:output method="text" disable-output-escaping="yes"/>
+	<xsl:variable name="nl">
+		<xsl:text>&#10;</xsl:text>
+	</xsl:variable>
+	<xsl:template match="weather">
+		<xsl:apply-templates select="cc"/>
+		<xsl:apply-templates select="dayf"/>
+		<xsl:comment>PycWeather</xsl:comment>
+	</xsl:template>
+	<xsl:template match="cc">
+		<xsl:text>Location: </xsl:text><xsl:value-of select="obst"/><xsl:text> (</xsl:text><xsl:value-of select="../loc/lat"/><xsl:text>, </xsl:text><xsl:value-of select="../loc/lon"/><xsl:text>)</xsl:text><xsl:value-of select="$nl"/>
+		<xsl:text>Temperature: </xsl:text><xsl:value-of select="tmp"/>°<xsl:value-of select="../head/ut"/><xsl:value-of select="$nl"/>
+		<xsl:if test="tmp != flik">
+			<xsl:text>Windchill: </xsl:text><xsl:value-of select="flik"/>°<xsl:value-of select="../head/ut"/><xsl:value-of select="$nl"/>
+		</xsl:if>
+		<xsl:text>Conditions: </xsl:text><xsl:value-of select="t"/><xsl:value-of select="$nl"/>
+		<xsl:text>Wind: </xsl:text>
+		<xsl:choose>
+			<xsl:when test="wind/s = 'calm'">
+				<xsl:text>0</xsl:text>
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:value-of select="wind/s"/>
+			</xsl:otherwise>
+		</xsl:choose>
+		<xsl:value-of select="../head/us"/>
+		<xsl:text> (</xsl:text><xsl:value-of select="wind/t"/><xsl:text>)</xsl:text>
+	</xsl:template>
+	<!-- MULTIPLE DAYS DISPLAY -->
+	<xsl:template match="dayf">
+		<!-- don't repeat the first one -->
+		<xsl:apply-templates select="child::day[position() > 1]"/>
+	</xsl:template>
+	<xsl:template match="day">
+		<xsl:value-of select="$nl"/>
+		<xsl:value-of select="@dt"/><xsl:text>, </xsl:text><xsl:value-of select="@t"/>
+		<xsl:if test="@d = 1">
+			<xsl:text> (Tomorrow)</xsl:text>
+		</xsl:if>
+		<xsl:text>: </xsl:text>
+		<xsl:apply-templates select="part"/>
+	</xsl:template>
+	<xsl:template match="part">
+		<xsl:choose>
+			<xsl:when test="@p = 'd'">
+				<xsl:text>Day (</xsl:text>
+				<xsl:value-of select="../hi"/>°<xsl:value-of select="../../../head/ut"/>
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:text>Night (</xsl:text>
+				<xsl:value-of select="../low"/>°<xsl:value-of select="../../../head/ut"/>
+			</xsl:otherwise>
+		</xsl:choose>
+		<xsl:text>, </xsl:text>
+		<xsl:apply-templates select="t"/>
+		<xsl:text>)</xsl:text>
+		<xsl:if test="@p = 'd'">
+			<xsl:text>; </xsl:text>
+		</xsl:if>
+	</xsl:template>
+</xsl:stylesheet>