pax_global_header00006660000000000000000000000064130257243020014510gustar00rootroot0000000000000052 comment=9e30affa831629be47d6693fad3af6102a3c056d HydrelioxGitHub-pyiss-9e30aff/000077500000000000000000000000001302572430200164265ustar00rootroot00000000000000HydrelioxGitHub-pyiss-9e30aff/.travis.yml000066400000000000000000000003671302572430200205450ustar00rootroot00000000000000language: python python: - "3.3" - "3.4" - "3.5" # command to install dependencies install: - pip install -r requirements.txt - pip install coveralls script: nosetests -v --with-coverage --cover-package=pyiss after_success: coverallsHydrelioxGitHub-pyiss-9e30aff/LICENSE000066400000000000000000000020521302572430200174320ustar00rootroot00000000000000MIT License Copyright (c) 2016 Hydreliox Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. HydrelioxGitHub-pyiss-9e30aff/README.md000066400000000000000000000033071302572430200177100ustar00rootroot00000000000000PyIss =================== [![Coverage Status](https://coveralls.io/repos/github/HydrelioxGitHub/pyiss/badge.svg)](https://coveralls.io/github/HydrelioxGitHub/pyiss) [![Build Status](https://travis-ci.org/HydrelioxGitHub/pyiss.svg?branch=master)](https://travis-ci.org/HydrelioxGitHub/pyiss) [![PyPI version](https://badge.fury.io/py/pyiss.svg)](https://badge.fury.io/py/pyiss) ![ISS](https://upload.wikimedia.org/wikipedia/commons/8/88/ISS_after_STS-118_%28computer_rendering_of_August_2006%29.png) ### Library **PyIss** is a Python3 library to access to International Space Station location and data - This library has been developed using this [API](http://open-notify.org/) - This library is for Python3 version 3.3 and upper. ### Installation There are many ways to install ``pyiss``: * With pip (preferred), do ``pip install pyiss``. * To install from source, download it from https://github.com/HydrelioxGitHub/pyiss/ and do ``python setup.py install``. ### Usage To use ``pyiss``, just import it in your project like so:: >>> import pyiss Afterwards, you can have access to ISS location:: >>> station = pyiss.ISS() >>> print(station.current_location()) {'longitude': '133.6864', 'latitude': '51.4806'} Other details:: >>> print(station.pass_times(1, 1)) >>> print(station.number_of_people_in_space()) >>> print(station.seconds_before_next_rise(-50.2322, 76.5668)) >>> print(station.is_ISS_above(4,71, 7)) >>> print(station.next_rise(2, 5, 6).timestamp()) That's it! Documentation is coming ! ### License ``pyiss`` is distributed under the MIT license. HydrelioxGitHub-pyiss-9e30aff/pyiss/000077500000000000000000000000001302572430200175755ustar00rootroot00000000000000HydrelioxGitHub-pyiss-9e30aff/pyiss/__init__.py000066400000000000000000000120501302572430200217040ustar00rootroot00000000000000from datetime import datetime import requests from voluptuous import Schema, Required, All, Any, Length, Range class ISS(object): """Representation of the ISS details.""" 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): """Number of people in space. Be aware that does not mean these people are inside the ISS (it does most of the time), They can be travelling to and from the station. :return: Return a dict with number of people in space right now and their name and their craft :rtype: dict """ data = requests.get('{}{}'.format(self.API_URL, self.API_PEOPLE), timeout=5) if data.status_code is 200: return data.json() else: raise Exception("Error server n {}".format(data.status_code)) def current_location(self): """Current location of the ISS. :return: A dict with latitude and longitude of ISS :rtype: dict """ data = requests.get('{}{}'.format( self.API_URL, self.API_CURRENT_LOCATION), timeout=5) 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): """The next pass times of the ISS. :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('{}{}'.format(self.API_URL, self.API_PASS_TIMES), params=payload, timeout=5) # 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): """The number of people onboard the ISS at the moment. :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): """The next rise of the ISS. :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): """Location of the ISS regardin the current location. :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() HydrelioxGitHub-pyiss-9e30aff/pyiss/tests/000077500000000000000000000000001302572430200207375ustar00rootroot00000000000000HydrelioxGitHub-pyiss-9e30aff/pyiss/tests/__init__.py000066400000000000000000000000001302572430200230360ustar00rootroot00000000000000HydrelioxGitHub-pyiss-9e30aff/pyiss/tests/test_current_location.py000066400000000000000000000033701302572430200257250ustar00rootroot00000000000000from 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 ) HydrelioxGitHub-pyiss-9e30aff/pyiss/tests/test_is_ISS_above.py000066400000000000000000000075141302572430200246640ustar00rootroot00000000000000from 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])) HydrelioxGitHub-pyiss-9e30aff/pyiss/tests/test_next_rise.py000066400000000000000000000066421302572430200243600ustar00rootroot00000000000000from unittest import TestCase from httmock import all_requests, HTTMock, response import pyiss import datetime class TestNext_rise(TestCase): def setUp(self): """ Instantiate the Http Request Mock, the ISS class call and the json response """ # Json response self.json_next_rise = { "message": "success", "request": { "altitude": 100, "datetime": 1481418788, "latitude": 15.0, "longitude": 20.0, "passes": 5 }, "response": [ { "duration": 348, "risetime": 1481448840 }, { "duration": 634, "risetime": 1481454465 }, { "duration": 220, "risetime": 1481460482 }, { "duration": 224, "risetime": 1481484335 }, { "duration": 640, "risetime": 1481489937 } ] } self.timestamp_next_rise = self.json_next_rise['response'][0][ "risetime"] # HTTP Mock @all_requests def correct_response(url, request): headers = {'content-type': 'application/json', 'Set-Cookie': 'foo=bar;'} return response(200, self.json_next_rise, 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_next_rise, headers, None, 5, request) self.http_wrong = wrong_response self.iss = pyiss.ISS() def test_next_rise_json_return(self): """ Test that the function return the right datetime """ with HTTMock(self.http_correct): response = self.iss.next_rise(20, 15) self.assertEqual(self.timestamp_next_rise, response.timestamp()) def test_next_rise_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.next_rise, 15, 20) def test_next_rise_input_bound(self): """ Test that input raise exception using voluptuous Each set of data test a boundary """ with HTTMock(self.http_correct): 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.next_rise, 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.assertEqual(self.timestamp_next_rise, self.iss.next_rise(value[0], value[1], value[2]).timestamp()) HydrelioxGitHub-pyiss-9e30aff/pyiss/tests/test_number_of_people_in_space.py000066400000000000000000000042411302572430200275320ustar00rootroot00000000000000from unittest import TestCase from httmock import all_requests, HTTMock, response import pyiss class TestNumber_of_people_in_space(TestCase): def setUp(self): """ Instantiate the Http Request Mock, the ISS class call and the json response """ # Json response self.json_number_of_people_in_space = { "people": [{"craft": "ISS", "name": "Sergey Rizhikov"}, {"craft": "ISS", "name": "Andrey Borisenko"}, {"craft": "ISS", "name": "Shane Kimbrough"}, {"craft": "ISS", "name": "Oleg Novitskiy"}, {"craft": "ISS", "name": "Thomas Pesquet"}, {"craft": "ISS", "name": "Peggy Whitson"}], "message": "success", "number": 6} # HTTP Mock @all_requests def correct_response(url, request): headers = {'content-type': 'application/json', 'Set-Cookie': 'foo=bar;'} return response(200, self.json_number_of_people_in_space, 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_number_of_people_in_space, headers, None, 5, request) self.http_wrong = wrong_response self.iss = pyiss.ISS() def test_number_of_people_in_space_json_return(self): """ Test that the function return the right number """ with HTTMock(self.http_correct): self.assertEqual(self.iss.number_of_people_in_space(), self.json_number_of_people_in_space['number']) def test_number_of_people_in_space_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.number_of_people_in_space) HydrelioxGitHub-pyiss-9e30aff/pyiss/tests/test_pass_times.py000066400000000000000000000067771302572430200245400ustar00rootroot00000000000000from unittest import TestCase from httmock import all_requests, HTTMock, response import pyiss class TestPass_times(TestCase): def setUp(self): """ Instantiate the Http Request Mock, the ISS class call and the json response """ # Json response self.json_pass_times = { "message": "success", "request": { "altitude": 100, "datetime": 1481418788, "latitude": 15.0, "longitude": 20.0, "passes": 5 }, "response": [ { "duration": 348, "risetime": 1481448840 }, { "duration": 634, "risetime": 1481454465 }, { "duration": 220, "risetime": 1481460482 }, { "duration": 224, "risetime": 1481484335 }, { "duration": 640, "risetime": 1481489937 } ] } self.location = self.json_pass_times['response'] #HTTP Mock @all_requests def correct_response(url, request): headers = {'content-type': 'application/json', 'Set-Cookie': 'foo=bar;'} return response(200, self.json_pass_times, 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_pass_times, headers, None, 5, request) self.http_wrong = wrong_response self.iss = pyiss.ISS() def test_pass_times_json_return(self): """ Test that the function return the right list answer """ with HTTMock(self.http_correct): response = self.iss.pass_times(20, 15) self.assertListEqual(self.location, response) def test_pass_times_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.pass_times, 15,20) def test_pass_times_input_bound(self): """ Test that input raise exception using voluptuous Each set of data test a boundary """ with HTTMock(self.http_correct): data = [[-80.1, 1, 1, 1], [80.1, 1, 1, 1], [1, -180.1, 1, 1], [1, 180.1, 1, 1], [1, 1, -1, 1], [1, 1, 10000.1, 1], [1, 1, 1, 0], [1, 1, 1, 101], [1, 1, 1, 5.1]] for value in data: self.assertRaises(Exception, self.iss.pass_times, value[0], value[1], value[2], value[3]) data = [[-80, 1, 1, 1], [80, 1, 1, 1], [1, -180, 1, 1], [1, 180, 1, 1], [1, 1, 0, 1], [1, 1, 10000, 1], [1, 1, 1, 1], [1, 1, 1, 100]] for value in data: self.assertListEqual(self.location, self.iss.pass_times(value[0], value[1], value[2], value[3])) HydrelioxGitHub-pyiss-9e30aff/pyiss/tests/test_people_in_space.py000066400000000000000000000040141302572430200254740ustar00rootroot00000000000000from unittest import TestCase from httmock import all_requests, HTTMock, response import pyiss class TestPeople_in_space(TestCase): def setUp(self): """ Instantiate the Http Request Mock, the ISS class call and the json response """ #Json response self.json_people_in_space = { "people": [{"craft": "ISS", "name": "Sergey Rizhikov"}, {"craft": "ISS", "name": "Andrey Borisenko"}, {"craft": "ISS", "name": "Shane Kimbrough"}, {"craft": "ISS", "name": "Oleg Novitskiy"}, {"craft": "ISS", "name": "Thomas Pesquet"}, {"craft": "ISS", "name": "Peggy Whitson"}], "message": "success", "number": 6} #HTTP Mock @all_requests def correct_response(url, request): headers = {'content-type': 'application/json', 'Set-Cookie': 'foo=bar;'} return response(200, self.json_people_in_space, 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_people_in_space, headers, None, 5, request) self.http_wrong = wrong_response self.iss = pyiss.ISS() def test_people_in_space_json_return(self): """ Test that the function return the right json answer """ with HTTMock(self.http_correct): response = self.iss.people_in_space() self.assertDictEqual(response, self.json_people_in_space) def test_people_in_space_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.people_in_space)HydrelioxGitHub-pyiss-9e30aff/requirements.txt000066400000000000000000000000331302572430200217060ustar00rootroot00000000000000requests httmock voluptuousHydrelioxGitHub-pyiss-9e30aff/setup.cfg000066400000000000000000000000471302572430200202500ustar00rootroot00000000000000[metadata] description-file = README.mdHydrelioxGitHub-pyiss-9e30aff/setup.py000066400000000000000000000013241302572430200201400ustar00rootroot00000000000000from setuptools import setup setup( name = 'pyiss', packages = ['pyiss'], # this must be the same as the name above install_requires = ['requests', 'httmock', 'voluptuous'], version = '1.0.1', description = 'A simple python3 library for info about the current ' 'International Space Station location', author = 'Hydreliox', author_email = 'hydreliox@gmail.com', license = 'MIT', url = 'https://github.com/HydrelioxGitHub/pyiss', # use the URL to the # github repo download_url = 'https://github.com/HydrelioxGitHub/pyiss/tarball/1.0.1', keywords = ['ISS', 'space', 'station', 'API'], # arbitrary keywords classifiers = [], test_suite='nose.collector', tests_require=['nose'], )