Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updates for py3.8 compatibility #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ utility for fetching the forecast.
Requires
========

* Python 2.6+
* argparse (if Python < 2.7)
* Python 3.5+
* argparse
* dateutils
* configparser


Command-Line Usage
Expand Down
28 changes: 14 additions & 14 deletions bin/noaa
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Database (NDFD).
"""

import argparse
import ConfigParser
import configparser as configparser # update to match package name change
import os
import sys

Expand Down Expand Up @@ -101,23 +101,23 @@ def format_conditions(conditions, padding=30, color=True):
def config_get_boolean(config, section, option, default=None):
try:
value = config.getboolean(section, option)
except ConfigParser.NoSectionError:
except configparser.NoSectionError:
value = default
except ConfigParser.NoOptionError:
except configparser.NoOptionError:
value = default

return value


def make_parser():
config = ConfigParser.ConfigParser()
config = configparser.ConfigParser()
config.read(os.path.expanduser("~/.noaarc"))

try:
default_location = config.get('default', 'location').split()
except ConfigParser.NoSectionError:
except configparser.NoSectionError:
default_location = None
except ConfigParser.NoOptionError:
except configparser.NoOptionError:
default_location = None

default_metric = config_get_boolean(
Expand Down Expand Up @@ -220,14 +220,14 @@ def main():
pretty_location, fcast = forecast_func(args)

if args.heading:
print "Forecast for %s" % pretty_location

for datapoint in fcast:
print datapoint.date.strftime('%a'),
print format_conditions(datapoint.conditions, color=args.color),
print format_temp(datapoint.min_temp, color=args.color),
print format_temp(datapoint.max_temp, color=args.color),
print simple_temp_graph(datapoint.max_temp, color=args.color)
print("Forecast for %s" % pretty_location)

for datapoint in fcast: # some updates for py3.8 compatibility
print(datapoint.date.strftime('%a'))
print(format_conditions(datapoint.conditions, color=args.color))
print(format_temp(datapoint.min_temp, color=args.color))
print(format_temp(datapoint.max_temp, color=args.color))
print(simple_temp_graph(datapoint.max_temp, color=args.color))


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion noaa/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
Python bindings to the NOAA National Digital Forecast Database (NDFD)
"""

__version__ = "0.2.1"
__version__ = "0.2.2"
27 changes: 14 additions & 13 deletions noaa/forecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@
from noaa import utils


def daily_forecast_by_zip_code(zip_code, start_date=None, num_days=6,
metric=False):
def daily_forecast_by_zip_code(zip_code, start_date=None, num_days=6, metric=False):
"""Return a daily forecast by zip code.

:param zip_code:
:param start_date:
:param num_days:
:param metric:
:returns: [ForecastedCondition() ...]
"""
location_info = [("zipCodeList", zip_code)]
client = "NDFDgenByDayMultiZipCode" # pulled from the details of the API
return _daily_forecast_from_location_info(
location_info, start_date=start_date, num_days=num_days,
location_info, client, start_date=start_date, num_days=num_days,
metric=metric)


