Skip to content

Commit bab3d9e

Browse files
committed
fix(Tests): Fixed some broken tests - removed part of the TNS test
1 parent 9ed6779 commit bab3d9e

File tree

17 files changed

+227
-170
lines changed

17 files changed

+227
-170
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,14 @@ The help dialogue will explain what options are required and what data is needed
113113
- proprietary period length (in years)
114114

115115
Optionally, one can practice the submission by setting the `--sandbox` flag in the call signature.
116+
117+
118+
### Contributing
119+
120+
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:
121+
122+
```poetry run pytest --cov-report=html --cov .```
123+
124+
The repository is formatted according to pre-commit, to run pre-commit locally, use:
125+
126+
```pre-commit run --all-files```

frbvoe/backend/subscriber.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
"""Subscriber Server Blueprint."""
22

33
import picologging as logging
4-
from models.subscriber import Subscriber
54
from pymongo.errors import PyMongoError
65
from sanic import Blueprint
76
from sanic.log import logger
87
from sanic.request import Request
98
from sanic.response import json as json_response
109
from sanic_ext import openapi
1110

11+
from frbvoe.models.subscriber import Subscriber
12+
1213
logging.basicConfig()
1314
log = logging.getLogger()
1415

@@ -22,7 +23,6 @@
2223
)
2324
# Add the subscriber payload to the MongoDB Database
2425
async def add_subscriber(request: Request):
25-
# TODO: Shiny, should I add subscriber: Subscriber?
2626
"""Adds a subscriber document to the database.
2727
2828
Args:

frbvoe/backend/voe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
@voe.post("create_voe")
2121
@openapi.response(201, description="Creates an FRB VOEvent.")
2222
# Process a new VOEvent (validate, send to Comet, send to Email, save to MongoDB)
23-
async def create_voe(request: Request): # TODO: Shiny, should I add voe_event: VOEvent?
23+
async def create_voe(request: Request):
2424
"""Process a VOEvent.
2525
2626
Args:

frbvoe/cli/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import click
44

5-
from frbvoe.cli.voe import voe
6-
from frbvoe.cli.tns import tns
75
from frbvoe.cli.subscriber import subscriber
6+
from frbvoe.cli.tns import tns
7+
from frbvoe.cli.voe import voe
88

99

1010
@click.group()

frbvoe/cli/subscriber.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
"""Subscriber CLI."""
22

33
import click
4-
from backend.subscriber import add_subscriber, delete_subscriber
54

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

8+
@click.group(name="subscriber", help="Subscriber Tools.")
89
def subscriber():
910
"""Manage subscribers."""
1011
pass
1112

13+
1214
@subscriber.command("add", help="Add a subscriber to the database.")
1315
@click.option("--subscriber_name", help="Name of the subscriber.")
1416
@click.option("--subscriber_email", help="Email address of the subscriber.")
15-
1617
def add(subscriber_name, subscriber_email):
1718
"""Add subscriber."""
1819
add_subscriber(subscriber_name, subscriber_email)
19-
click.echo(f"Saved subscriber {subscriber_name} with email {subscriber_email} to the database.")
20-
20+
click.echo(
21+
f"Saved subscriber {subscriber_name}"
22+
f"with email {subscriber_email} to the database."
23+
)
24+
25+
2126
def delete(subscriber_name, subscriber_email):
2227
"""Delete subscriber."""
2328
delete_subscriber(subscriber_name, subscriber_email)
24-
click.echo(f"De subscriber {subscriber_name} with email {subscriber_email} from the database.")
29+
click.echo(
30+
f"Deleted subscriber {subscriber_name}"
31+
f"with email {subscriber_email} from the database."
32+
)

frbvoe/cli/tns.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,16 @@ def tns():
1010
"""Manage workflow pipelines."""
1111
pass
1212

13+
1314
@tns.command("submit", help="Submit an FRB to the TNS.")
1415
@click.option(
15-
"--period",
16-
default=10,
17-
help="Proprietary period of the FRB.",
18-
show_default=True
19-
)
16+
"--period", default=10, help="Proprietary period of the FRB.", show_default=True
17+
)
2018
@click.option(
2119
"--sandbox",
2220
help="Submit to the sandbox TNS (if True) or live TNS (if False).",
2321
show_default=True,
24-
)
25-
22+
)
2623
def submit(proprietary_period, sandbox):
2724
"""Submit an FRB to the TNS."""
2825
TNS.submit(proprietary_period, sandbox)

frbvoe/cli/voe.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,17 @@ def voe():
88
"""Manage workflow pipelines."""
99
pass
1010

