Modifying our RSS to return values

As we are using our LoadRssFeed as a library module now, we will want to modify the end result to return an array we can use in our chart module that we will build shortly. We will return two counts both in an array, one for May and one for June.

Also, we will remove the print statement as we understand that it is working properly. So, remove the print line at the end of the LoadRssFeed, get_all_rss_dates function and replace it with return [month_count.count(5), month_count.count(6)]. This will allow us to return a single object but keep two values for our chart. Here's the implementation of the file:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import urllib2 
from xml.etree import ElementTree
import time

def get_all_rss_dates():

    '''create a global array to our function to save our month counts.'''
    month_count = []

    try: 
        '''Open the file via HTTP.'''
        response = urllib2.urlopen('http://www.packtpub.com/rss.xml') 
        tree = ElementTree.parse(response) 
        root = tree.getroot() 
    
        '''Array of post dates.'''
        news_post_date = root.findall("channel//pubDate") 
    
        '''Iterate in all our searched elements and print the inner text for each.''' 
        for date in news_post_date:
            '''Create a variable striping out commas, and generating a new array item for every space.'''
            datestr_array = date.text.replace(',', '').split(' ')
            
            '''Create a formatted string to match up with our strptime method.'''
            formatted_date = "{0} {1}, {2}, {3}".format(datestr_array[2], datestr_array[1], datestr_array[3], datestr_array[4])
            
            '''Parse a time object from our string.'''
            blog_datetime = time.strptime(formatted_date, "%b %d, %Y, %H:%M:%S")

            '''Add this date's month to our count array'''
            month_count.append(blog_datetime.tm_mon)
        
        '''Finally, close our open network.'''
        response.close()
    
    except Exception as e:
        '''If we have an issue show a message and alert the user.'''
        print(e)
    
    '''Return two counts for both months.'''
    return [month_count.count(5), month_count.count(6)]

Tip

Packt Publishing's website's RSS feed only accounts for the past two months of posts, so if you're reading this in October, for example, you would need to set the count to 10 for October and 9 for September for each month_count item.

Building our chart module

Next, let's create a new Python file to be our chart building library that uses pygal. We will name this file chart_build.py and add this in our project root along with our LoadRssFeed.py and main_chartbuild.py files.

Next, open the chart_build.py file and let's build a simple bar chart that shows the number of posts for the months of May and June. Like our LoadRssFeed module we built, we will wrap our chart code in a function with a parameter called dataarr, indicating a data array. Before we add our data to our chart, let's set up our chart configuration.

Building a portable configuration for our chart

In pygal, we typically create a chart, and inside it, we specify parameters to set settings for the chart and add our parameter values to the chart object that we call. The pygal library offers a way to modularize our configuration options.

This is helpful because in this example, we use only one chart but what if we had eight or twelve more charts to build? Having a portable configuration to set up the chart layout and theme can be very useful rather than rewriting the configuration each time.

Take a look at the following code. Here, I'm creating a Python class called ConfigChart, which has a parameter called Config that basically overrides the Config object in the chart we assign this to. Inside the class, I have a list of parameters that I can cleanly update and modify. Notice that I also import pygal, and using from pygal, I also import Config to work as a separate object:

import pygal
from pygal import Config

'''Creating our own class with values to pass in as parameters to our chart.'''
class ConfigChart(Config):
    show_legend = True
    human_readable = True
    fill = True
 '''explicit_size sets a fixed size to our width height            properties.'''
    explicit_size = True
    width = 860
    height = 640
    title= 'Posts per month on Packtpub.com'
    y_label = 'Posts'
    x_label = 'Month'
    y_title = 'Posts'
    x_title = 'Month'
    show_y_labels = True
    show_x_labels = True
    stroke = False
    tooltip_font_size = 42
    title_font_size = 24
 '''Always include an error message for any dynamic data.'''
    no_data_text = 'Unable to load data'

