File: C:/Users/fred/anaconda3/Lib/site-packages/astropy/coordinates/calculation.py
# Licensed under a 3-clause BSD style license - see LICENSE.rst
# Standard library
import re
import textwrap
import warnings
from datetime import datetime
from urllib.request import Request, urlopen
# Third-party
from astropy import time as atime
from astropy.utils.console import _color_text, color_print
from .funcs import get_sun
__all__ = []
class HumanError(ValueError):
pass
class CelestialError(ValueError):
pass
def get_sign(dt):
""" """
if (int(dt.month) == 12 and int(dt.day) >= 22) or (
int(dt.month) == 1 and int(dt.day) <= 19
):
zodiac_sign = "capricorn"
elif (int(dt.month) == 1 and int(dt.day) >= 20) or (
int(dt.month) == 2 and int(dt.day) <= 17
):
zodiac_sign = "aquarius"
elif (int(dt.month) == 2 and int(dt.day) >= 18) or (
int(dt.month) == 3 and int(dt.day) <= 19
):
zodiac_sign = "pisces"
elif (int(dt.month) == 3 and int(dt.day) >= 20) or (
int(dt.month) == 4 and int(dt.day) <= 19
):
zodiac_sign = "aries"
elif (int(dt.month) == 4 and int(dt.day) >= 20) or (
int(dt.month) == 5 and int(dt.day) <= 20
):
zodiac_sign = "taurus"
elif (int(dt.month) == 5 and int(dt.day) >= 21) or (
int(dt.month) == 6 and int(dt.day) <= 20
):
zodiac_sign = "gemini"
elif (int(dt.month) == 6 and int(dt.day) >= 21) or (
int(dt.month) == 7 and int(dt.day) <= 22
):
zodiac_sign = "cancer"
elif (int(dt.month) == 7 and int(dt.day) >= 23) or (
int(dt.month) == 8 and int(dt.day) <= 22
):
zodiac_sign = "leo"
elif (int(dt.month) == 8 and int(dt.day) >= 23) or (
int(dt.month) == 9 and int(dt.day) <= 22
):
zodiac_sign = "virgo"
elif (int(dt.month) == 9 and int(dt.day) >= 23) or (
int(dt.month) == 10 and int(dt.day) <= 22
):
zodiac_sign = "libra"
elif (int(dt.month) == 10 and int(dt.day) >= 23) or (
int(dt.month) == 11 and int(dt.day) <= 21
):
zodiac_sign = "scorpio"
elif (int(dt.month) == 11 and int(dt.day) >= 22) or (
int(dt.month) == 12 and int(dt.day) <= 21
):
zodiac_sign = "sagittarius"
return zodiac_sign
_VALID_SIGNS = [
"capricorn",
"aquarius",
"pisces",
"aries",
"taurus",
"gemini",
"cancer",
"leo",
"virgo",
"libra",
"scorpio",
"sagittarius",
]
# Some of the constellation names map to different astrological "sign names".
# Astrologers really needs to talk to the IAU...
_CONST_TO_SIGNS = {"capricornus": "capricorn", "scorpius": "scorpio"}
_ZODIAC = (
(1900, "rat"),
(1901, "ox"),
(1902, "tiger"),
(1903, "rabbit"),
(1904, "dragon"),
(1905, "snake"),
(1906, "horse"),
(1907, "goat"),
(1908, "monkey"),
(1909, "rooster"),
(1910, "dog"),
(1911, "pig"),
)
# https://stackoverflow.com/questions/12791871/chinese-zodiac-python-program
def _get_zodiac(yr):
return _ZODIAC[(yr - _ZODIAC[0][0]) % 12][1]
def horoscope(birthday, corrected=True, chinese=False):
"""
Enter your birthday as an `astropy.time.Time` object and
receive a mystical horoscope about things to come.
Parameters
----------
birthday : `astropy.time.Time` or str
Your birthday as a `datetime.datetime` or `astropy.time.Time` object
or "YYYY-MM-DD"string.
corrected : bool
Whether to account for the precession of the Earth instead of using the
ancient Greek dates for the signs. After all, you do want your *real*
horoscope, not a cheap inaccurate approximation, right?
chinese : bool
Chinese annual zodiac wisdom instead of Western one.
Returns
-------
Infinite wisdom, condensed into astrologically precise prose.
Notes
-----
This function was implemented on April 1. Take note of that date.
"""
from bs4 import BeautifulSoup
today = datetime.now()
err_msg = "Invalid response from celestial gods (failed to load horoscope)."
headers = {"User-Agent": "foo/bar"}
special_words = {
"([sS]tar[s^ ]*)": "yellow",
"([yY]ou[^ ]*)": "magenta",
"([pP]lay[^ ]*)": "blue",
"([hH]eart)": "red",
"([fF]ate)": "lightgreen",
}
if isinstance(birthday, str):
birthday = datetime.strptime(birthday, "%Y-%m-%d")
if chinese:
# TODO: Make this more accurate by using the actual date, not just year
# Might need third-party tool like https://pypi.org/project/lunardate
zodiac_sign = _get_zodiac(birthday.year)
url = (
"https://www.horoscope.com/us/horoscopes/yearly/"
f"{today.year}-chinese-horoscope-{zodiac_sign}.aspx"
)
summ_title_sfx = f"in {today.year}"
try:
res = Request(url, headers=headers)
with urlopen(res) as f:
try:
doc = BeautifulSoup(f, "html.parser")
# TODO: Also include Love, Family & Friends, Work, Money, More?
item = doc.find(id="overview")
desc = item.getText()
except Exception:
raise CelestialError(err_msg)
except Exception:
raise CelestialError(err_msg)
else:
birthday = atime.Time(birthday)
if corrected:
with warnings.catch_warnings():
warnings.simplefilter("ignore") # Ignore ErfaWarning
zodiac_sign = get_sun(birthday).get_constellation().lower()
zodiac_sign = _CONST_TO_SIGNS.get(zodiac_sign, zodiac_sign)
if zodiac_sign not in _VALID_SIGNS:
raise HumanError(
f"On your birthday the sun was in {zodiac_sign.title()}, which is"
" not a sign of the zodiac. You must not exist. Or maybe you can"
" settle for corrected=False."
)
else:
zodiac_sign = get_sign(birthday.to_datetime())
url = f"https://astrology.com/horoscope/daily/{zodiac_sign}.html"
summ_title_sfx = f"on {today.strftime('%Y-%m-%d')}"
res = Request(url, headers=headers)
with urlopen(res) as f:
try:
doc = BeautifulSoup(f, "html.parser")
item = doc.find("div", {"id": "content"})
desc = item.getText()
except Exception:
raise CelestialError(err_msg)
print("*" * 79)
color_print(f"Horoscope for {zodiac_sign.capitalize()} {summ_title_sfx}:", "green")
print("*" * 79)
for block in textwrap.wrap(desc, 79):
split_block = block.split()
for i, word in enumerate(split_block):
for re_word in special_words.keys():
match = re.search(re_word, word)
if match is None:
continue
split_block[i] = _color_text(match.groups()[0], special_words[re_word])
print(" ".join(split_block))
def inject_horoscope():
import astropy
astropy._yourfuture = horoscope
inject_horoscope()