Musings of a dad with too much time on his hands and not enough to do. Wait. Reverse that.

Month: May 2021

The Last Odyssey

I switched to ebooks several years ago, finding it quite convenient to pack my ebook reader with hundreds of tomes that I tote around with me to school parking lots while I wait for my kids to finish their practices, haircut establishments while I await my turn, the DMV while I wait…forever, etc. Nevertheless, I still have a backlog of physical books spread throughout the house and occasionally pick one up to read in-between electronic ones.

One of these I read recently was James Rollins’s The Last Odyssey. The Last Odyssey is a fast-paced, modern day adventure that pits a secret, U.S. government special operations team against the stereotypical bad people bent on sending humanity into the dark ages.

The thread that most endeared me to the novel was the interweaving of historical texts and mysteries–especially Homer’s The Odyssey–into the fabric of the story. I find it reminiscent of Umberto Eco’s Foucault’s Pendulum or Dan Brown’s Da Vinci Code. Or maybe National Treasure, if you’re not the reading type. The villians and protagonists are out to retrace Odysseus’s 10 year trek home, which turns out to be more true than myth (thanks to much literary license). What awaits at the end of the trek could spell doom for the masses in the hands of the wrong people.

If you’re like me, you’ll want to read the author’s notes at the end where he enumerates all the books and events from which he drew inspiration. I’ve already added several of these to my watchlist.

So, if you need a break from your daily grind, The Last Odyssey will entertain you without overly taxing your exhausted prefrontal cortex.

Python and SOAP

Simple Object Access Protocol, or SOAP, was the new hotness in web service technology…some 15 or 20 years ago. It was built around XML, Web Service Definition Language (WSDL), XML namespaces and other complex ideas.

Today’s web service standard is Representational state transfer (REST)–a much simpler approach to data transmission over the web. Instead of trading around clunky XML files, REST APIs typically leverage sleeker JSON (JavaScript Object Notation) documents in their communication.

But some things never die and, recently, I found myself elbow-deep into a number of SOAP APIs while trying to pull data from a vendor product. I wrote a Python client to interface with those APIs. While Python has a number of packages designed to work with the technology, I wanted to stick with just the requests package to keep my dependencies minimal. Ultimately, my client worked well and I wanted to share a few tidbits here that I learned along the way to get my requests code to successfully call SOAP web services.

1. The header can be tricky

Getting your header right is critical to successful service calls. I found two header elements essential for my code: SOAPAction and Content-Type. It was important that I set SOAPAction to a url corresponding with the particular web method I wished to call. The vendor documentation was pretty important here to determine what that url should be.

What’s interesting about Content-Type is that the web is full of valid suggestions for the proper value: text/xml and application/soap+xml are two that I’ve seen bandied about. In my case, neither value worked. Again from the vendor documentation, the value that made my calls work was application/x-www-form-urlencoded. So, my header dictionary looked roughly like this:

headers = {'SOAPAction': 'http://somesite.com/webservices/SomeMethod', 'Content-Type': 'application/x-www-form-urlencoded'}

2. The post data doesn’t necessarily need to be XML

Crazy notion, right? Posting non-XML to a SOAP API? Early on in my work, I kept trying to format all my post arguments into a single XML document and tried to push that document to the web method with my requests call, but the code would never work. At some point, I stumbled upon a forum or discussion thread where one of the participants posted code that actually used a dictionary for his post data object–what you would normally do with a REST API. I was taken aback but gave it a go and, to my astonishment, it worked! Some web methods required simple parameters like strings and integers, ready made for Python dictionaries. A few did have a parameter or two of XML. For those, I simply had to push a string representation of a properly formatted XML document. My code looked something like this:

import requests

str_xml = '<some_doc><some_elem>1</some_elem></some_doc>'
post_data = {'token': 'blah', 'search_xml': str_xml}
ws_url = 'https://somesite.com/ws/something.asmx/SomeMethod'
resp = requests.post(ws_url, data=post_data, headers=headers)

3. Parsing the XML response can be tricky

