From f085e07f671adaf1c554da36d9c4f049b2b4b649 Mon Sep 17 00:00:00 2001 From: tabbott36 Date: Fri, 10 May 2024 11:02:13 -0400 Subject: [PATCH] fix(frbvoe): WIP --- frbvoe/backend/voe.py | 21 ++++++--- frbvoe/models/email.py | 7 +-- frbvoe/models/voe.py | 51 ++++++++++++++-------- frbvoe/utilities/email.py | 90 +++++++++++++++++++++------------------ poetry.lock | 60 +++++++++++++++++++++++++- pyproject.toml | 1 + 6 files changed, 160 insertions(+), 70 deletions(-) diff --git a/frbvoe/backend/voe.py b/frbvoe/backend/voe.py index 5ee2247..92913f1 100644 --- a/frbvoe/backend/voe.py +++ b/frbvoe/backend/voe.py @@ -7,18 +7,21 @@ from sanic.response import json as json_response from sanic_ext import openapi +import picologging as logging +logging.basicConfig() +log = logging.getLogger() + from frbvoe.models.comet import Comet from frbvoe.models.email import Email from frbvoe.models.voe import VOEvent voe = Blueprint("voe", url_prefix="/") - # Post at /create_voe @voe.post("create_voe") @openapi.response(201, description="Validates VOEvent data from a host observatory.") # Add the validated payload to the MongoDB Database -async def create_voe(request: Request, voe_event: VOEvent): +async def create_voe(request: Request): #TODO: Shiny, should I add voe_event: VOEvent? """Process a VOEvent. Args: @@ -34,12 +37,18 @@ async def create_voe(request: Request, voe_event: VOEvent): PyMongoError: If there is an error with the PyMongo library. """ + log.info("Processing VOEvent") + voe = VOEvent(**request.json) + print(voe.json()) + + + # Send VOEvent to Comet - comet_report = Comet(voe_event.model_dump()) - comet_report.send + # comet_report = Comet(**request.json) + # comet_report.send # Send VOEvent to Email - email_report = Email(voe_event.model_dump()) + email_report = Email(**request.json) email_report.send # Add VOEvent to MongoDB @@ -48,7 +57,7 @@ async def create_voe(request: Request, voe_event: VOEvent): # Document -> VOEvent Payload Dict. mongo = request.app.ctx.mongo try: - insert_result = await mongo["frbvoe"]["voe"].insert_one(voe_event.model_dump()) + insert_result = await mongo["frbvoe"]["voe"].insert_one(voe.model_dump()) except (Exception, PyMongoError) as mongo_error: logger.error(f"{mongo_error} on /voe") return json_response({"message": mongo_error}, status=500) diff --git a/frbvoe/models/email.py b/frbvoe/models/email.py index 663d053..bd27b8e 100644 --- a/frbvoe/models/email.py +++ b/frbvoe/models/email.py @@ -19,9 +19,10 @@ class Email(VOEvent): email_password (SecretStr) : VOEvent author email account password. Optional. """ - email_password: SecretStr = Field( - default=None, description="VOEvent author email account password. Optional." - ) + # email_password: SecretStr = Field( + # default=None, + # description="VOEvent author email account password. Optional." + # ) @property def send(email_report: Dict[str, Any]): diff --git a/frbvoe/models/voe.py b/frbvoe/models/voe.py index 8137678..5fd9afe 100644 --- a/frbvoe/models/voe.py +++ b/frbvoe/models/voe.py @@ -4,7 +4,7 @@ from typing import Literal, Optional import picologging as logging -from pydantic import EmailStr, Field, StrictFloat, StrictInt, StrictStr +from pydantic import EmailStr, Field, StrictFloat, StrictInt, StrictStr, BaseModel from pydantic_settings import BaseSettings, SettingsConfigDict from sanic import Request @@ -12,7 +12,7 @@ log = logging.getLogger() -class VOEvent(BaseSettings): +class VOEvent(BaseModel): #BaseSettings """VOEvent Object. Args: @@ -57,26 +57,38 @@ class VOEvent(BaseSettings): VOEvent: VOEvent object. """ - model_config = SettingsConfigDict( # TODO: Shiny is this needed? - title="FRB VOEvent", - validate_assignment=True, - validate_return=True, - revalidate_instances="always", - # This parameter ignores any extra fields that are not defined in the model - extra="ignore", - ) + # model_config = SettingsConfigDict( # TODO: Shiny is this needed? + # title="FRB VOEvent", + # validate_assignment=True, + # validate_return=True, + # revalidate_instances="always", + # # This parameter ignores any extra fields that are not defined in the model + # extra="ignore", + # ) kind: Literal[ "detection", "subsequent", "retraction", "update", - ] = Field(..., description="Which kind of VOEvent. Required.", example="detection") + ] = Field( + ..., + description="Which kind of VOEvent. Required.", + example="detection" + ) observatory_name: StrictStr = Field( - ..., description="Name of the host observatory. Required.", example="CHIME" - ) - date: datetime = Field( ..., - gt=datetime(2024, 1, 1), # release date of frb-voe + description="Name of the host observatory. Required.", + example="CHIME" + ) + # date: datetime = Field( + # ..., + # gt=datetime(2024, 1, 1), # release date of frb-voe + # description="Detection time of the FRB. Required.", + # example="2020-01-13 16:55:08.844845", + # ) + date : StrictStr = Field( + ..., + # release date of frb-voe description="Detection time of the FRB. Required.", example="2020-01-13 16:55:08.844845", ) @@ -167,9 +179,12 @@ class VOEvent(BaseSettings): example=13.8, ) flux: float = Field( - default=None, description="Flux of the FRB in Jy. Optional.", example=4.9 + default=None, + description="Flux of the FRB in Jy. Optional.", + example=4.9 ) right_ascension: float = Field( + default=None, ge=0.0, le=360.0, description="""Right acension of the FRB in degrees @@ -177,6 +192,7 @@ class VOEvent(BaseSettings): example=55.2938, ) declination: float = Field( + default=None, ge=-90.0, le=90.0, description="Declination of the FRB in degrees (-90 ≤ Dec ≤ 90). Required.", @@ -198,6 +214,7 @@ class VOEvent(BaseSettings): website: Optional[StrictStr] = Field( default=None, description="Link to the host observatory website. Optional.", + example="https://host_observatory.com/" ) tns_name: Optional[StrictStr] = Field( default=None, @@ -215,7 +232,7 @@ def payload(self): log.info("Returning VOEvent payload") return self.dict() - @staticmethod + @staticmethod #TODO: Shiny what's this for? async def compile(request: Request): """Extracts data from request and returns object. diff --git a/frbvoe/utilities/email.py b/frbvoe/utilities/email.py index c19c94f..8a83f77 100644 --- a/frbvoe/utilities/email.py +++ b/frbvoe/utilities/email.py @@ -25,6 +25,7 @@ def send_email(email_report: Dict[str, Any]): Raises: None """ + email_report = email_report.model_dump() subject = f"{email_report['observatory_name']}_VOE_{email_report['kind']}" if email_report["kind"] in ["detection", "subsequent"]: email_message = f""" @@ -48,36 +49,6 @@ def send_email(email_report: Dict[str, Any]): \n \t\ttsys: {email_report['tsys']} K\n \n - \t\tbackend: {email_report['backend']}\n - \n - \tevent parameters:\n - \t\tevent_no: {email_report['internal_id']}\n - \n - \t\tknown_source_name: {email_report['tns_name']}\n - \n - \t\tdm: {email_report['dm']} +/- {email_report['dm_error']} pc/cm^3\n - \n - \t\ttimestamp_utc: {email_report['date']} - +/- {email_report['sampling_time']}\n #TODO - \n - \t\tsnr: {email_report['snr']}\n - \n - \t\tpos_error_deg_95: {email_report['pos_error_deg_95']} degrees\n - \n\n - WHERE and WHEN\n - \tCoordinate system: {email_report['coordinate_system']}\n - \tTimestamp [UTC]: {email_report['date']}\n - \tLocalization: ({email_report['ra']}, {email_report['dec']}) - +/- {email_report['pos_error_deg_95']} degrees (J2000)\n - \n\n - HOW\n - \tDescription: information regarding the host observatory can be found here: - {email_report['website']}\n - \n\n - WHY\n - \tImportance: {email_report['importance']}\n - \n\n - ********** This email was generated automatically by the {email_report['observatory_name']} frb-voe Service. @@ -125,8 +96,8 @@ def send_email(email_report: Dict[str, Any]): email_message = email_report["update_message"] # Email configuration - receiver_email = "thomas.abbott@mail.mcgill.ca" # TODO: load from DB - smtp_server = "smtp.example.com" # TODO: Shiny what should this be? + receiver_email = "thomas.abbott@physics.mcgill.ca" # TODO: load from DB + smtp_server = "smtp.example.com" # Change to the appropriate server if needed smtp_port = 587 # Change to the appropriate port if needed # Create a message @@ -135,17 +106,52 @@ def send_email(email_report: Dict[str, Any]): message["To"] = receiver_email message["Subject"] = subject message.attach(MIMEText(email_message, "plain")) + + #print email message + print(email_message) + + # # Connect to the SMTP server + # server = smtplib.SMTP(smtp_server, smtp_port) + # server.starttls() # Secure the connection + # # server.login(email_report["email"], email_report["email_password"]) + # server.login("username", "password") # TODO: load from DB + # # Send the email + # server.send_message(message) + + # # Quit the server + # server.quit() + status = "Success" - # Connect to the SMTP server - server = smtplib.SMTP(smtp_server, smtp_port) - server.starttls() # Secure the connection - server.login(email_report["email"], email_report["email_password"]) + return status - # Send the email - server.send_message(message) - # Quit the server - server.quit() - status = "Success" - return status +# \t\tbackend: {email_report['backend']}\n +# \n +# \tevent parameters:\n +# \t\tevent_no: {email_report['internal_id']}\n +# \n +# \t\tknown_source_name: {email_report['tns_name']}\n +# \n +# \t\tdm: {email_report['dm']} +/- {email_report['dm_error']} pc/cm^3\n +# \n +# \t\ttimestamp_utc: {email_report['date']} +# +/- {email_report['sampling_time']}\n #TODO +# \n +# \t\tsnr: {email_report['snr']}\n +# \n +# \t\tpos_error_deg_95: {email_report['pos_error_deg_95']} degrees\n +# \n\n +# WHERE and WHEN\n +# \tCoordinate system: {email_report['coordinate_system']}\n +# \tTimestamp [UTC]: {email_report['date']}\n +# \tLocalization: ({email_report['ra']}, {email_report['dec']}) +# +/- {email_report['pos_error_deg_95']} degrees (J2000)\n +# \n\n +# HOW\n +# \tDescription: information regarding the host observatory can be found here: +# {email_report['website']}\n +# \n\n +# WHY\n +# \tImportance: {email_report['importance']}\n +# \n\n \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index c771f95..61ca6b9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiofiles" @@ -791,6 +791,51 @@ files = [ [package.dependencies] setuptools = "*" +[[package]] +name = "numpy" +version = "1.26.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, +] + [[package]] name = "packaging" version = "24.0" @@ -1182,6 +1227,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1189,8 +1235,16 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1207,6 +1261,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1214,6 +1269,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -1720,4 +1776,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "66d864a3aac364c5e20067121e87d2084cf13a05e36ff040bb2e9512114d195b" +content-hash = "8b024df26068bbd16612b757be19ab56eb542bc3f1ca272ab80adbfa8886ef3d" diff --git a/pyproject.toml b/pyproject.toml index 5a1772a..d27c0a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ picologging = "^0.9.3" comet = "^3.1.0" sanic = {extras = ["ext"], version = "^23.12"} motor = "^3.4.0" +numpy = "^1.26.4" [tool.poetry.group.dev.dependencies]