Package: herald-of-completion
Herald of CompletionHark! The herald of completion has arrived ... to let you know when your long-running tasks are done.Decorate your functions with messengers, who will send a notification to you when your function has finished running.The notification can contain a message and, optionally, the traceback if your function failed.Installationpipinstallherald-of-completionUsageWrap the@heralddecorator around the function you want to be notified about:fromherald.decoratorsimportHeraldfromherald.messengersimportDiscordMessengerherald=Herald(".env")# Specify location of your .env settings file# herald is the name of your decoratordiscord=DiscordMessenger()# create a new messenger@herald(discord)# wrap decorator around the function, with the messenger you want to usedefmy_function():a=[1,2,3]returnaYou can send multiple messengers at the same time:fromherald.decoratorsimportHeraldfromherald.messengersimportDiscordMessenger,EmailMessengerherald=Herald(".env")discord=DiscordMessenger()email=EmailMessenger("recipient@email.com")# some messengers take arguments@herald([discord,email])# multiple messengers can be used at the same timedefmy_function():a=[1,2,3]returnaOptionsBy default, Herald will send a basic notification message indicating whether the function finished successfully or with an error. You can pass in a custom message to use instead:@herald(email,message="My custom message")Passingsend_result=Trueto the decorator will send the return value of your function through the messenger. This also includes notifying you of any exceptions that were raised:@herald(email,send_result=True)# defaults to Truedefmy_function():a=[1,2,3]returna[100]# if an exception is raised, `send_result=True` will also send the tracebackPassingsend_args=Truewill show theargsandkwargsthe function was called with:@herald(email,send_args=True)# defaults to Truedefmy_function(var1,var2):return", ".join([var1,var2])my_function("Hello",var2="world")# function call will be notified with all args and kwargsManual notificationsThere may be times where you want to send a notification without using a decorator / tying it to a specific function.A utility function,send_notification(), can be used for this purpose. To use this, you'll need to construct your ownTaskInfoobject (see:fields) containing the notification contents:fromherald.typesimportTaskInfofromherald.utilsimportsend_notification# import the utilitydiscord=DiscordMessenger()email=EmailMessenger()info=TaskInfo(message="custom message",...)# create TaskInfo with contents of the messagesend_notification([discord,email],info,".env")# pass in path to your .env file, if requiredFor more details about usage, the full API documentation can be found here:documentation.env settingsSome messengers require credentials and/or additional settings to work. These values are stored in a.envfile.Pass the location of this file to theHeraldconstructor, which will pass the values down to your messengers.The.envfile should look something likethis. You only need settings for the messengers you want to use:# Discord settings
WEBHOOK_URL="https://discord.com/..."

# Email settings
SMTP_SERVER="smtp.gmail.com"
SMTP_PORT=587
SMTP_STARTTLS=True
SMTP_USER="user@gmail.com"
SMTP_PASSWORD="password"Given the contents of this file, make sure you don't check it in to version control!ExplanationNameValue TypeMessengerDescriptionWEBHOOK_URLstrDiscordThe webhook URL for your server. InstructionshereSMTP_SERVERstrEmailSTMP server of the email address you want to sendfromSMTP_PORTintEmailSTMP port of the email address you want to sendfromSMTP_STARTTLSboolEmailWhether your server uses STARTTLS for authenticationSMTP_USERstrEmailYour email usernameSMTP_PASSWORDstrEmailYour email passwordContributionCreating a new messengerCreating a new messenger is straightforward and requires only 1 file:Create a new module insrc/herald/messengers/Your class name should take the form<Name>Messengerand inherit the baseMessengerabstract class. Example:class DiscordMessenger(Messenger): ...Your class must implement the abstract methods defined in the baseMessengerclasshereThose methods define how your messenger sets it's secret values, and how it uses those settings to send a notificationFinally, import your messenger in the__init__.pyfilehere. This shortens the import path for users.Thenotify()method of your messenger will receive aTaskInfodataclass object. You can use the dataclass' fields (e.g.name,header) to construct custom notification messages.Note: Pull requests should be made to thedevelopbranch.TestsUnit and integration tests are locatedhere.Tests should be run usingpytest.Code styleThe project is formatted using theblackformatter.Docstrings should follow theGoogle style(with a few tweaks to help with Sphinx generation of documentation pages). Use the docstrings throughout the codebase as a guide.