-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e8fa749
commit 1063066
Showing
10 changed files
with
710 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
from datetime import datetime | ||
import requests | ||
from voluptuous import Schema, Required, All, Any, Length, Range | ||
|
||
|
||
class ISS: | ||
""" | ||
""" | ||
|
||
API_URL = "http://api.open-notify.org/" | ||
API_CURRENT_LOCATION = "iss-now.json" | ||
API_PASS_TIMES = "iss-pass.json" | ||
API_PEOPLE = "astros.json" | ||
|
||
def __init__(self): | ||
return | ||
|
||
def people_in_space(self): | ||
""" | ||
:return: Return a dict with number of people in space right now and | ||
their name and their craft | ||
:rtype: dict | ||
""" | ||
data = requests.get(self.API_URL + self.API_PEOPLE) | ||
|
||
if data.status_code is 200: | ||
return data.json() | ||
else: | ||
raise Exception("Error server n {}".format( | ||
data.status_code)) | ||
|
||
def current_location(self): | ||
""" | ||
:return: A dict with latitude and longitude of ISS | ||
:rtype: dict | ||
""" | ||
data = requests.get(self.API_URL + self.API_CURRENT_LOCATION) | ||
|
||
if data.status_code is 200: | ||
return data.json()['iss_position'] | ||
else: | ||
raise Exception("Error server n {}".format( | ||
data.status_code)) | ||
|
||
def pass_times(self, latitude, longitude, altitude=None, number=None): | ||
""" | ||
:param latitude: latitude in degrees of location you want iss pass | ||
above | ||
:type latitude: float | ||
:param longitude: longitude in degrees of location you want iss pass | ||
above | ||
:type longitude: float | ||
:param altitude: altitude in meters of location you want iss pass | ||
above, default is 100 when not given | ||
:type altitude: float | ||
:param number: number of next pass above the location, default is 5 | ||
if not given. Min is 1, max is 100 | ||
:type number: int | ||
:return: a list of the next pass of the ISS with the risetime and | ||
the duration | ||
:rtype: list | ||
""" | ||
|
||
# Check input | ||
schema = Schema({ | ||
Required('lat'): All(Any(int, float), Range(min=-80, max=80)), | ||
Required('long'): All(Any(int, float), Range(min=-180, max=180)), | ||
'alt': Any(None, All(Any(int, float), Range(min=0, max=10000))), | ||
'number': Any(None, All(int, Range(min=1, max=100))) | ||
}) | ||
schema({'lat' : latitude, 'long': longitude, 'alt' : altitude, 'number': number}) | ||
|
||
#Build request | ||
payload = {'lat': latitude, 'lon': longitude} | ||
|
||
if altitude is not None: | ||
payload['alt'] = altitude | ||
|
||
if number is not None: | ||
payload['n'] = number | ||
|
||
data = requests.get(self.API_URL + self.API_PASS_TIMES, | ||
params=payload) | ||
|
||
#Check error | ||
if data.status_code is 200: | ||
return data.json()['response'] | ||
else: | ||
raise Exception("Error server n {}".format( | ||
data.status_code)) | ||
|
||
def number_of_people_in_space(self): | ||
""" | ||
:return: The number of people in space right now | ||
:rtype: int | ||
""" | ||
return self.people_in_space()['number'] | ||
|
||
def next_rise(self, latitude, longitude, altitude=None): | ||
""" | ||
:param latitude: latitude in degrees of location you want iss pass | ||
above | ||
:type latitude: float | ||
:param longitude: longitude in degrees of location you want iss pass | ||
above | ||
:type longitude: float | ||
:param altitude: altitude in meters of location you want iss pass | ||
above, default is 100 when not given | ||
:type altitude: float | ||
:return: Return the next date when ISS will be over 10 degree above the | ||
horizon | ||
:rtype: datetime | ||
""" | ||
rise = self.pass_times(latitude, longitude, altitude, | ||
2) | ||
timestamp = rise[0]['risetime'] | ||
|
||
return datetime.fromtimestamp(timestamp) | ||
|
||
def is_ISS_above(self, latitude, longitude, altitude=None): | ||
""" | ||
:param latitude: latitude in degrees of location you want iss pass | ||
above | ||
:type latitude: float | ||
:param longitude: longitude in degrees of location you want iss pass | ||
above | ||
:type longitude: float | ||
:param altitude: altitude in meters of location you want iss pass | ||
above, default is 100 when not given | ||
:type altitude: float | ||
:return: True if the ISS is above the location, False if not | ||
:rtype: bool | ||
""" | ||
test = self.pass_times(latitude, longitude, altitude, 2) | ||
# 2 results where asked so if API return only 1, that mean ISS is | ||
# above the location | ||
return len(test) is 1 | ||
|
||
|
||
if __name__ == '__main__': | ||
iss = ISS() | ||
# print (type(iss.people_in_space())) | ||
# print(iss.current_location()) | ||
# print (type(iss.pass_times(5, 8))) | ||
#print(iss.pass_times(1,1)) | ||
# print (iss.number_of_people_in_space()) | ||
# print (iss.seconds_before_next_rise(-50.2322, 76.5668)) | ||
# print (iss.is_ISS_above(4,71,7 )) | ||
print(iss.next_rise(2, 5, 6).timestamp()) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
from unittest import TestCase | ||
from httmock import all_requests, HTTMock, response | ||
import pyiss | ||
|
||
|
||
class TestCurrent_location(TestCase): | ||
def setUp(self): | ||
""" | ||
Instantiate the Http Request Mock, the ISS class call and the json response | ||
""" | ||
|
||
#Json response | ||
self.json_current_location = {"timestamp": 1481410143, "message": "success", "iss_position": {"latitude": "6.8272", "longitude": "-160.2689"}} | ||
|
||
#HTTP Mock | ||
@all_requests | ||
def correct_response(url, request): | ||
headers = {'content-type': 'application/json', | ||
'Set-Cookie': 'foo=bar;'} | ||
return response(200, self.json_current_location, headers, None, 5, | ||
request) | ||
self.http_correct = correct_response | ||
|
||
@all_requests | ||
def wrong_response(url, request): | ||
headers = {'content-type': 'application/json', | ||
'Set-Cookie': 'foo=bar;'} | ||
return response(403, self.json_current_location, headers, None, 5, | ||
request) | ||
self.http_wrong = wrong_response | ||
|
||
self.iss = pyiss.ISS() | ||
|
||
def test_current_location_json_return(self): | ||
""" | ||
Test that the function return the right dict answer | ||
""" | ||
with HTTMock(self.http_correct): | ||
response = self.iss.current_location() | ||
location = {"latitude": "6.8272", "longitude": "-160.2689"} | ||
self.assertDictEqual(response, location) | ||
|
||
def test_current_location_error_server(self): | ||
""" | ||
Test that the function raise an exception if the server response is not correct | ||
""" | ||
with HTTMock(self.http_wrong): | ||
self.assertRaises(Exception, self.iss.current_location ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
from unittest import TestCase | ||
from httmock import all_requests, HTTMock, response | ||
import pyiss | ||
|
||
|
||
class TestIs_ISS_above(TestCase): | ||
def setUp(self): | ||
""" | ||
Instantiate the Http Request Mock, the ISS class call and the json response | ||
""" | ||
|
||
# Json response | ||
self.json_is_ISS_above_false = { | ||
"message": "success", | ||
"request": { | ||
"altitude": 100, | ||
"datetime": 1481418788, | ||
"latitude": 15.0, | ||
"longitude": 20.0, | ||
"passes": 5 | ||
}, | ||
"response": [ | ||
{ | ||
"duration": 348, | ||
"risetime": 1481448840 | ||
}, | ||
{ | ||
"duration": 634, | ||
"risetime": 1481454465 | ||
} | ||
] | ||
} | ||
|
||
self.json_is_ISS_above_true = { | ||
"message": "success", | ||
"request": { | ||
"altitude": 100, | ||
"datetime": 1481418788, | ||
"latitude": 15.0, | ||
"longitude": 20.0, | ||
"passes": 5 | ||
}, | ||
"response": [ | ||
{ | ||
"duration": 348, | ||
"risetime": 1481448840 | ||
} | ||
] | ||
} | ||
|
||
# HTTP Mock | ||
@all_requests | ||
def true_response(url, request): | ||
headers = {'content-type': 'application/json', | ||
'Set-Cookie': 'foo=bar;'} | ||
return response(200, self.json_is_ISS_above_true, headers, None, 5, | ||
request) | ||
|
||
self.http_true = true_response | ||
|
||
@all_requests | ||
def false_response(url, request): | ||
headers = {'content-type': 'application/json', | ||
'Set-Cookie': 'foo=bar;'} | ||
return response(200, self.json_is_ISS_above_false, headers, None, | ||
5, | ||
request) | ||
|
||
self.http_false = false_response | ||
|
||
@all_requests | ||
def wrong_response(url, request): | ||
headers = {'content-type': 'application/json', | ||
'Set-Cookie': 'foo=bar;'} | ||
return response(403, self.json_is_ISS_above, headers, None, 5, | ||
request) | ||
|
||
self.http_wrong = wrong_response | ||
|
||
self.iss = pyiss.ISS() | ||
|
||
def test_is_ISS_above_true(self): | ||
""" | ||
Test that json match a true answer | ||
""" | ||
with HTTMock(self.http_true): | ||
response = self.iss.is_ISS_above(20, 15) | ||
|
||
self.assertTrue(response) | ||
|
||
def test_is_ISS_above_false(self): | ||
""" | ||
Test that json match a false answer | ||
""" | ||
with HTTMock(self.http_false): | ||
response = self.iss.is_ISS_above(20, 15) | ||
|
||
self.assertFalse(response) | ||
|
||
def test_is_ISS_above_error_server(self): | ||
""" | ||
Test that the function raise an exception if the server response is not correct | ||
""" | ||
with HTTMock(self.http_wrong): | ||
self.assertRaises(Exception, self.iss.is_ISS_above, 15, 20) | ||
|
||
def test_is_ISS_above_input_bound(self): | ||
""" | ||
Test that input raise exception using voluptuous | ||
Each set of data test a boundary | ||
""" | ||
with HTTMock(self.http_true): | ||
data = [[-80.1, 1, 1], [80.1, 1, 1], [1, -180.1, 1], | ||
[1, 180.1, 1], [1, 1, -1], [1, 1, 10000.1]] | ||
for value in data: | ||
self.assertRaises(Exception, self.iss.is_ISS_above, value[0], | ||
value[1], value[2]) | ||
|
||
data = [[-80, 1, 1], [80, 1, 1], [1, -180, 1], | ||
[1, 180, 1], [1, 1, 0], [1, 1, 10000]] | ||
for value in data: | ||
self.assertTrue(self.iss.is_ISS_above(value[0], | ||
value[1], value[2])) |
Oops, something went wrong.