Al Adkins
Al Adkins

Reputation: 31

Yahoo Weather API 2019 - TypeError/AttributeError

Want to run Yahoo 2019 Weather API on Raspberry Pi in Python 3.5.3.
Verified Yahoo access codes by successfully running Yahoo sample code for 2.7.10.

All the sample code is from: https://gist.github.com/VerizonMediaOwner/e6be950f74c5a8071329f1d9a50e3158#file-weather_ydn_sample-py

Ran 2to3 conversion and received the following script TypeError indicated:

#Weather API Python sample code**
#Copyright 2019 Oath Inc. Licensed under the terms of the zLib license see
#https://opensource.org/licenses/Zlib for terms.**
#$ python --version**
#Python 2.7.10 - AFTER 2TO 3 CONVERSION**

import time, uuid, urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse
import hmac, hashlib
from base64 import b64encode

#Basic info

url = 'https://weather-ydn-yql.media.yahoo.com/forecastrss'
method = 'GET'
app_id = 'XXX'
consumer_key = 'XXX'
consumer_secret = 'XXX'
concat = '&'
query = {'location': 'sunnyvale,ca', 'format': 'json'}
oauth = {
    'oauth_consumer_key': consumer_key,
    'oauth_nonce': uuid.uuid4().hex,
    'oauth_signature_method': 'HMAC-SHA1',
    'oauth_timestamp': str(int(time.time())),
    'oauth_version': '1.0'
}

#Prepare signature string (merge all params and SORT them)

merged_params = query.copy()
merged_params.update(oauth)
sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
signature_base_str =  method + concat + urllib.parse.quote(url, safe='') + concat + urllib.parse.quote(concat.join(sorted_params), safe='')

#Generate signature

composite_key = urllib.parse.quote(consumer_secret, safe='') + concat
oauth_signature = b64encode(hmac.new(composite_key, signature_base_str, hashlib.sha1).digest())

#Prepare Authorization header

oauth['oauth_signature'] = oauth_signature
auth_header = 'OAuth ' + ', '.join(['{}="{}"'.format(k,v) for k,v in oauth.items()])

#Send request

url = url + '?' + urllib.parse.urlencode(query)
request = urllib.request.Request(url)
request.add_header('Authorization', auth_header)
request.add_header('X-Yahoo-App-Id', app_id)
response = urllib.request.urlopen(request).read()
print(response)

ERROR:
pi@raspberrypi:~/Weather $ python3 yahoo2TO3.py
Traceback (most recent call last):
  File "yahoo2.py", line 41, in <module>
    oauth_signature = b64encode(hmac.new(composite_key, signature_base_str, hashlib.sha1).digest())
  File "/usr/lib/python3.5/hmac.py", line 144, in new
    return HMAC(key, msg, digestmod)
  File "/usr/lib/python3.5/hmac.py", line 42, in __init__
    raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
TypeError: key: expected bytes or bytearray, but got 'str'

Tried the 3.7 code sample and received AttributeError:

#Weather API Python sample code
#Copyright 2019 Oath Inc. Licensed under the terms of the zLib license see #https://opensource.org/licenses/Zlib for terms.
#$ python --version
#Python 3.7.x

import time, uuid, urllib, json
import hmac, hashlib
from base64 import b64encode

#Basic info

app_id = 'XXX'
consumer_key = 'XXX'
consumer_secret = 'XXX'
query = {'location': 'macau,mo', 'format': 'json', 'u': 'c'}

url = 'https://weather-ydn-yql.media.yahoo.com/forecastrss'
method = 'GET'
concat = '&'
oauth = {
'oauth_consumer_key': consumer_key,
'oauth_nonce': uuid.uuid4().hex,
'oauth_signature_method': 'HMAC-SHA1',
'oauth_timestamp': str(int(time.time())),
'oauth_version': '1.0'
}

#Prepare signature string (merge all params and SORT them)

merged_params = query.copy()
merged_params.update(oauth)
sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
signature_base_str = method + concat + urllib.parse.quote(url, safe='') + concat + urllib.parse.quote(concat.join(sorted_params), safe='')

#Generate signature

composite_key = urllib.parse.quote(consumer_secret, safe='') + concat
oauth_signature = b64encode(hmac.new(composite_key.encode('utf-8'), signature_base_str.encode('utf-8'), hashlib.sha1).digest())
#Prepare Authorization header

oauth['oauth_signature'] = oauth_signature.decode('utf-8')
auth_header = 'OAuth ' + ', '.join(['{}="{}"'.format(k,v) for k,v in oauth.items()])
#Send request

url = url + '?' + urllib.parse.urlencode(query)
request = urllib.request.Request(url)
request.headers['Authorization'] = auth_header
request.headers['X-Yahoo-App-Id']= app_id
response = urllib.request.urlopen(request).read()
print(response)

ERROR:
pi@raspberrypi:~/Weather3 $ python3 yahoo3.py
Traceback (most recent call last):
  File "yahoo3.py", line 34, in <module>
    sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
  File "yahoo3.py", line 34, in <listcomp>
    sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
AttributeError: module 'urllib' has no attribute 'parse'

Request assistance to run one or the other in 3.5.

Upvotes: 1

Views: 496

Answers (1)

Al Adkins
Al Adkins

Reputation: 31

RESOLVED: In the sample code for Python 3.7 change the header import urllib to import urllib.request. After this change it works just fine using Raspberry Pi Python 3.5.3.

Upvotes: 2

Related Questions