Skip to content

Commit

Permalink
fix(Tests): Fixed some broken tests - removed part of the TNS test
Browse files Browse the repository at this point in the history
  • Loading branch information
tabbott36 committed Oct 22, 2024
1 parent 9ed6779 commit bab3d9e
Show file tree
Hide file tree
Showing 17 changed files with 227 additions and 170 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,14 @@ The help dialogue will explain what options are required and what data is needed
- proprietary period length (in years)

Optionally, one can practice the submission by setting the `--sandbox` flag in the call signature.


### Contributing

All motivated community members are welcomed and encouraged to contribute to the frb-voe Service. Contributions should be initiated with an issue and corresponding development branch. We encourage users to write tests for their contributed code, which can be run locally using:

```poetry run pytest --cov-report=html --cov .```

The repository is formatted according to pre-commit, to run pre-commit locally, use:

```pre-commit run --all-files```
4 changes: 2 additions & 2 deletions frbvoe/backend/subscriber.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""Subscriber Server Blueprint."""

import picologging as logging
from models.subscriber import Subscriber
from pymongo.errors import PyMongoError
from sanic import Blueprint
from sanic.log import logger
from sanic.request import Request
from sanic.response import json as json_response
from sanic_ext import openapi

from frbvoe.models.subscriber import Subscriber

logging.basicConfig()
log = logging.getLogger()

Expand All @@ -22,7 +23,6 @@
)
# Add the subscriber payload to the MongoDB Database
async def add_subscriber(request: Request):
# TODO: Shiny, should I add subscriber: Subscriber?
"""Adds a subscriber document to the database.
Args:
Expand Down
2 changes: 1 addition & 1 deletion frbvoe/backend/voe.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
@voe.post("create_voe")
@openapi.response(201, description="Creates an FRB VOEvent.")
# Process a new VOEvent (validate, send to Comet, send to Email, save to MongoDB)
async def create_voe(request: Request): # TODO: Shiny, should I add voe_event: VOEvent?
async def create_voe(request: Request):
"""Process a VOEvent.
Args:
Expand Down
4 changes: 2 additions & 2 deletions frbvoe/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import click

from frbvoe.cli.voe import voe
from frbvoe.cli.tns import tns
from frbvoe.cli.subscriber import subscriber
from frbvoe.cli.tns import tns
from frbvoe.cli.voe import voe


@click.group()
Expand Down
20 changes: 14 additions & 6 deletions frbvoe/cli/subscriber.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
"""Subscriber CLI."""

import click
from backend.subscriber import add_subscriber, delete_subscriber

@click.group(name="subscriber", help="Subscriber Tools.")
from frbvoe.backend.subscriber import add_subscriber, delete_subscriber


@click.group(name="subscriber", help="Subscriber Tools.")
def subscriber():
"""Manage subscribers."""
pass


@subscriber.command("add", help="Add a subscriber to the database.")
@click.option("--subscriber_name", help="Name of the subscriber.")
@click.option("--subscriber_email", help="Email address of the subscriber.")

def add(subscriber_name, subscriber_email):
"""Add subscriber."""
add_subscriber(subscriber_name, subscriber_email)
click.echo(f"Saved subscriber {subscriber_name} with email {subscriber_email} to the database.")

click.echo(
f"Saved subscriber {subscriber_name}"
f"with email {subscriber_email} to the database."
)


def delete(subscriber_name, subscriber_email):
"""Delete subscriber."""
delete_subscriber(subscriber_name, subscriber_email)
click.echo(f"De subscriber {subscriber_name} with email {subscriber_email} from the database.")
click.echo(
f"Deleted subscriber {subscriber_name}"
f"with email {subscriber_email} from the database."
)
11 changes: 4 additions & 7 deletions frbvoe/cli/tns.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,16 @@ def tns():
"""Manage workflow pipelines."""
pass


@tns.command("submit", help="Submit an FRB to the TNS.")
@click.option(
"--period",
default=10,
help="Proprietary period of the FRB.",
show_default=True
)
"--period", default=10, help="Proprietary period of the FRB.", show_default=True
)
@click.option(
"--sandbox",
help="Submit to the sandbox TNS (if True) or live TNS (if False).",
show_default=True,
)

)
def submit(proprietary_period, sandbox):
"""Submit an FRB to the TNS."""
TNS.submit(proprietary_period, sandbox)
16 changes: 4 additions & 12 deletions frbvoe/cli/voe.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,17 @@ def voe():
"""Manage workflow pipelines."""
pass


@voe.command("send", help="Send VOEvent.")
@click.option(
"--hostname",
default="localhost",
help="Destination to send the VOE."
)
@click.option(
"--port",
default=8098,
help="Port to send the VOE."
)
@click.option("--hostname", default="localhost", help="Destination to send the VOE.")
@click.option("--port", default=8098, help="Port to send the VOE.")
@click.option(
"--file",
default="./voe",
type=click.File("r"),
help="VOEvent file.",
show_default=True,
)

)
def send(hostname, port):
"""Send VOEvent."""
click.echo(f"Send VOEvent.{hostname}:{port}")
71 changes: 58 additions & 13 deletions frbvoe/models/tns.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
from typing import Any, Dict

import picologging as logging

# import requests
from pydantic import Field, SecretStr
import requests
from pydantic import Field
from pydantic_settings import SettingsConfigDict

from frbvoe.models.voe import VOEvent
Expand All @@ -18,6 +17,9 @@ class TNS(VOEvent):
"""Represents a TNS (Transient Name Server) object.
Tokenized Attributes:
period (float): Proprietary period (in years) of the event on the TNS.
Defaults to 1 year.
sandbox (bool): If True, use the TNS sandbox. Defaults to True.
tns_api_key (SecretStr): API key for the TNS. Required.
tns_report_id (SecretInt): Report ID for the TNS submission. Required.
tns_bot_name (SecretStr): Name of the TNS bot. Required.
Expand All @@ -32,17 +34,51 @@ class TNS(VOEvent):
# This parameter ignores any extra fields that are not defined in the model
extra="ignore",
)
tns_api_key: SecretStr = Field(
period: float = Field(
default=1,
gt=0.0,
lt=100.0,
description="""Proprietary period in years of the event on the TNS.
Defaults to 1 year.""",
example=2.5,
)
sandbox: bool = Field(
default=True,
description="""If True, use the TNS sandbox. Defaults to True.""",
example=True,
)
tns_api_key: str = Field( # consider changing to SecretStr
...,
description="API key for the TNS. Required.",
)
tns_report_id: int = Field(
..., description="Report ID for the TNS submission. Required."
)
tns_bot_name: SecretStr = Field(..., description="Name of the TNS bot. Required.")
tns_bot_name: str = Field(..., description="Name of the TNS bot. Required.")

@property
def submit(tns_report: Dict[str, Any]): # TODO
def search(tns_report: Dict[str, Any]):
"""Searches the TNS API for a specific event.
Args:
tns_report (Dict[str, Any]): The TNS report data to be searched.
Returns:
The response from the TNS API.
Raises:
requests.HTTPError: If the request to the TNS API fails.
"""
url = "http://0.0.0.0:4357/v1/voe/tns/search"
internal_name = tns_report["internal_name"]
print(f"Searching TNS for object with internal name '{internal_name}'")
tns_name = requests.post(url, json={"internal_name": internal_name}).json()[
"tns_name"
]
return tns_name

@property
def submit(tns_report: Dict[str, Any]):
"""Submits a VOEvent to the TNS API.
Args:
Expand All @@ -54,10 +90,19 @@ def submit(tns_report: Dict[str, Any]): # TODO
Raises:
requests.HTTPError: If the request to the TNS API fails.
"""
# headers = {"User-Agent": tns_marker}
# json_data = {"api_key": api_key, "data": voevent}
# log.info("Sending VOE payload to TNS.")
# response = requests.post(url, headers=headers, data=json_data)
# response.raise_for_status()
# return response
pass
# Make the JSON report
url = "https://sandbox.wis-tns.org/api/bulk-report-form"
headers = {"User-Agent": tns_report["tns_bot_name"]}
json_data = {"api_key": tns_report["tns_api_key"], "data": tns_report}
log.info("Sending VOE payload to TNS.")
resp = requests.post(url=url, headers=headers, json=json_data)
status = resp.status_code
assert status == 200, f"Bad response status code: {status}"
resp_json = resp.json()
print(f"Got response from backend: {resp_json}")
tns_name = resp_json["tns_name"]
assert (
tns_name is not None
), "TNS rejected submission, retain report ID if this persists."

return tns_name
43 changes: 11 additions & 32 deletions frbvoe/models/voe.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# from pydantic_settings import BaseSettings, SettingsConfigDict
from sanic import Request

from frbvoe.utilities.email import send_email # TODO: check this import
from frbvoe.utilities.email import send_email

logging.basicConfig()
log = logging.getLogger()
Expand Down Expand Up @@ -72,38 +72,20 @@ class VOEvent(BaseModel): # 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",
# )
comet_port: int = Field(
default=8098, description="Port of the Comet broker. Default is 8098. Optional."
)
email_password: SecretStr = Field(
default=None, description="VOEvent author email account password. Optional."
)
kind: Literal[
"detection",
"subsequent",
"retraction",
"update",
] = Field(..., description="Which kind of VOEvent. Required.", example="detection")
kind: Literal["detection", "subsequent", "retraction", "update"] = 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="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",
)
Expand Down Expand Up @@ -200,8 +182,7 @@ class VOEvent(BaseModel): # BaseSettings
default=None,
ge=0.0,
le=360.0,
description="""Right acension of the FRB in degrees
in degrees (0 < RA < 360). Required.""",
description="Right acension of the FRB in degrees (0 < RA < 360). Required.",
example=55.2938,
)
declination: float = Field(
Expand All @@ -221,8 +202,8 @@ class VOEvent(BaseModel): # BaseSettings
default=None,
ge=0.0,
le=1.0,
description="Importance of the FRB (0 < Importance < 1). Optional.",
example=0.9979,
description="Importance of the FRB (0 Importance 1). Optional.",
example=0.99,
)
website: Optional[StrictStr] = Field(
default=None,
Expand Down Expand Up @@ -255,10 +236,8 @@ def send_comet(comet_report: Dict[str, Any]):
comet_port (SecretInt) : Port of the comet broker. Optional
"""
log.info("Sending VOE payload to Comet as a report.")
# vp.dump(voevent=comet_report, xml_declaration=False, file="temp_voe.txt")
response = requests.post(
"http://comet:8098/", json=comet_report
) # TODO: check comet endpoint
response = requests.post("http://comet:8098/", json=comet_report)
# TODO: check comet endpoint
return response.status_code == 200

@property
Expand All @@ -274,7 +253,7 @@ def send_email(email_report: Dict[str, Any]):
log.info("Emailing VOE payload to subscribers.")
send_email(email_report)

@staticmethod # TODO: Shiny what's this for?
@staticmethod
async def compile(request: Request):
"""Extracts data from request and returns object.
Expand All @@ -290,4 +269,4 @@ async def compile(request: Request):
"""
await request.receive_body()
voe = request.json
return VOEvent(**voe)
return VOEvent(**voe)
7 changes: 7 additions & 0 deletions frbvoe/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ def create(name: str = "frbvoe", debug: bool = False) -> Sanic:
app.blueprint(voe_blueprint)
# ? Listeners
app.register_listener(mongo, "before_server_start")

# add an option for client(app).get("/shutdown") to shutdown the server
@app.route("/shutdown")
async def shutdown(request):
await app.ctx.mongo.close()
return app.text("Server shutting down...")

return app


Expand Down
Loading

0 comments on commit bab3d9e

Please sign in to comment.