Skip to content

Commit

Permalink
Use block-stdout to block print statements
Browse files Browse the repository at this point in the history
Re-use ``inspect.engine()`` element from support.py
Add a feature to get holidays in any country at any time
Update dependencies in version_locked_requirements.txt
  • Loading branch information
dormant-user committed Aug 18, 2023
1 parent e066591 commit ed7b078
Show file tree
Hide file tree
Showing 16 changed files with 2,521 additions and 12,468 deletions.
2,365 changes: 142 additions & 2,223 deletions docs/genindex.html

Large diffs are not rendered by default.

12,028 changes: 2,295 additions & 9,733 deletions docs/index.html

Large diffs are not rendered by default.

Binary file modified docs/objects.inv
Binary file not shown.
470 changes: 0 additions & 470 deletions docs/py-modindex.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/searchindex.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion jarvis/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
from multiprocessing import current_process

version = "3.5"
version = "3.5.1"

install_script = os.path.join(os.path.dirname(__file__), 'lib', 'install.sh')

Expand Down
4 changes: 2 additions & 2 deletions jarvis/_preexec/keywords_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
from collections import OrderedDict
from typing import NoReturn

import inflect
import yaml

from jarvis.modules.builtin_overrides import ordered_dump, ordered_load
from jarvis.modules.conditions import conversation, keywords
from jarvis.modules.models import models
from jarvis.modules.utils import support

# Used by docs, actual fileio is created in models.py as it gets invoked during the imports above
if not os.path.isdir(models.fileio.root):
Expand All @@ -19,7 +19,7 @@ def rewrite_keywords() -> NoReturn:
"""Loads keywords.yaml file if available, else loads the base keywords module as an object."""
keywords_src = OrderedDict(**keywords.keyword_mapping(), **conversation.conversation_mapping())
# WATCH OUT: for changes in keyword/function name
keywords_src['events'] = [models.env.event_app.lower(), inflect.engine().plural(models.env.event_app)]
keywords_src['events'] = [models.env.event_app.lower(), support.ENGINE.plural(models.env.event_app)]
if os.path.isfile(models.fileio.keywords):
with open(models.fileio.keywords) as dst_file:
try:
Expand Down
3 changes: 1 addition & 2 deletions jarvis/executors/date_time.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from datetime import datetime

import inflect
import pytz
from timezonefinder import TimezoneFinder

Expand Down Expand Up @@ -44,7 +43,7 @@ def current_time(converted: str = None) -> None:
def current_date(*args) -> None:
"""Says today's date and adds the current time in speaker queue if report or time_travel function was called."""
dt_string = datetime.now().strftime("%A, %B")
date_ = inflect.engine().ordinal(datetime.now().strftime("%d"))
date_ = support.ENGINE.ordinal(datetime.now().strftime("%d"))
year = str(datetime.now().year)
event = others.celebrate()
if shared.called['time_travel']:
Expand Down
71 changes: 61 additions & 10 deletions jarvis/executors/others.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import random
import re
import string
import subprocess
import urllib.error
import urllib.request
Expand All @@ -11,6 +12,8 @@
from typing import Dict, List, NoReturn, Tuple, Union

import boto3
from blockstdout import BlockPrint
from dateutil import parser, relativedelta
from googlehomepush import GoogleHome
from googlehomepush.http_server import serve_file
from holidays import country_holidays
Expand Down Expand Up @@ -223,9 +226,8 @@ def ip_scan(host_id: int) -> Tuple[str, str]:
for target in chosen:
file_url = serve_file(file, "audio/mp3") # serves the file on local host and generates the play url
support.flush_screen()
util.block_print()
GoogleHome(host=target).play(file_url, "audio/mp3")
util.release_print()
with BlockPrint():
GoogleHome(host=target).play(file_url, "audio/mp3")
if len(chosen) > 1:
speaker.speak(text=f"That's interesting, you've asked me to play on {len(chosen)} devices at a time. "
f"I hope you'll enjoy this {models.env.title}.", run=True)
Expand Down Expand Up @@ -344,19 +346,68 @@ def report(*args) -> NoReturn:
shared.called['report'] = False


def extract_humanized_date(phrase: str) -> Tuple[datetime.date, str, str]:
"""Converts most humanized date into datetime object.
Args:
phrase: Takes the phrase spoken as an argument.
Returns:
Tuple[datetime.date, str, str]:
A tuple of the date object, human friendly name, and the tense.
"""
today = datetime.now().date()