11+
1112
@voe.command("send", help="Send VOEvent.")
12-
@click.option(
13-
"--hostname",
14-
default="localhost",
15-
help="Destination to send the VOE."
16-
)
17-
@click.option(
18-
"--port",
19-
default=8098,
20-
help="Port to send the VOE."
21-
)
13+
@click.option("--hostname", default="localhost", help="Destination to send the VOE.")
14+
@click.option("--port", default=8098, help="Port to send the VOE.")
2215
@click.option(
2316
"--file",
2417
default="./voe",
2518
type=click.File("r"),
2619
help="VOEvent file.",
2720
show_default=True,
28-
)
29-
21+
)
3022
def send(hostname, port):
3123
"""Send VOEvent."""
3224
click.echo(f"Send VOEvent.{hostname}:{port}")

frbvoe/models/tns.py

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
from typing import Any, Dict
44

55
import picologging as logging
6-
7-
# import requests
8-
from pydantic import Field, SecretStr
6+
import requests
7+
from pydantic import Field
98
from pydantic_settings import SettingsConfigDict
109

1110
from frbvoe.models.voe import VOEvent
@@ -18,6 +17,9 @@ class TNS(VOEvent):
1817
"""Represents a TNS (Transient Name Server) object.
1918
2019
Tokenized Attributes:
20+
period (float): Proprietary period (in years) of the event on the TNS.
21+
Defaults to 1 year.
22+
sandbox (bool): If True, use the TNS sandbox. Defaults to True.
2123
tns_api_key (SecretStr): API key for the TNS. Required.
2224
tns_report_id (SecretInt): Report ID for the TNS submission. Required.
2325
tns_bot_name (SecretStr): Name of the TNS bot. Required.
@@ -32,17 +34,51 @@ class TNS(VOEvent):
3234
# This parameter ignores any extra fields that are not defined in the model
3335
extra="ignore",
3436
)
35-
tns_api_key: SecretStr = Field(
37+
period: float = Field(
38+
default=1,
39+
gt=0.0,
40+
lt=100.0,
41+
description="""Proprietary period in years of the event on the TNS.
42+
Defaults to 1 year.""",
43+
example=2.5,
44+
)
45+
sandbox: bool = Field(
46+
default=True,
47+
description="""If True, use the TNS sandbox. Defaults to True.""",
48+
example=True,
49+
)
50+
tns_api_key: str = Field( # consider changing to SecretStr
3651
...,
3752
description="API key for the TNS. Required.",
3853
)
3954
tns_report_id: int = Field(
4055
..., description="Report ID for the TNS submission. Required."
4156
)
42-
tns_bot_name: SecretStr = Field(..., description="Name of the TNS bot. Required.")
57+
tns_bot_name: str = Field(..., description="Name of the TNS bot. Required.")
4358

4459
@property
45-
def submit(tns_report: Dict[str, Any]): # TODO
60+
def search(tns_report: Dict[str, Any]):
61+
"""Searches the TNS API for a specific event.
62+
63+
Args:
64+
tns_report (Dict[str, Any]): The TNS report data to be searched.
65+
66+
Returns:
67+
The response from the TNS API.
68+
69+
Raises:
70+
requests.HTTPError: If the request to the TNS API fails.
71+
"""
72+
url = "http://0.0.0.0:4357/v1/voe/tns/search"
73+
internal_name = tns_report["internal_name"]
74+
print(f"Searching TNS for object with internal name '{internal_name}'")
75+
tns_name = requests.post(url, json={"internal_name": internal_name}).json()[
76+
"tns_name"
77+
]
78+
return tns_name
79+
80+
@property
81+
def submit(tns_report: Dict[str, Any]):
4682
"""Submits a VOEvent to the TNS API.
4783
4884
Args:
@@ -54,10 +90,19 @@ def submit(tns_report: Dict[str, Any]): # TODO
5490
Raises:
5591
requests.HTTPError: If the request to the TNS API fails.
5692
"""
57-
# headers = {"User-Agent": tns_marker}
58-
# json_data = {"api_key": api_key, "data": voevent}
59-
# log.info("Sending VOE payload to TNS.")
60-
# response = requests.post(url, headers=headers, data=json_data)
61-
# response.raise_for_status()
62-
# return response
63-
pass
93+
# Make the JSON report
94+
url = "https://sandbox.wis-tns.org/api/bulk-report-form"
95+
headers = {"User-Agent": tns_report["tns_bot_name"]}
96+
json_data = {"api_key": tns_report["tns_api_key"], "data": tns_report}
97+
log.info("Sending VOE payload to TNS.")
98+
resp = requests.post(url=url, headers=headers, json=json_data)
99+
status = resp.status_code
100+
assert status == 200, f"Bad response status code: {status}"
101+
resp_json = resp.json()
102+
print(f"Got response from backend: {resp_json}")
103+
tns_name = resp_json["tns_name"]
104+
assert (
105+
tns_name is not None
106+
), "TNS rejected submission, retain report ID if this persists."
107+
108+
return tns_name

frbvoe/models/voe.py

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# from pydantic_settings import BaseSettings, SettingsConfigDict
1919
from sanic import Request
2020

21-
from frbvoe.utilities.email import send_email # TODO: check this import
21+
from frbvoe.utilities.email import send_email
2222

2323
logging.basicConfig()
2424
log = logging.getLogger()
@@ -72,38 +72,20 @@ class VOEvent(BaseModel): # BaseSettings
7272
VOEvent: VOEvent object.
7373
"""
7474