Expand All @@ -29,21 +30,23 @@ def daily_forecast_by_lat_lon(lat, lon, start_date=None, num_days=6,
:param lon:
:param start_date:
:param num_days:
:param metric:
:returns: [ForecastedCondition() ...]
"""
location_info = [("lat", lat), ("lon", lon)]
client = "NDFDgenByDay" # pulled from the details of the API
return _daily_forecast_from_location_info(
location_info, start_date=start_date, num_days=num_days,
location_info, client, start_date=start_date, num_days=num_days,
metric=metric)


def daily_forecast_by_location(location, start_date=None, num_days=6,
metric=False):
def daily_forecast_by_location(location, start_date=None, num_days=6, metric=False):
"""Return a daily forecast by location.

:param location: A location string that will be geocoded (ex. "Austin")
:param start_date:
:param num_days:
:param metric:
:returns: [ForecastedCondition() ...]
"""
loc = geocode.geocode_location(location)
Expand Down Expand Up @@ -110,21 +113,19 @@ def _parse_conditions(tree):
return time_layout_key, values


def _daily_forecast_from_location_info(location_info, start_date=None,
num_days=6, metric=False):
def _daily_forecast_from_location_info(location_info, client, start_date=None, num_days=6, metric=False):
if not start_date:
start_date = datetime.date.today()

# NOTE: the order of the query-string parameters seems to matter; so,
# we can't use a dictionary to hold the params
params = location_info + [("format", "24 hourly"),
params = [("whichClient", client)] + location_info + [("format", "24 hourly"), # update to match newest API
("startDate", start_date.strftime("%Y-%m-%d")),
("numDays", str(num_days)),
("Unit", "m" if metric else "e")]
("Unit", "m" if metric else "e"),
("Submit", "Submit")]

FORECAST_BY_DAY_URL = ("http://www.weather.gov/forecasts/xml"
"/sample_products/browser_interface"
"/ndfdBrowserClientByDay.php")
FORECAST_BY_DAY_URL="https://graphical.weather.gov/xml/sample_products/browser_interface/ndfdBrowserClientByDay.php"

resp = utils.open_url(FORECAST_BY_DAY_URL, params)
tree = utils.parse_xml(resp)
Expand Down
6 changes: 2 additions & 4 deletions noaa/geocode.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ def geocode_location(location, api_key=None):

For high-volume traffic, you will need to specify an API-key.
"""
GEOCODE_URL = "http://maps.google.com/maps/geo"
params = [('q', location),
('sensor', 'false'),
('output', 'json')]
GEOCODE_URL = "https://maps.googleapis.com/maps/api/geocode/json" # update to match new google API
params = ["latlng", location[0], location[1]]

if api_key:
params += [('key', api_key)]
Expand Down
2 changes: 1 addition & 1 deletion noaa/observation.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def station_observation_by_station_id(station_id):
and return the observation (if any) that has the data we want.
"""
STATION_OBSERVATIONS_URL = (
'http://www.weather.gov/data/current_obs/%s.xml' % station_id)
'https://w1.weather.gov/data/current_obs/%s.xml' % station_id) # updated to reflect new API

resp = noaa.utils.open_url(STATION_OBSERVATIONS_URL)
tree = noaa.utils.parse_xml(resp)
Expand Down
1 change: 0 additions & 1 deletion noaa/stations.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,4 @@ def _parse_stations(fileobj):
station = noaa.models.Station(station_id, location)

stations.append(station)

return stations
23 changes: 12 additions & 11 deletions noaa/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import sys
import urllib
from xml.etree import ElementTree as ET

import dateutil.parser
import urllib.request
from urllib.parse import urlencode, quote_plus
from dateutil import parser


def colorize(text, color):
Expand Down Expand Up @@ -38,22 +39,22 @@ def all_numbers(L):

def print_tree(tree, indent=4):
"""Print an ElementTree for debugging purposes."""
def print_elem(elem, level):
print " " * (indent * level),
print 'tag="%s"' % elem.tag,
print 'text="%s"' % elem.text.strip() if elem.text is not None else "",
print 'attrib=%s' % elem.attrib
def print_elem(elem, level): # some updates for py3.8 compatibility
print(" " * (indent * level))
print('tag="%s"' % elem.tag)
print('text="%s"' % elem.text.strip() if elem.text is not None else "")
print('attrib=%s' % elem.attrib)
for child in elem.getchildren():
print_elem(child, level + 1)
print_elem(tree.getroot(), 0)


def open_url(url, params=None):
if params:
query_string = urllib.urlencode(params)
query_string = urlencode(params, quote_via=quote_plus) # some updates for py3.8 compatibility
url = "?".join([url, query_string])

resp = urllib.urlopen(url)
resp = urllib.request.urlopen(url) # some updates for py3.8 compatibility
return resp


Expand All @@ -72,7 +73,7 @@ def die_on(*exception_classes, **kwargs):
try:
yield
except exception_classes as e:
print >> sys.stderr, msg_func(e)
print(msg_func(e)) # some updates for py3.8 compatibility
sys.exit(exit_code)


Expand All @@ -82,7 +83,7 @@ def parse_xml(fileobj):


def parse_dt(dt):
return dateutil.parser.parse(dt)
return parser.parse(dt)


def great_circle_distance(lat1, lon1, lat2, lon2, radius, angle_units="deg"):
Expand Down
1 change: 1 addition & 0 deletions tools/pip-requires
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
argparse
dateutils
pep8
configparser