if "day after tomorrow" in phrase:
return today + relativedelta.relativedelta(days=2), "day after tomorrow", "is"
elif "day before yesterday" in phrase:
return today - relativedelta.relativedelta(days=2), "day before yesterday", "was"
elif "tomorrow" in phrase:
return today + relativedelta.relativedelta(days=1), "tomorrow", "is"
elif "yesterday" in phrase:
return today - relativedelta.relativedelta(days=1), "yesterday", "was"

try:
parsed_date = parser.parse(phrase, fuzzy=True)
except parser.ParserError as error:
logger.error(error)
return today, "today", "is"

if "next" in phrase:
next_occurrence = parsed_date + relativedelta.relativedelta(weeks=1)
return next_occurrence.date(), f"next {next_occurrence.strftime('%A')}, ({next_occurrence.strftime('%B')} " \
f"{support.ENGINE.ordinal(next_occurrence.strftime('%d'))})", "is"
elif "last" in phrase:
last_occurrence = parsed_date - relativedelta.relativedelta(weeks=1)
return last_occurrence.date(), f"last {last_occurrence.strftime('%A')}, ({last_occurrence.strftime('%B')} " \
f"{support.ENGINE.ordinal(last_occurrence.strftime('%d'))})", "was"

return parsed_date, f"{parsed_date.strftime('%A')}, ({parsed_date.strftime('%B')} " \
f"{support.ENGINE.ordinal(parsed_date.strftime('%d'))})", "is"


def celebrate(phrase: str = None) -> str:
"""Function to look if the current date is a holiday or a birthday.
Args:
phrase: Takes the phrase spoken as an argument.
Returns:
str:
A string of the event observed today.
"""
countrycode = None
countryname = None
if phrase:
date, day, tense = extract_humanized_date(phrase)
logger.info(f"Extracted humanized date: {date}")
else:
date, day, tense = datetime.today().date(), "today", "is"
if phrase:
phrase = phrase.strip()
countries = {country[1]: [' '.join(re.findall('[A-Z][^A-Z]*', country[0])), country[2]] for country in
COUNTRIES.values()}
countries = {
country[1]: [' '.join(re.findall('[A-Z][^A-Z]*', country[0])), country[2]] for country in COUNTRIES.values()
}
for code, names in countries.items():
# If country code is used, then it should be a precise match, otherwise just regex it
if code in phrase.split() or any(name in phrase for name in names):
Expand All @@ -372,18 +423,18 @@ def celebrate(phrase: str = None) -> str:
if not countrycode:
countrycode = "US"
countryname = "USA"
if current_holiday := country_holidays(countrycode.upper()).get(datetime.today().date()):
if current_holiday := country_holidays(countrycode.upper()).get(date):
if phrase:
speaker.speak(text=f"Today is {current_holiday!r} in {countryname}")
speaker.speak(text=f"{string.capwords(day)} {tense} {current_holiday!r} in {countryname}")
else:
return current_holiday
elif models.env.birthday == datetime.now().strftime("%d-%B"):
elif models.env.birthday == date.strftime("%d-%B"):
if phrase:
speaker.speak(text=f"Today is your birthday {models.env.title}!")
speaker.speak(text=f"{string.capwords(day)} {tense} your birthday {models.env.title}!")
else:
return "Birthday"
elif phrase:
speaker.speak(text=f"There are no events to celebrate today in {countryname}")
speaker.speak(text=f"There are no events to celebrate {day}, in {countryname}")


def time_travel() -> None:
Expand Down
3 changes: 1 addition & 2 deletions jarvis/executors/unconditional.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import re
import webbrowser

import inflect
import requests
from geopy.distance import geodesic

Expand Down Expand Up @@ -81,7 +80,7 @@ def google_maps(query: str) -> bool:
option = 'only option I found is'
next_val = f"Do you want to head there {models.env.title}?"
elif n <= 2:
option = f'{inflect.engine().ordinal(n)} option is'
option = f'{support.ENGINE.ordinal(n)} option is'
next_val = f"Do you want to head there {models.env.title}?"
elif n <= 5:
option = 'next option would be'
Expand Down
3 changes: 1 addition & 2 deletions jarvis/executors/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from typing import Any, Dict, NoReturn, Optional, Tuple, Union
from urllib.parse import urlencode

import inflect
import requests