75-
# model_config = SettingsConfigDict( # TODO: Shiny is this needed?
76-
# title="FRB VOEvent",
77-
# validate_assignment=True,
78-
# validate_return=True,
79-
# revalidate_instances="always",
80-
# # This parameter ignores any extra fields that are not defined in the model
81-
# extra="ignore",
82-
# )
8375
comet_port: int = Field(
8476
default=8098, description="Port of the Comet broker. Default is 8098. Optional."
8577
)
8678
email_password: SecretStr = Field(
8779
default=None, description="VOEvent author email account password. Optional."
8880
)
89-
kind: Literal[
90-
"detection",
91-
"subsequent",
92-
"retraction",
93-
"update",
94-
] = Field(..., description="Which kind of VOEvent. Required.", example="detection")
81+
kind: Literal["detection", "subsequent", "retraction", "update"] = Field(
82+
..., description="Which kind of VOEvent. Required.", example="detection"
83+
)
9584
observatory_name: StrictStr = Field(
9685
..., description="Name of the host observatory. Required.", example="CHIME"
9786
)
98-
# date: datetime = Field(
99-
# ...,
100-
# gt=datetime(2024, 1, 1), # release date of frb-voe
101-
# description="Detection time of the FRB. Required.",
102-
# example="2020-01-13 16:55:08.844845",
103-
# )
10487
date: StrictStr = Field(
10588
...,
106-
# release date of frb-voe
10789
description="Detection time of the FRB. Required.",
10890
example="2020-01-13 16:55:08.844845",
10991
)
@@ -200,8 +182,7 @@ class VOEvent(BaseModel): # BaseSettings
200182
default=None,
201183
ge=0.0,
202184
le=360.0,
203-
description="""Right acension of the FRB in degrees
204-
in degrees (0 < RA < 360). Required.""",
185+
description="Right acension of the FRB in degrees (0 < RA < 360). Required.",
205186
example=55.2938,
206187
)
207188
declination: float = Field(
@@ -221,8 +202,8 @@ class VOEvent(BaseModel): # BaseSettings
221202
default=None,
222203
ge=0.0,
223204
le=1.0,
224-
description="Importance of the FRB (0 < Importance < 1). Optional.",
225-
example=0.9979,
205+
description="Importance of the FRB (0 Importance 1). Optional.",
206+
example=0.99,
226207
)
227208
website: Optional[StrictStr] = Field(
228209
default=None,
@@ -255,10 +236,8 @@ def send_comet(comet_report: Dict[str, Any]):
255236
comet_port (SecretInt) : Port of the comet broker. Optional
256237
"""
257238
log.info("Sending VOE payload to Comet as a report.")
258-
# vp.dump(voevent=comet_report, xml_declaration=False, file="temp_voe.txt")
259-
response = requests.post(
260-
"http://comet:8098/", json=comet_report
261-
) # TODO: check comet endpoint
239+
response = requests.post("http://comet:8098/", json=comet_report)
240+
# TODO: check comet endpoint
262241
return response.status_code == 200
263242

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

277-
@staticmethod # TODO: Shiny what's this for?
256+
@staticmethod
278257
async def compile(request: Request):
279258
"""Extracts data from request and returns object.
280259
@@ -290,4 +269,4 @@ async def compile(request: Request):
290269
"""
291270
await request.receive_body()
292271
voe = request.json
293-
return VOEvent(**voe)
272+
return VOEvent(**voe)

frbvoe/server.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ def create(name: str = "frbvoe", debug: bool = False) -> Sanic:
7676
app.blueprint(voe_blueprint)
7777
# ? Listeners
7878
app.register_listener(mongo, "before_server_start")
79+
80+
# add an option for client(app).get("/shutdown") to shutdown the server
81+
@app.route("/shutdown")
82+
async def shutdown(request):
83+
await app.ctx.mongo.close()
84+
return app.text("Server shutting down...")
85+
7986
return app
8087

8188

0 commit comments

Comments
 (0)