I “believe” the most appropriate way to deal with XML responses in the response object is through the content property. But, since the response is supposed to be XML, I wanted to run the content through ElementTree to get a proper XML document I could more easily process. In my early attempts, I passed the content value to ElementTree’s fromstring function to get back a proper XML document that I can process like any other XML document. Or so I thought.

The rub is that fromstring returns an XML element, not an XML document. You have to add one more line, a call to the ElementTree constructor itself, you get the proper XML document object you can use in the rest of your code. My response processing code then looked like this:

import xml.etree.ElementTree as ET


resp = requests.post(ws_url, data=post_data, headers=headers)

resp_elem = ET.fromstring(resp.content)
resp_doc = ET.ElementTree(resp_elem)

# now, you can use functions like find and findall with the resp_doc object

So, the next time you find yourself having to work with SOAP APIs–and hopefully you don’t–there are some handy tips and tricks to consider.

Learning Guitar with Python, Part 3

Past posts in this sorta-series: Part 1 and Part 2.

Pentatonic scales are quite popular among guitar players. If you’re rusty on your Greek, “Penta” means “five”. Thus, these scales only have five notes instead of seven–the fourth and seventh notes are dropped from their modal counterparts.

The major and minor pentatonic scales that I learned are truncated versions of the Ionian and Aeolian modal scales, respectively. My guitar teacher also showed me a longer form of both the major and minor pentatonic scales: scales that traverse more frets than the normal four-fret span. Furthermore, the long-form minor scale includes a feature called “The House,” where the notes on the fretboard resemble a house:

Bad rendering of how notes in the minor pentatonic scale resemble a house

“The House” is, apparently, a popular shape used by lots of famous guitar players.

To help me learn these scales, as I have with previous scales, I coded them up in Python in a Jupyter notebook and displayed them in HTML. Here’s the code I wrote:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display_html

%matplotlib inline

major_pentatonic = {'Low E':['','1','','2'], 'A':['3','','','5'], 'D':['6','','','1'], 'G':['2','','3',''], 
                    'B':['','5','','6'], 'High E':['','1','','2']}
minor_pentatonic = {'Low E':['6','','','1'], 'A':['2','','3',''], 'D':['5','','6',''], 'G':['1','','2',''], 
                    'B':['3','','','5'], 'High E':['6','','','1']}
major_pent_long = {'Low E':['1','','2','','3','','',''], 'A':['','','5','','6','','',''], 
                   'D':['','','1','','2','','3',''], 'G':['','','','','5','','6',''], 
                   'B':['','','','','','1','','2'], 'High E':['','','','','3','','','5']}
minor_pent_long = {'Low E':['5','','6','','','','',''], 'A':['1','','2','','3','','',''], 
                   'D':['','','5','','6','','',''], 'G':['','','1','','2','','3',''], 
                   'B':['','','','','','5','','6'], 'High E':['','','','','','1','','2']}

pent_scales = {'Major Pentatonic':major_pentatonic, 'Minor Pentatonic':minor_pentatonic, 
               'Major Pentatonic (Long)':major_pent_long, 'Minor Pentatonic (The House)': minor_pent_long}
pent_html = '<h3>Pentatonic Scale Shapes</h3>'

for i, scale_name in enumerate(pent_scales):
    nbr_of_frets = len(pent_scales[scale_name]['Low E'])
    df_scale = pd.DataFrame(pent_scales[scale_name], index=np.arange(1, nbr_of_frets+1))
    # https://stackoverflow.com/a/50899244
    df_scale_styler = df_scale.style.set_table_attributes("style='display:inline'").set_caption(scale_name)
    pent_html += df_scale_styler._repr_html_() + '&nbsp;&nbsp;&nbsp;'
    if (i+1) % 2 == 0:
        pent_html += '<p></p>'

display_html(pent_html, raw=True)

And that code rendered this graphic:

Pentatonic scales rendered in a Jupyter notebook

So now I can show my notebook in a computer monitor and play along to the scale.

More to come!

© 2024 DadOverflow.com

Theme by Anders NorenUp ↑