├── requirements.txt ├── .travis.yml ├── setup.py ├── .gitignore ├── README.md ├── LICENSE ├── test_kandilli.py └── kandilli.py /requirements.txt: -------------------------------------------------------------------------------- 1 | cssselect==0.9.1 2 | lxml==3.4.1 3 | nose==1.3.4 4 | pyquery==1.2.9 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - "2.7" 5 | 6 | install: 7 | - pip install -r requirements.txt 8 | 9 | script: 10 | - nosetests 11 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | try: 2 | from setuptools import setup 3 | except ImportError: 4 | from distutils.core import setup 5 | 6 | REQUIREMENTS = [i.strip() for i in open("requirements.txt").readlines()] 7 | 8 | config = dict(description='Kandilli last earthquakes api', 9 | long_description=open('README.md').read(), 10 | author='Halit Alptekin', 11 | url='https://github.com/halitalptekin/kandilli', 12 | author_email='info@halitalptekin.com', 13 | license='MIT', 14 | keywords='api, earthqueke, earthquakes', 15 | version='0.1.1', 16 | py_modules=['kandilli'], 17 | platforms='any', 18 | name='kandilli', 19 | install_requires=REQUIREMENTS) 20 | 21 | setup(**config) 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kandilli API 2 | [![Latest Version](https://pypip.in/version/kandilli/badge.svg)](https://pypi.python.org/pypi/kandilli/) 3 | [![Downloads](https://pypip.in/download/kandilli/badge.svg)](https://pypi.python.org/pypi/kandilli/) 4 | [![Download format](https://pypip.in/format/kandilli/badge.svg)](https://pypi.python.org/pypi/kandilli/) 5 | [![Supported Python versions](https://pypip.in/py_versions/kandilli/badge.svg)](https://pypi.python.org/pypi/kandilli/) 6 | [![License](https://pypip.in/license/kandilli/badge.svg)](https://pypi.python.org/pypi/kandilli/) 7 | [![Build Status](https://api.travis-ci.org/halitalptekin/kandilli.png)](https://travis-ci.org/halitalptekin/kandilli) 8 | 9 | Simple kandilli last earthquakes api. 10 | 11 | # Installation 12 | 13 | pip install kandilli 14 | 15 | # Usage 16 | 17 | from kandilli import LastEarthquakes 18 | 19 | api = LastEarthquakes(10) 20 | print api.data[0] 21 | 22 | api.refresh() 23 | print api.data[0] 24 | 25 | api.many = 25 26 | api.refresh() 27 | print api.data[0] 28 | 29 | api.many = 250 30 | for data in api: 31 | print data['yer'] 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Halit Alptekin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /test_kandilli.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import datetime 3 | import random 4 | from kandilli import LastEarthquakes 5 | from itertools import islice 6 | 7 | 8 | class ApiTest(unittest.TestCase): 9 | def setUp(self): 10 | self.many = 10 11 | self.api = LastEarthquakes(self.many) 12 | 13 | def test_return_iterator_data(self): 14 | for d in islice(self.api, self.many): 15 | self.assertIsInstance(d, dict) 16 | 17 | def test_return_zero_data_length(self): 18 | self.assertEqual(len(self.api), 0) 19 | 20 | def test_return_data_length(self): 21 | self.api.refresh() 22 | self.assertEqual(self.many, len(self.api)) 23 | 24 | def test_return_too_many_items(self): 25 | too_many_items = LastEarthquakes(5000) 26 | self.assertNotEqual(5000, len(too_many_items)) 27 | 28 | def test_return_dict_items(self): 29 | self.assertIsInstance(self.api.data, list) 30 | 31 | def test_many_getter(self): 32 | self.api.many = 4 33 | self.assertEqual(4, self.api.many) 34 | 35 | def test_refresh(self): 36 | self.api.many = 2 37 | self.api.refresh() 38 | self.assertEqual(2, len(self.api)) 39 | 40 | def test_cache(self): 41 | x = self.api.data 42 | y = self.api.data 43 | self.assertEqual(x, y) 44 | 45 | def test_maxlen(self): 46 | self.api.refresh() 47 | self.assertGreater(self.api.maxlen, 500) 48 | 49 | def test_maxlen_zero(self): 50 | self.assertEqual(self.api.maxlen, 0) 51 | 52 | def test_time_format_time(self): 53 | test_data = self.api.data[random.randrange(0, len(self.api))]["tarih"] 54 | datetime_obj = datetime.datetime.strptime(test_data, "%Y.%m.%d") 55 | self.assertIsInstance(datetime_obj, datetime.date) 56 | 57 | def test_time_format_hour(self): 58 | test_data = self.api.data[random.randrange(0, len(self.api))]["saat"] 59 | datetime_obj = datetime.datetime.strptime(test_data, "%H:%M:%S") 60 | self.assertIsInstance(datetime_obj, datetime.date) 61 | -------------------------------------------------------------------------------- /kandilli.py: -------------------------------------------------------------------------------- 1 | """ 2 | Last Earthquakes Api 3 | """ 4 | import urllib 5 | from pyquery import PyQuery 6 | 7 | __version__ = '0.1.1' 8 | __all__ = ['LastEarthquakes'] 9 | 10 | DEFAULT_MANY = 10 11 | QUERY_URL = "http://www.koeri.boun.edu.tr/scripts/lst6.asp" 12 | COL_NAMES = ('tarih', 'saat', 'enlem', 'boylam', 13 | 'derinlik', 'md', 'ml', 'mw', 'yer', 'nitelik') 14 | 15 | 16 | class ApiError(Exception): 17 | """ 18 | ApiError exception class 19 | """ 20 | def __init__(self, name): 21 | """ 22 | Default constructor for exception class 23 | :param name: str 24 | """ 25 | self.name = name 26 | 27 | def __repr__(self): 28 | return "".format(self.name) 29 | 30 | 31 | class LastEarthquakes(object): 32 | """ 33 | Last earthquakes api. 34 | """ 35 | def __init__(self, many=DEFAULT_MANY): 36 | """ 37 | Api constructor method 38 | :param many: integer 39 | """ 40 | self.__features = dict(data_start=6, html_tag='pre', 41 | html_del='\r', many=many) 42 | self.__cache = None 43 | self.__data = None 44 | 45 | def __request(self): 46 | """ 47 | Request url and return all html content 48 | """ 49 | try: 50 | data = urllib.urlopen(QUERY_URL).read() 51 | except IOError: 52 | raise ApiError("Connection error!") 53 | 54 | return data 55 | 56 | def __parse(self, content): 57 | """ 58 | Parse html content and return raw data 59 | :param content: string 60 | """ 61 | parser = PyQuery(content) 62 | temp_data = parser(self.__features.get("html_tag")).text() 63 | 64 | return temp_data.split(self.__features.get("html_del")) 65 | 66 | def __iter__(self): 67 | """ 68 | Iterator for data 69 | """ 70 | self.__data = self.__parse(self.__request()) 71 | 72 | start = self.__features.get("data_start") 73 | many = self.__features.get("many") 74 | finish = many + start if len(self.__data) > many else len(self.__data) 75 | for i in xrange(start, finish): 76 | datum = self.__data[i].split() 77 | datum[8:-1] = [" ".join(datum[8:-1])] 78 | 79 | yield dict(zip(COL_NAMES, datum)) 80 | 81 | def __len__(self): 82 | """ 83 | Data length descriptor 84 | """ 85 | return 0 if not self.__data else len(self.__cache) 86 | 87 | def __repr__(self): 88 | """ 89 | Repr descriptor for instances 90 | """ 91 | return "<{name} many={many}>".format(name="LastEarthquakesApi", 92 | many=self.__features.get("many")) 93 | 94 | def __str__(self): 95 | """ 96 | String descriptor for instances 97 | """ 98 | return self.__repr__() 99 | 100 | @property 101 | def data(self): 102 | """ 103 | Property method for data 104 | """ 105 | if not self.__data: 106 | self.__cache = list(self) 107 | return self.__cache 108 | else: 109 | return self.__cache 110 | 111 | @property 112 | def many(self): 113 | """ 114 | Getter method for many variable 115 | """ 116 | return self.__features.get("many") 117 | 118 | @many.setter 119 | def many(self, value): 120 | """ 121 | Setter method for many variable 122 | :param value: int 123 | """ 124 | if not self.__data: 125 | new_many = value if DEFAULT_MANY > value else DEFAULT_MANY 126 | else: 127 | new_many = min(value, len(self.__data)) 128 | self.__features["many"] = new_many 129 | 130 | @property 131 | def maxlen(self): 132 | """ 133 | Getter method for max length 134 | """ 135 | offset = self.__features.get("data_start") 136 | return 0 if not self.__data else len(self.__data) - offset 137 | 138 | def refresh(self): 139 | """ 140 | Refresh method for re-check all data 141 | """ 142 | self.__cache = list(self) --------------------------------------------------------------------------------