from jarvis.executors import files, location, word_match
Expand Down Expand Up @@ -108,7 +107,7 @@ def weather(phrase: str = None, monitor: bool = False) -> Union[Tuple[Any, int,
elif 'next week' in phrase:
key = -1
next_week = datetime.fromtimestamp(response['daily'][-1]['dt']).strftime("%A, %B %d")
tell = f"on {' '.join(next_week.split()[:-1])} {inflect.engine().ordinal(next_week.split()[-1])}"
tell = f"on {' '.join(next_week.split()[:-1])} {support.ENGINE.ordinal(next_week.split()[-1])}"
else:
key = 0
tell = 'today'
Expand Down
6 changes: 3 additions & 3 deletions jarvis/lib/version_locked_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ axju-jokes==1.0.3
inflect==7.0.0
pywebostv==0.8.9
speedtest-cli==2.1.3
holidays==0.29
holidays==0.30
randfacts==0.20.2
openai==0.27.8
fastapi==0.95.1 # Upgrades pydantic
uvicorn==0.22.0 # Upgrades pydantic
aiofiles==23.1.0
aiofiles==23.2.1
python-multipart==0.0.6
pydantic[email]==1.10.7 # Major code change, hold
icalendar==5.0.7
Expand All @@ -31,7 +31,7 @@ pytest==7.4.0
bs4==0.0.1
Pillow==10.0.0
packaging==23.1
numpy==1.25.1
numpy==1.25.2
SoundFile==0.12.1
deepdiff==6.3.1
pymyq==3.1.6
Expand Down
5 changes: 2 additions & 3 deletions jarvis/modules/retry/retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@
import warnings
from typing import Any, Callable, NoReturn, Union

import inflect

from jarvis.modules.logger import logger
from jarvis.modules.utils import support


def retry(attempts: int = 3, interval: Union[int, float] = 0, warn: bool = False, exclude_exc=None) -> \
Expand Down Expand Up @@ -68,7 +67,7 @@ def wrapper(*args: Any, **kwargs: Any) -> Callable:
return_val = func(*args, **kwargs)
# Log messages only when the function did not return during the first attempt
if i > 1:
logger.info(f"{func.__name__} returned at {inflect.engine().ordinal(num=i)} attempt")
logger.info(f"{func.__name__} returned at {support.ENGINE.ordinal(num=i)} attempt")
return return_val
except exclusions as excl_error:
logger.error(excl_error)
Expand Down
8 changes: 5 additions & 3 deletions jarvis/modules/utils/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
from jarvis.modules.models import models
from jarvis.modules.utils import shared

ENGINE = inflect.engine()

days_in_week = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
db = database.Database(database=models.fileio.base_db)

Expand Down Expand Up @@ -393,7 +395,7 @@ def number_to_words(input_: Union[int, str], capitalize: bool = False) -> str:
str:
String version of the number.
"""
result = inflect.engine().number_to_words(num=input_)
result = ENGINE.number_to_words(num=input_)
return result[0].upper() + result[1:] if capitalize else result


Expand All @@ -411,8 +413,8 @@ def pluralize(count: int, word: str, to_words: bool = False, cap_word: bool = Fa
String formatted time in singular or plural.
"""
if to_words:
return f"{number_to_words(input_=count, capitalize=cap_word)} {inflect.engine().plural(text=word, count=count)}"
return f"{count} {inflect.engine().plural(text=word, count=count)}"
return f"{number_to_words(input_=count, capitalize=cap_word)} {ENGINE.plural(text=word, count=count)}"
return f"{count} {ENGINE.plural(text=word, count=count)}"


def time_converter(second: float) -> str:
Expand Down
14 changes: 1 addition & 13 deletions jarvis/modules/utils/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@
import contextlib
import difflib
import hashlib
import os
import random
import re
import socket
import string
import sys
import uuid
from datetime import datetime, timezone
from typing import Any, Dict, Hashable, List, NoReturn, Union
from typing import Any, Dict, Hashable, List, Union


def get_timezone() -> str:
Expand Down Expand Up @@ -343,16 +341,6 @@ def remove_duplicates(input_: List[Any]) -> List[Any]:
return [i for n, i in enumerate(input_) if i not in input_[n + 1:]]


def block_print() -> NoReturn:
"""Suppresses print statement."""
sys.stdout = open(os.devnull, 'w')


def release_print() -> NoReturn:
"""Removes print statement's suppression."""
sys.stdout = sys.__stdout__


def get_free_port() -> int:
"""Chooses a PORT number dynamically that is not being used to ensure we don't rely on a single port.
Expand Down
5 changes: 5 additions & 0 deletions release_notes.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Release Notes
=============

3.5.1 (08/18/2023)
------------------
- Adds a new feature to request holidays on any date/day
- Minor improvements in stability

3.5 (08/10/2023)
----------------
- Adds a new feature to place functional restrictions on offline commands
Expand Down

0 comments on commit ed7b078

Please sign in to comment.