Source code for astrodbkit.utils
"""Utility functions for Astrodbkit"""
import functools
import re
import warnings
from datetime import datetime
from decimal import Decimal
from astroquery.simbad import Simbad
__all__ = ["json_serializer", "get_simbad_names"]
[docs]
def deprecated_alias(**aliases):
"""
Decorator from StackOverflow
https://stackoverflow.com/questions/49802412/how-to-implement-deprecation-in-python-with-argument-alias
in order to handle deprecation of renamed columns
To use: add @deprecated_alias(old_name='new_name')
"""
def deco(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
rename_kwargs(f.__name__, kwargs, aliases)
return f(*args, **kwargs)
return wrapper
return deco
[docs]
def rename_kwargs(func_name, kwargs, aliases):
"""Helper function used be deprecated_alias"""
for alias, new in aliases.items():
if alias in kwargs:
if new in kwargs:
raise TypeError(f"{func_name} received both {alias} and {new}")
warnings.warn(f"{alias} is deprecated; use {new}", DeprecationWarning)
kwargs[new] = kwargs.pop(alias)
[docs]
def json_serializer(obj):
"""Function describing how things should be serialized in JSON.
Datetime objects are saved with datetime.isoformat(), Parameter class objects use clean_dict()
while all others use __dict__"""
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, Decimal):
return float(obj)
if isinstance(obj, bytes):
return obj.decode("utf-8")
return obj.__dict__
[docs]
def datetime_json_parser(json_dict):
"""Function to convert JSON dictionary objects to datetime when possible.
This is required to get datetime objects into the database.
Adapted from: https://stackoverflow.com/questions/8793448/how-to-convert-to-a-python-datetime-object-with-json-loads
"""
for key, value in json_dict.items():
if isinstance(value, str):
try:
json_dict[key] = datetime.fromisoformat(value)
except (ValueError, AttributeError):
pass
else:
pass
return json_dict
def _name_formatter(name):
"""
Clean up names of spurious formatting (extra spaces, some special characters)
Parameters
----------
name : str
Name to clean up
Returns
-------
Cleaned up name
"""
# Clean up multiple spaces
name = re.sub(r"\s\s+", " ", name)
# Clean up Simbad types
strings_to_delete = ["V* ", "EM* ", "NAME ", "** ", "Cl* ", "* "]
for pattern in strings_to_delete:
name = name.replace(pattern, "")
name = name.strip()
# Clean up 'hidden' names from Simbad
if "HIDDEN" in name.upper():
name = None
return name
[docs]
def get_simbad_names(name, verbose=False):
"""
Get list of alternate names from Simbad
Parameters
----------
name : str
Name to resolve
verbose : bool
Verbosity flag
Returns
-------
List of names
"""
t = Simbad.query_objectids(name)
if t is not None and len(t) > 0:
temp = [_name_formatter(s) for s in t["ID"].tolist()]
return [s for s in temp if s is not None and s != ""]
else:
if verbose:
print(f"No Simbad match for {name}")
return [name]