├── .gitignore ├── .travis.yml ├── LICENSE ├── README.rst ├── pyaztro ├── __init__.py ├── aztro.py ├── exceptions.py ├── helpers.py └── models.py ├── setup.py └── tests ├── __init__.py └── tests.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # Pycharm 107 | .idea/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | # command to install dependencies 3 | install: 4 | - pip install .[test] 5 | # command to run tests 6 | script: 7 | - python setup.py test 8 | cache: pip 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Sameer Kumar 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | https://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | PyAztro 2 | ============ 3 | |downloads| |GitHub make-a-pull-requests| |Maintenance yes| |Paypal| |say thanks| 4 | 5 | PyAztro is a client library for `aztro `_ written in Python. 6 | 7 | aztro provides horoscope info for sun signs such as Lucky Number, Lucky Color, Mood, Color, Compatibility with other sun signs, description of a sign for that day etc. 8 | 9 | Documentation for aztro API is available `here `_, documentation for PyAztro most of the common usage. 10 | 11 | 12 | 13 | Requirements 14 | --------------- 15 | 16 | * Python 3+ (Recommended) 17 | * The ``requests`` and ``dateutils`` library. `pip` should handle this for you when installing pyaztro. 18 | 19 | Installation 20 | --------------- 21 | :: 22 | 23 | $ pip install pyaztro 24 | 25 | Usage 26 | ------------------ 27 | :: 28 | 29 | >>> import pyaztro 30 | >>> horoscope = pyaztro.Aztro(sign='aries') 31 | 32 | # Mood 33 | >>> horoscope.mood 34 | 'Relaxed' 35 | 36 | # Lucky time 37 | >>> horoscope.lucky_time 38 | '2pm' 39 | 40 | # Description 41 | >>> horoscope.description 42 | 'If you don't have big plans, you can rest assured that you will soon. A surprise missive is waiting. Enjoy. It's spontaneity, not variety, that's the spice of life.' 43 | 44 | # Sun sign date range 45 | >>> horoscope.date_range 46 | [datetime.datetime(2019, 3, 21, 0, 0), datetime.datetime(2019, 4, 20, 0, 0)] 47 | 48 | # Lucky Color 49 | >>> horoscope.color 50 | 'Spring Green' 51 | 52 | # Sign compatibility 53 | >>> horoscope.compatibility 54 | 'Aquarius' 55 | 56 | # Horoscope date for which the info is valid for 57 | >>> horoscope.current_date 58 | datetime.date(2019, 6, 2) 59 | 60 | # Lucky number 61 | >>> horoscope.lucky_number 62 | 85 63 | 64 | 65 | Support 66 | ---------- 67 | If you encounter any bugs, please let me know by `creating an issue `_ or tweeting at me `@sameer_kumar018 `_. 68 | 69 | Author 70 | ------ 71 | `Sameer Kumar `_ 72 | 73 | 74 | 75 | 76 | .. |downloads| image:: https://pepy.tech/badge/pyaztro 77 | :target: https://pepy.tech/project/pyaztro 78 | 79 | .. |GitHub make-a-pull-requests| image:: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square 80 | :target: http://makeapullrequest.com 81 | 82 | .. |say thanks| image:: https://img.shields.io/badge/say-thanks-ff69b4.svg 83 | :target: https://saythanks.io/to/sameerkumar18 84 | 85 | .. |Maintenance yes| image:: https://img.shields.io/badge/Maintained%3F-yes-green.svg 86 | :target: https://gitHub.com/sameerkumar18/pyaztro 87 | 88 | .. |Paypal| image:: https://img.shields.io/badge/Paypal-Donate-blue.svg 89 | :target: https://www.paypal.me/sameerkumar18 90 | -------------------------------------------------------------------------------- /pyaztro/__init__.py: -------------------------------------------------------------------------------- 1 | from pyaztro.aztro import Aztro -------------------------------------------------------------------------------- /pyaztro/aztro.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | PyAztro 5 | ~~~~~~~ 6 | 7 | PyAztro is a Python Wrapper for aztro - The Astrology API 8 | 9 | 10 | :copyright: (c) 2018 by Sameer Kumar. 11 | :license: Apache 2.0, see LICENSE for more details. 12 | 13 | """ 14 | 15 | import requests 16 | from pyaztro.helpers import parse_date, parse_date_range, parse_time, signs, days 17 | import pyaztro.exceptions 18 | 19 | 20 | class Aztro(object): 21 | def __init__(self, sign, day='today', timezone=None): 22 | base_url = 'https://aztro.sameerkumar.website' 23 | sign = str(sign).lower() if sign else sign 24 | day = str(day).lower() if day else day 25 | # Backward compatibility 26 | self.sign = sign 27 | self.day = day 28 | if sign not in signs: 29 | raise pyaztro.exceptions.PyAztroSignException('Invalid sign {0} passed'.format(sign), sign) 30 | if day not in days: 31 | raise pyaztro.exceptions.PyAztroDayException('Invalid day {0} passed'.format(day), day) 32 | params = ( 33 | ('sign', sign), 34 | ('day', day), 35 | ('timezone', timezone) 36 | 37 | ) 38 | try: 39 | r = requests.post(url=base_url, params=params) 40 | if r.status_code is 200: 41 | data = r.json() 42 | else: 43 | raise pyaztro.exceptions.PyAztroInvalidAPIResponseException( 44 | 'Could not get a successful response from aztro API', r.content) 45 | except requests.exceptions.RequestException as re: 46 | raise pyaztro.exceptions.PyAztroRequestsException('Exception during making request to aztro API', re) 47 | 48 | try: 49 | self.lucky_time = parse_time(data['lucky_time']) 50 | self.description = data['description'] 51 | self.date_range = parse_date_range(data['date_range']) 52 | self.color = data['color'] 53 | self.mood = data['mood'] 54 | self.compatibility = data['compatibility'] 55 | self.current_date = parse_date(data['current_date']) 56 | self.lucky_number = int(data['lucky_number']) 57 | except Exception as ex: 58 | raise pyaztro.exceptions.PyAztroInvalidAPIResponseException('Could not parse data from aztro API', ex) 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /pyaztro/exceptions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | pyaztro.exceptions 5 | ~~~~~~~~~~~~~~~~~~~ 6 | 7 | This module contains the set of PyAztro' exceptions. 8 | """ 9 | 10 | from requests.exceptions import RequestException 11 | 12 | 13 | class PyAztroException(Exception): 14 | # Exception raised when 15 | # Base Exception for all exceptions 16 | def __init__(self, message, errors): 17 | super().__init__(message) 18 | self.errors = errors 19 | 20 | 21 | class PyAztroRequestsException(RequestException): 22 | # Exceptions caused using requests library 23 | pass 24 | 25 | 26 | class PyAztroDayException(PyAztroException): 27 | # Exception raised when `day` is wrong 28 | pass 29 | 30 | 31 | class PyAztroSignException(PyAztroException): 32 | # Exception raised when `sign` is wrong 33 | pass 34 | 35 | 36 | class PyAztroInvalidAPIResponseException(PyAztroException): 37 | # Exception raised when aztro API response is not parse-able 38 | pass 39 | -------------------------------------------------------------------------------- /pyaztro/helpers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | pyaztro.helpers 5 | ~~~~~~~ 6 | 7 | """ 8 | 9 | from dateutil.parser import parse 10 | 11 | signs = [ 12 | 'aries', 'taurus', 'gemini', 'cancer', 'leo', 'virgo', 'libra', 13 | 'scorpio', 'sagittarius', 'capricorn', 'aquarius', 'pisces' 14 | ] 15 | days = ['yesterday', 'today', 'tomorrow'] 16 | 17 | 18 | def parse_date(date_string): 19 | return parse(date_string).date() 20 | 21 | 22 | def parse_date_range(date_range_string): 23 | # returns a tuple of 2 date objects 24 | dates = date_range_string.split('-') 25 | response = [parse(dates[0]), parse(dates[1])] 26 | return response 27 | 28 | 29 | def parse_time(time_string): 30 | return time_string 31 | -------------------------------------------------------------------------------- /pyaztro/models.py: -------------------------------------------------------------------------------- 1 | class dotdict(dict): 2 | """dot.notation access to dictionary attributes""" 3 | __getattr__ = dict.get 4 | __setattr__ = dict.__setitem__ 5 | __delattr__ = dict.__delitem__ 6 | 7 | 8 | class APIModel(object): 9 | def __init__(self, data): 10 | self.lucky_time = data['lucky_time'] 11 | self.description = data['description'] 12 | self.date_range = data['date_range'] 13 | self.color = data['color'] 14 | self.mood = data['mood'] 15 | self.compatibility = data['compatibility'] 16 | self.current_date = data['current_date'] 17 | self.lucky_number = data['lucky_number'] 18 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | PyAztro 5 | ~~~~~~~ 6 | 7 | Setup for PyAztro 8 | """ 9 | 10 | from setuptools import setup, find_packages 11 | import os 12 | 13 | 14 | if os.path.exists('README.rst'): 15 | readme_path = 'README.rst' 16 | else: 17 | readme_path = 'README.md' 18 | 19 | setup( 20 | name='pyaztro', 21 | version='0.3', 22 | description='A client library for aztro - The Astrology API', 23 | long_description=open(readme_path).read(), 24 | url='https://github.com/sameerkumar18/pyaztro', 25 | author='Sameer Kumar', 26 | author_email='sam@sameerkumar.website', 27 | license='Apache 2.0', 28 | 29 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers 30 | classifiers=[ 31 | 'Development Status :: 5 - Production/Stable', 32 | 'Intended Audience :: Developers', 33 | 'Topic :: Software Development :: Libraries', 34 | 'License :: OSI Approved :: Apache Software License', 35 | 'Programming Language :: Python', 36 | 'Programming Language :: Python :: 2', 37 | 'Programming Language :: Python :: 2.7', 38 | 'Programming Language :: Python :: 3', 39 | 'Programming Language :: Python :: 3.4', 40 | 'Programming Language :: Python :: 3.5', 41 | 'Programming Language :: Python :: 3.6', 42 | 'Programming Language :: Python :: 3.7', 43 | 'Programming Language :: Python :: Implementation :: CPython', 44 | 'Programming Language :: Python :: Implementation :: PyPy' 45 | ], 46 | 47 | keywords='api wrapper client library astrology data aztro', 48 | 49 | packages=find_packages(exclude=['contrib', 'docs', 'tests', 'venv']), 50 | 51 | install_requires=['requests', 'python-dateutil'], 52 | 53 | test_suite='tests', 54 | 55 | # List additional groups of dependencies here (e.g. development 56 | # dependencies). You can install these using the following syntax, 57 | # for example: 58 | # $ pip install -e .[dev] 59 | extras_require={ 60 | 'dev': ['sphinx', 'sphinx-autobuild'] 61 | } 62 | ) -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sameerkumar18/pyaztro/508f60ab58eba51eef863f0e7aaeade6bc960041/tests/__init__.py -------------------------------------------------------------------------------- /tests/tests.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import requests 3 | import pyaztro 4 | import ssl 5 | import urllib3 6 | import datetime 7 | import sys 8 | 9 | 10 | class AztroResponseTest(unittest.TestCase): 11 | # List of valid signs : 12 | 13 | signs = [ 14 | 'aries', 'taurus', 'gemini', 'cancer', 'leo', 'virgo', 'libra', 15 | 'scorpio', 'sagittarius', 'capricorn', 'aquarius', 'pisces' 16 | ] 17 | 18 | # List of 'aries' sign in different case : 19 | any_case_sign = [ 20 | 'aries', 'Aries', 'ARIES', 'ArIes' 21 | ] 22 | 23 | # List of non valid signs : 24 | non_signs = [ 25 | 'phoenix', 'pegasus' 26 | ] 27 | 28 | # List of valid input for day parameter : 29 | days = ['yesterday', 'today', 'tomorrow'] 30 | 31 | # List of non valid input for day parameter : 32 | wrong_date = ['day after tomorrow', '21st', 'tuesday'] 33 | 34 | # Part of response to be returned on wrong input : 35 | wrong_param_response = "Seems to be some kind of problem in the parameters" 36 | 37 | # setUp method for setting up the test 38 | def setUp(self): 39 | try: 40 | self.check = pyaztro.Aztro(sign='aries', day='today') 41 | except Exception as networkerror: 42 | print("setUp method failed to execute :", networkerror) 43 | sys.exit(1) 44 | 45 | # Test for checking the types of attributes in response object 46 | 47 | def test_response_object_type(self): 48 | self.assertTrue(type(self.check.lucky_time) is str) 49 | self.assertTrue(type(self.check.description) is str) 50 | self.assertTrue(type(self.check.date_range) is list) 51 | self.assertTrue(type(self.check.color) is str) 52 | self.assertTrue(type(self.check.mood) is str) 53 | self.assertTrue(type(self.check.compatibility) is str) 54 | self.assertTrue(type(self.check.current_date) is datetime.date) 55 | self.assertTrue(type(self.check.lucky_number) is int) 56 | 57 | # Test when the sign passed is a valid sign: 58 | def test_correct_sign(self): 59 | for i in self.signs: 60 | print(i) 61 | data = pyaztro.Aztro(i) 62 | self.assertTrue(type(data) is pyaztro.aztro.Aztro) 63 | 64 | # Test for checking the response when wrong input for sign is passed : 65 | # def test_wrong_sign(self): 66 | # for i in self.non_signs: 67 | # data = pyaztro.Aztro(sign=i) 68 | # self.assertTrue(type(data) is str) 69 | # self.assertTrue(self.wrong_param_response in data) 70 | 71 | # Test for checking the response when correct input is entered for day: 72 | def test_correct_date(self): 73 | for i in range(3): 74 | data = pyaztro.Aztro(sign='aries', day=self.days[i]) 75 | self.assertTrue(type(data) is pyaztro.aztro.Aztro) 76 | self.assertEqual(type(data.current_date), type(datetime.date.today() - datetime.timedelta(days=(i - 1)))) 77 | 78 | # Test for checking the response object when wrong input is enteres for day: 79 | # def test_wrong_date(self): 80 | # for i in self.wrong_date: 81 | # data = pyaztro.Aztro(sign='aries', day=i) 82 | # self.assertTrue(type(data) is str) 83 | # self.assertTrue(self.wrong_param_response in data) 84 | 85 | # Test for checking the response object when sign is given in different case: 86 | def test_anycase_input(self): 87 | for i in self.any_case_sign: 88 | data = pyaztro.Aztro(sign=i) 89 | self.assertEqual(type(data), type(self.check)) 90 | 91 | 92 | # def suite(q): 93 | # suite = unittest.TestSuite() 94 | # suite.addTest(AztroResponseTest.test_correct_sign(q)) 95 | # suite.addTest(AztroResponseTest.test_wrong_sign(q)) 96 | # suite.addtest(AztroResponseTest.test_correct_date(q)) 97 | # suite.addTest(AztroResponseTest.test_wrong_date(q)) 98 | # suite.addTest(AztroResponseTest.test_parse_date(q)) 99 | # suite.addTest(AztroResponseTest.test_parse_date_range(q)) 100 | # suite.addTest(AztroResponseTest.test_parse_time(q)) 101 | # return suite 102 | 103 | if __name__ == '__main__': 104 | unittest.main() 105 | # runner = unittest.TextTestRunner() 106 | # query = AztroResponseTest() 107 | # runner.run(suite(query)) 108 | --------------------------------------------------------------------------------