Package: pyalert
:moyai: pyalertpyalertis a lightweight framework that empowers you to stay on top of what data is flowing through your Python code.pyalertis designed to:mimic the feeling of writing unit testsunobtrusively add runtime alerting to your Python code:mag: Table of Contents:gear: How Does It Work?:memo: In Summary:brain: Further Thinking:construction: Roadmap:handshake: Contribution:gear: How Does It Work?Suppose you are building software that involves processing data from a bike race...classBiker:def__init__(self,name:str,age:int,avg_mph:int):self.name=nameself.age=ageself.avg_mph=avg_mphdefbike_race(bikers:List[Biker])->str:"""A bike race that takes three Bikers and returns a winner announcement"""winner=max(bikers,key=lambdabiker:biker.avg_mph)returnf"{winner.name}wins with an avg mph of{winner.avg_mph}!"Instead of cluttering your code with complex catching logic andlog/printstatements to indicate when certain occurances arise,pyalertfacilitates an intuitive segregation of such concerns with a unit-test-like design pattern...As is often done with unit tests, let's define a class that contains our alerts...Note how we use the@alert_confdecorator to configure the runtime behavior of each alert method...frompyalertimportPyAlerts,alert_conf# must inherit from PyAlertsclassBikeRaceAlerts(PyAlerts):"""Alerts for the bike_race function"""# takes="input" configures the alert method to take the input args as its args@alert_conf(takes="input",raise_error=False)defsuspiciously_fast_bikers(self,*args,**kwargs):bikers=args[0]ifargselsekwargs["bikers"]msg="Suspicious speeds--implement compulsory drug testing after the race!"assertnotany(b.avg_mph>30),msg# raise_error=True will cause an error to be raised if the assertion fails@alert_conf(takes="input",raise_error=True)defimpossibly_fast_bikers(self,*args,**kwargs):bikers=args[0]ifargselsekwargs["bikers"]msg="Stop the race! we need to recalibrate our speedometers!"assertnotany(b.avg_mph>100forbinbikers),msg# takes="output" configures the alert method to take the return value as its arg@alert_conf(takes="output",raise_error=False)defverbose_winner_announcement(self,return_value):msg="The winner announcement came out unusually verbose!"assertlen(return_value)<120,msgLastly, we'll decorate our originalbike_racefunction with the@pyalertdecorator and passBikeRaceAlertsas the argument:frompyalertimportpyalert@pyalert(pyalerts=BikeRaceAlerts)defbike_race(bikers:List[Biker])->str:...And voila,pyalertswill take care of our alerts at runtime!:memo: In Summarypyalerthas 3 fundamental abstractions...flowchart TD
    pkg("📦 pyalert")
    pa("1️⃣\n@pyalert\n(decorator)")
    PA("2️⃣\nPyAlerts\n(base class)")
    ac("3️⃣\n@alert_conf\n(decorator)")

    
    pkg --- pa
    pkg --- PA
    pkg --- acThey are used as follows:flowchart LR
    pa("1️⃣\n@pyalert\n(decorator)\n📦")
    yPA("PyAlerts\nchild\nclass\n👤")
    PA("2️⃣\nPyAlerts\n(base class)\n📦")
    am("alert\nmethods\n👤")
    yf("your\nfunction\n👤")
    as("assert\nstatements\n🐍")
    ac("3️⃣\n@alert_conf\n(decorator)\n📦")

    pa -. takes a --> yPA
    pa -. and\ndecorates --> yf
    yPA -. and which\ncontains --> am
    yPA -. which\ninherits\nfrom --> PA
    am -. that use --> as
    am -. and are\nconfigured\nby --> ac:brain: Further Thinking====== :thought_balloon: :one: ======pyalertsis designed to enhance your project by::desktop_computer: - helping drive development with quicker insights:eye: - helping with the monitoring of data phenomena in production...all while introducing minimal boilerplate to your source code.====== :thought_balloon: :two: ======pyalertscan be used minimally as a mere seperation-of-tasks practice within a single file...or...since it feels so much like unit testing, why not create analertsfolder that mirrors yoursrccode folder structure?📦project┣📂src┣📂tests┣📂alerts┣📜README.md┗📜requirements.txt====== :thought_balloon: :three: ======Are you inheriting a codebase that is already jam-packed with verbosity and complexity?Since the only boilerplate required to usepyalertsis a simple@pyalertdecorator, you can easily add it to your codebase without worrying about the repurcussions.:construction: Roadmap:exclamation: Conceive/implement integration strategy with logging:exclamation: CI pipeline:exclamation: Docs:handshake: ContributionIf you think there is open-source merit to this idea, or have any thoughts on how its proposed utility might be nullified by other existing tools, please let me know!Hereis a single-question form where you can voice your enthusiasm about the idea of pyalert being developed/maintained on a scale of 1-10.If you would like contribute and collaborate, please reach out to me onLinkedIn!