As you can see, I've added many of the values we discussed in Chapter 5, Tweaking pygal, and also ensured that our no_data_text parameter had a value in case of any connection issues. Also, as we want to render this in a browser, I've set the width and height as well as set a parameter called explicit_size to True to force the SVG output to a fixed size.

Setting up our chart for data

Now, let's finish setting up our chart to receive data in our chart_build.py file. Here, I've wrapped my pygal chart creation code in a function called generate_chart and added a parameter to handle our chart's data pulled from the RSS feed.

Here's the final code for the chart, including our ConfigChart class, applied to our chart object. Notice that for the add() methods for the chart, I simply added dataarr with an array index to specify the value for May and June, respectively:

import pygal
from pygal import Config

'''Creating our own class with values to pass in as parameters to our chart.'''
class ConfigChart(Config):
    show_legend = True
    human_readable = True
    fill = True
    '''explicit_size sets a fixed size to our width height properties.'''
    explicit_size = True
    width = 860
    height = 640
    title= 'Posts per month on Packtpub.com'
    y_label = 'Posts'
    x_label = 'Month'
    y_title = 'Posts'
    x_title = 'Month'
    show_y_labels = True
    show_x_labels = True
    stroke = False
    tooltip_font_size = 42
    title_font_size = 24
    '''Always include an error message for any dynamic data.'''
    no_data_text = 'Unable to load data'

'''Generate chart based on imported array, (with 2 values)'''
def generate_chart(dataarr):

    '''Initialize the chart with our ConfigChart class.'''
    mychart = pygal.Bar(ConfigChart())

    '''Add data to the chart for May and June.'''
    mychart.add('May', dataarr[0])
    mychart.add('June', dataarr[1])

    '''Launch our web browser with our SVG, (we can also render to file as well)'''
    mychart.render_in_browser()

Check our code in the LoadRssFeed.py file before running main_chartbuild.py. We made one change here; we changed the print exception to throw, an exception if we encounter a data connection issue in our try/catch block. If we were deploying this application publically, we would add a UI error for a consumer rather than an exception.

In this code, we've updated to return two values that we will pass into our chart:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import urllib2 
from xml.etree import ElementTree
import time

def get_all_rss_dates():
    '''create a global array to our function to save our month counts.'''
    month_count = []

    try:
        '''Open the file via HTTP. '''
        response = urllib2.urlopen('http://www.packtpub.com/rss.xml')
        tree = ElementTree.parse(response)
        root = tree.getroot()
    
        '''Array of post dates.'''
        news_post_date = root.findall("channel//pubDate")
    
        '''Iterate in all our searched elements and print the inner text for each. '''
        for date in news_post_date:
            '''Create a variable striping out commas, and generating a new array item for every space.'''
            datestr_array = date.text.replace(',', '').split(' ')
            
            '''Create a formatted string to match up with our strptime method.'''
            formatted_date = "{0} {1}, {2}, {3}".format(datestr_array[2], datestr_array[1], datestr_array[3], datestr_array[4])
            
            '''Parse a time object from our string.'''
            blog_datetime = time.strptime(formatted_date, "%b %d, %Y, %H:%M:%S")

            '''Add this date's month to our count array'''
            month_count.append(blog_datetime.tm_mon)
        
        '''Finally, close our open network. '''
        response.close()
    
    except Exception as e:
        '''If we have an issue show a message and alert the user.'''
        throw
    
    #Return two counts for both months.
    return [month_count.count(5), month_count.count(6)]

Configuring our main function to pass data

One more task to do is set up our main function, which is our main_chartbuild.py, which is called when our script is executed. As our LoadRssFeed module returns an array that we pass into our chart, we will call the generate_chart() method from our chart module that we build and pass in the result, as shown in the following code:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import LoadRssFeed, chart_build

#Call our 'LoadRssFeed' function.
chart_build.generate_chart(LoadRssFeed.get_all_rss_dates())

Let's run our main_chartbuild.py file and take a look at the results:

Configuring our main function to pass data
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.102.166