diff --git a/README.md b/README.md index 436c9247415e5212f0cb71803ef5488221a81772..9de81eed3331cd64d729eca0df52c30e79c3af90 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,34 @@ output_factory.write_file( ### Docker -Docker is the simplest install option. Find instructions [here](./localdev/local_development.md). +Docker is the simplest install option. + +1. Create and start a new container + + named `geomagio`, + listening on local port `8000`, + from the image `usgs/geomag-algorithms` on docker hub + + ``` + docker run -dit --name geomagio -p 8000:8000 usgs/geomag-algorithms + ``` + +2. Use the running container + +- Run the `geomag.py` command line interface: + + > To work with files outside the container, + > use a volume mount when starting the container + + ``` + docker exec -it geomagio geomag.py + ``` + +- Or, to run an interactive python prompt: + + ``` + docker exec -it geomagio python + ``` ## Algorithms diff --git a/code.json b/code.json index 0715617a11f874737de0119895b4a01fb69dc58b..bb37638f61c50d42e0fc91302e7c6d401d0f8ed6 100644 --- a/code.json +++ b/code.json @@ -3,7 +3,7 @@ "name": "geomag-algorithms", "organization": "U.S. Geological Survey", "description": "Library for processing Geomagnetic timeseries data.", - "version": "1.11.1", + "version": "1.12.1", "status": "Development", "permissions": { "usageType": "openSource", @@ -35,7 +35,7 @@ "email": "gs-haz_dev_team_group@usgs.gov" }, "date": { - "metadataLastUpdated": "2024-09-27" + "metadataLastUpdated": "2024-12-17" } } ] \ No newline at end of file diff --git a/docs/develop.md b/docs/develop.md index 932d5ed75c2763455a8be6501706dc5d2f52d7db..b9985919e8d964413884123747ffe4eedfdb7345 100644 --- a/docs/develop.md +++ b/docs/develop.md @@ -111,3 +111,6 @@ https://black.readthedocs.io/en/stable/the_black_code_style Resolve any rebase conflicts. If you have already pushed this branch to your fork, you *may* need to force push because branch history has changed. + +## Local Development +After you get everything installed, you can find further instructions on local development [here](../localdev/local_development.md). diff --git a/docs/install.md b/docs/install.md index 7e5e1fd7cd2c3676986d0cbb0ff277fb88bbeba8..1bc684aafbdb9987f648a965460905b168a7e45d 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,7 +1,7 @@ # Installation This document describes installation instructions for users. For those that wish to modify or develop custom code within **geomag-algorithms**, or prefer to install the Docker container, please see the following documents: > - [Develop](./develop.md) provides installation instruction for developers. -> - [Docker](../localdev/local_development.md) describes Docker container installation and usage. +> - [Docker](./install_docker.md) describes Docker container installation and usage. ## Requirements diff --git a/docs/metadata_webservice.md b/docs/metadata_webservice.md index 23600254ea9e16ba828b2cd1a7e611d699b8b6d5..9c0b5141becaac55e0c93bcad125ba2381376895 100644 --- a/docs/metadata_webservice.md +++ b/docs/metadata_webservice.md @@ -1,5 +1,41 @@ # Running the Metadata Webservice Locally +## Run mysql in a container (for local development) + +``` +docker run --rm --name mysql-db -e MYSQL_ROOT_PASSWORD=password -p 3306:3306 mysql:5.7 +``` + +This exposes port 3306 so python can connect locally. When running the webservice in a container, container links should be used so the container can access the database container. + +## Set up schema in database + +> This is only needed the first time the database is created. Volume mounts can make this more persistent. + +``` +export DATABASE_URL=mysql://root:password@localhost/geomag_operations +``` + +### Create mysql database +``` +docker exec -it mysql-db mysql -uroot -ppassword +``` +> Inside mysql container: +``` +CREATE DATABASE geomag_operations; +exit +``` + +``` +poetry run python create_db.py +``` + +### Add some testing data (depends on DATABASE_URL environment set above). + +``` +poetry run python test_metadata.py +``` + ## Set up OpenID application in code.usgs.gov. - Under your account, go to settings @@ -16,5 +52,21 @@ Scopes: `openid`, `profile`, `email` -## Running with Docker -[local_development.md](../localdev/local_development.md) describes Docker container installation and usage. +## Start webservice + +- Export variables used for authentication: + +``` +export DATABASE_URL=mysql://root:password@localhost/geomag_operations +export OPENID_CLIENT_ID={Application ID} +export OPENID_CLIENT_SECRET={Secret} +export OPENID_METADATA_URL=https://code.usgs.gov/.well-known/openid-configuration +export SECRET_KEY=changeme +export SECRET_SALT=salt +``` + +- Run app + +``` +poetry run uvicorn geomagio.api:app +``` diff --git a/geomagio/Metadata.py b/geomagio/Metadata.py deleted file mode 100644 index 2ce56f5e60c66eb1fccc5de4d6a94d3c6d74d6e2..0000000000000000000000000000000000000000 --- a/geomagio/Metadata.py +++ /dev/null @@ -1,1394 +0,0 @@ -"""Simulate metadata service until it is implemented. -""" - -from obspy import UTCDateTime - - -def get_instrument(observatory, start_time=None, end_time=None, metadata=None): - """Get instrument metadata - - Args: - observatory: observatory code - start_time: start time to match, or None to match any. - end_time: end time to match, or None to match any. - metadata: use custom list, defaults to _INSTRUMENT_METADATA - Returns: - list of matching metadata - """ - metadata = metadata or _INSTRUMENT_METADATA - return [ - m - for m in metadata - if m["station"] == observatory - and (end_time is None or m["start_time"] is None or m["start_time"] < end_time) - and (start_time is None or m["end_time"] is None or m["end_time"] > start_time) - ] - - -""" -To make this list easier to maintain: - - List NT network stations first, then other networks in alphabetical order - - Within networks, alphabetize by station, then start_time. - - When updating a metadata object, copy/paste the current one to the end of the list and update the endtime appropriately. - - Then update the existing object with the new information. -""" -_INSTRUMENT_METADATA = [ - { - "network": "NT", - "station": "BDT", - "start_time": None, - "end_time": UTCDateTime("2023-09-22T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 20613, "scale": 966.7624}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 944.1253}], - "W": [{"channel": "W_Volt", "offset": 47450, "scale": 975.5875}], - }, - "electronics": { - "serial": "E574", - # these scale values are calculated manually. - "x-scale": 966.7624, # nT/V - "y-scale": 944.1253, # nT/V - "z-scale": 975.5875, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0449", - # these constants combine with instrument setting for offset - "x-constant": 37027, # nT/mA - "y-constant": 36160, # nT/mA - "z-constant": 37365, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "BDT", - "start_time": UTCDateTime("2023-09-22T00:00:00.000Z"), - "end_time": UTCDateTime("2024-03-07T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 20729.5, "scale": 966.7624}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 944.1253}], - "W": [{"channel": "W_Volt", "offset": 47042.5, "scale": 975.5875}], - }, - "electronics": { - "serial": "E574", - # these scale values are calculated manually. - "x-scale": 966.7624, # nT/V - "y-scale": 944.1253, # nT/V - "z-scale": 975.5875, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0449", - # these constants combine with instrument setting for offset - "x-constant": 37027, # nT/mA - "y-constant": 36160, # nT/mA - "z-constant": 37365, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "BDT", - "start_time": UTCDateTime("2024-03-07T00:00:00.000Z"), - "end_time": None, - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 20724.67, "scale": 966.7624}], - "V": [{"channel": "V_Volt", "offset": -13.59, "scale": 944.1253}], - "W": [{"channel": "W_Volt", "offset": 47048.96, "scale": 975.5875}], - }, - "electronics": { - "serial": "E574", - # these scale values are calculated manually. - "x-scale": 966.7624, # nT/V - "y-scale": 944.1253, # nT/V - "z-scale": 975.5875, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0449", - # these constants combine with instrument setting for offset - "x-constant": 37027, # nT/mA - "y-constant": 36160, # nT/mA - "z-constant": 37365, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "BOU", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "BXX", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "BRT", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 506}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 505.6}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 506}, - ], - }, - }, - }, - { - "network": "NT", - "station": "BRW", - "start_time": UTCDateTime("2023-10-24T22:45:00.000Z"), - "end_time": None, - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 9214, "scale": 5797.3}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 5777.6}], - "W": [{"channel": "W_Volt", "offset": 37172, "scale": 5895.6}], - }, - "electronics": { - "serial": "????", - # these scale values are calculated manually. - "x-scale": 5797.3, # nT/V - "y-scale": 5777.6, # nT/V - "z-scale": 5895.6, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "????", - # these constants combine with instrument setting for offset - "x-constant": None, # nT/mA - "y-constant": None, # nT/mA - "z-constant": None, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "BSL", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "CMO", - "start_time": UTCDateTime("2023-10-27T16:20:00.000Z"), - "end_time": None, - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 12620, "scale": 967.7}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 969.7}], - "W": [{"channel": "W_Volt", "offset": 54907, "scale": 973.4}], - }, - "electronics": { - "serial": "E0568", - # these scale values are used to convert voltage - "x-scale": 967.7, # nT/V - "y-scale": 969.7, # nT/V - "z-scale": 973.4, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0443", - # these constants combine with instrument setting for offset - "x-constant": 37062, # nT/mA - "y-constant": 37141, # nT/mA - "z-constant": 37281, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "CMT", - "start_time": UTCDateTime("2023-10-26T21:00:00.000Z"), - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 99.4}, - {"channel": "U_Bin", "offset": 0, "scale": 502.5}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 101.5}, - {"channel": "V_Bin", "offset": 0, "scale": 512.5}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100.98}, - {"channel": "W_Bin", "offset": 0, "scale": 509.15}, - ], - }, - }, - }, - { - "network": "NT", - "station": "DED", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 508.20}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 508.40}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 508.03}, - ], - }, - }, - }, - { - "network": "NT", - "station": "FDT", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "FRD", - "start_time": None, - "end_time": UTCDateTime("2023-08-23T00:00:00.000Z"), - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "FRD", - "start_time": UTCDateTime("2023-08-23T00:00:00.000Z"), - "end_time": UTCDateTime("2023-08-30T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 21639, "scale": 978.4}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 971.0}], - "W": [{"channel": "W_Volt", "offset": 45573, "scale": 966.7}], - }, - "electronics": { - "serial": "E570", - # these scale values are used to convert voltage - "x-scale": 978.4, # nT/V - "y-scale": 971.0, # nT/V - "z-scale": 966.7, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0445", - # these constants combine with instrument setting for offset - "x-constant": 37474, # nT/mA - "y-constant": 37191, # nT/mA - "z-constant": 37025, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "FRD", - "start_time": UTCDateTime("2023-08-30T00:00:00.000Z"), - "end_time": UTCDateTime("2024-04-04T17:30:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 21639, "scale": 978.4}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 971.0}], - "W": [{"channel": "W_Volt", "offset": 45573, "scale": 966.7}], - }, - "electronics": { - "serial": "E570", - # these scale values are used to convert voltage - "x-scale": 978.4, # nT/V - "y-scale": 971.0, # nT/V - "z-scale": 966.7, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0445", - # these constants combine with instrument setting for offset - "x-constant": 37474, # nT/mA - "y-constant": 37191, # nT/mA - "z-constant": 37025, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "FRD", - "start_time": UTCDateTime("2024-04-04T17:30:00.000Z"), - "end_time": None, - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 21777, "scale": 978.4}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 971.0}], - "W": [{"channel": "W_Volt", "offset": 45426, "scale": 966.7}], - }, - "electronics": { - "serial": "E570", - # these scale values are used to convert voltage - "x-scale": 978.4, # nT/V - "y-scale": 971.0, # nT/V - "z-scale": 966.7, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0445", - # these constants combine with instrument setting for offset - "x-constant": 37474, # nT/mA - "y-constant": 37191, # nT/mA - "z-constant": 37025, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "FRN", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 98.48}, - {"channel": "U_Bin", "offset": 0, "scale": 497.50}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100.60}, - {"channel": "V_Bin", "offset": 0, "scale": 506}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 99}, - {"channel": "W_Bin", "offset": 0, "scale": 501}, - ], - }, - }, - }, - { - "network": "NT", - "station": "GUA", - "start_time": None, - "end_time": UTCDateTime("2024-02-26T03:00:00.000Z"), - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "GUA", - "start_time": UTCDateTime("2024-02-26T03:00:00.000Z"), - "end_time": UTCDateTime("2024-03-07T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 35975, "scale": 314.28}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 310.48}], - "W": [{"channel": "W_Volt", "offset": 7750, "scale": 317.5}], - }, - "electronics": { - "serial": "E0542", - # these scale values are used to convert voltage - "x-scale": 314.28, # V/nT - "y-scale": 310.48, # V/nT - "z-scale": 317.5, # V/nT - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0420", - # these constants combine with instrument setting for offset - "x-constant": 37085, # nT/mA - "y-constant": 36637, # nT/mA - "z-constant": 37465, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "GUA", - "start_time": UTCDateTime("2024-03-07T00:00:00.000Z"), - "end_time": None, - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 35976, "scale": 314.28}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 310.48}], - "W": [{"channel": "W_Volt", "offset": 7745, "scale": 317.5}], - }, - "electronics": { - "serial": "E0542", - # these scale values are used to convert voltage - "x-scale": 314.28, # V/nT - "y-scale": 310.48, # V/nT - "z-scale": 317.5, # V/nT - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0420", - # these constants combine with instrument setting for offset - "x-constant": 37085, # nT/mA - "y-constant": 36637, # nT/mA - "z-constant": 37465, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "GUT", - "start_time": None, - "end_time": UTCDateTime("2023-09-22T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 35989, "scale": 314.28}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 310.48}], - "W": [{"channel": "W_Volt", "offset": 7654, "scale": 317.5}], - }, - "electronics": { - "serial": "E0542", - # these scale values are used to convert voltage - "x-scale": 314.28, # V/nT - "y-scale": 310.48, # V/nT - "z-scale": 317.5, # V/nT - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0420", - # these constants combine with instrument setting for offset - "x-constant": 37085, # nT/mA - "y-constant": 36637, # nT/mA - "z-constant": 37465, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "GUT", - "start_time": UTCDateTime("2023-09-22T00:00:00.000Z"), - "end_time": UTCDateTime("2024-02-26T03:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 35975, "scale": 314.28}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 310.48}], - "W": [{"channel": "W_Volt", "offset": 7750, "scale": 317.5}], - }, - "electronics": { - "serial": "E0542", - # these scale values are used to convert voltage - "x-scale": 314.28, # V/nT - "y-scale": 310.48, # V/nT - "z-scale": 317.5, # V/nT - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0420", - # these constants combine with instrument setting for offset - "x-constant": 37085, # nT/mA - "y-constant": 36637, # nT/mA - "z-constant": 37465, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "GUT", - "start_time": UTCDateTime("2024-02-26T03:00:00.000Z"), - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "HON", - "start_time": None, - "end_time": UTCDateTime("2024-02-20T20:30:00.000Z"), - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "HON", - "start_time": UTCDateTime("2024-02-20T20:30:00.000Z"), - "end_time": UTCDateTime("2024-03-07T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 27126, "scale": 315.4}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 315.0}], - "W": [{"channel": "W_Volt", "offset": 21107.5, "scale": 311.7}], - }, - # this info should get updated when available - "electronics": { - "serial": "E558", - # these scale values are used to convert voltage - # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. - "x-scale": 315.4, # nT/V - "y-scale": 315.0, # nT/V - "z-scale": 311.7, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0428", - # these constants combine with instrument setting for offset - "x-constant": 37220, # nT/mA - "y-constant": 37175, # nT/mA - "z-constant": 36775, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "HON", - "start_time": UTCDateTime("2024-03-07T00:00:00.000Z"), - "end_time": None, - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 27126, "scale": 315.4}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 315.0}], - "W": [{"channel": "W_Volt", "offset": 21207.5, "scale": 311.7}], - }, - # this info should get updated when available - "electronics": { - "serial": "E558", - # these scale values are used to convert voltage - # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. - "x-scale": 315.4, # nT/V - "y-scale": 315.0, # nT/V - "z-scale": 311.7, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0428", - # these constants combine with instrument setting for offset - "x-constant": 37220, # nT/mA - "y-constant": 37175, # nT/mA - "z-constant": 36775, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "HOT", - "start_time": None, - "end_time": UTCDateTime("2022-07-14T16:07:30.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 0, "scale": 971.8}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 970.6}], - "W": [{"channel": "W_Volt", "offset": 0, "scale": 960.2}], - }, - # this info should get updated when available - "electronics": { - "serial": "E558", - # these scale values are used to convert voltage - # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. - "x-scale": 971.8, # nT/V - "y-scale": 970.6, # nT/V - "z-scale": 960.2, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0428", - # these constants combine with instrument setting for offset - "x-constant": 37220, # nT/mA - "y-constant": 37175, # nT/mA - "z-constant": 36775, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "HOT", - "start_time": UTCDateTime("2022-07-14T16:07:30.000Z"), - "end_time": UTCDateTime("2023-09-22T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 27123, "scale": 315.4}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 315.0}], - "W": [{"channel": "W_Volt", "offset": 21158, "scale": 311.7}], - }, - # this info should get updated when available - "electronics": { - "serial": "E558", - # these scale values are used to convert voltage - # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. - "x-scale": 315.4, # nT/V - "y-scale": 315.0, # nT/V - "z-scale": 311.7, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0428", - # these constants combine with instrument setting for offset - "x-constant": 37220, # nT/mA - "y-constant": 37175, # nT/mA - "z-constant": 36775, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "HOT", - "start_time": UTCDateTime("2023-09-22T00:00:00.000Z"), - "end_time": UTCDateTime("2024-02-20T20:30:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 27126, "scale": 315.4}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 315.0}], - "W": [{"channel": "W_Volt", "offset": 21107.5, "scale": 311.7}], - }, - # this info should get updated when available - "electronics": { - "serial": "E558", - # these scale values are used to convert voltage - # these are calculated using Ohm's law, given scaling resistor value, and given nT/mA values. - "x-scale": 315.4, # nT/V - "y-scale": 315.0, # nT/V - "z-scale": 311.7, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0428", - # these constants combine with instrument setting for offset - "x-constant": 37220, # nT/mA - "y-constant": 37175, # nT/mA - "z-constant": 36775, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "HOT", - "start_time": UTCDateTime("2024-02-20T20:30:00.000Z"), - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "NEW", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "LLO", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "SHU", - "start_time": None, - "end_time": UTCDateTime("2023-06-28T00:00:00.000Z"), - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 505}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 505}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 505}, - ], - }, - }, - }, - { - "network": "NT", - "station": "SHU", - "start_time": UTCDateTime("2023-06-28T00:00:00.000Z"), - "end_time": UTCDateTime("2023-09-07T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 19710, "scale": 944.935}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 964.909}], - "W": [{"channel": "W_Volt", "offset": 48068, "scale": 966.893}], - }, - # this info should get updated when available - "electronics": { - "serial": "E566", - # these scale values are used to convert voltage - # these are calculated using Ohm's law, given scaling resistor value (38.3 kohm), and given nT/mA values. - "x-scale": 944.935, # nT/V - "y-scale": 964.909, # nT/V - "z-scale": 966.893, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0441", - # these constants combine with instrument setting for offset - "x-constant": 36191, # nT/mA - "y-constant": 36956, # nT/mA - "z-constant": 37032, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "SHU", - "start_time": UTCDateTime("2023-09-07T00:00:00.000Z"), - "end_time": None, - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 19710, "scale": 975.1}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 969.4}], - "W": [{"channel": "W_Volt", "offset": 48068, "scale": 978.5}], - }, - # this info should get updated when available - "electronics": { - "serial": "E0598", - # these scale values are used to convert voltage - "x-scale": 975.1, # nT/V - "y-scale": 969.4, # nT/V - "z-scale": 978.5, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0460", - "x-constant": 37348, # nT/mA - "y-constant": 37127, # nT/mA - "z-constant": 37477, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "SIT", - "start_time": None, - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "SJG", - "start_time": None, - "end_time": UTCDateTime("2023-08-18T19:02:34.000Z"), - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "SJG", - "start_time": UTCDateTime("2023-08-18T19:02:34.000Z"), - "end_time": UTCDateTime("2023-08-30T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 27047, "scale": 313.2034}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 312.2797}], - "W": [{"channel": "W_Volt", "offset": 24288, "scale": 311.9576}], - }, - "electronics": { - "serial": "E0543", - # these scale values are calculated manually - "x-scale": 313.2034, # nT/V - "y-scale": 312.2797, # nT/V - "z-scale": 311.9576, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0419", - # these constants combine with instrument setting for offset - "x-constant": 36958, # nT/mA - "y-constant": 36849, # nT/mA - "z-constant": 36811, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "SJG", - "start_time": UTCDateTime("2023-08-30T00:00:00.000Z"), - "end_time": None, - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 26947.5, "scale": 313.2034}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 312.2797}], - "W": [{"channel": "W_Volt", "offset": 24690, "scale": 311.9576}], - }, - "electronics": { - "serial": "E0543", - # these scale values are calculated manually - "x-scale": 313.2034, # nT/V - "y-scale": 312.2797, # nT/V - "z-scale": 311.9576, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0419", - # these constants combine with instrument setting for offset - "x-constant": 36958, # nT/mA - "y-constant": 36849, # nT/mA - "z-constant": 36811, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "SJT", - "start_time": None, - "end_time": UTCDateTime("2023-08-18T19:02:34.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 27047, "scale": 313.2034}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 312.2797}], - "W": [{"channel": "W_Volt", "offset": 24288, "scale": 311.9576}], - }, - # this info should get updated when available - "electronics": { - "serial": "E0543", - # these scale values are calculated manually - "x-scale": 313.2034, # nT/V - "y-scale": 312.2797, # nT/V - "z-scale": 311.9576, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0419", - # these constants combine with instrument setting for offset - "x-constant": 36958, # nT/mA - "y-constant": 36849, # nT/mA - "z-constant": 36811, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "SJT", - "start_time": UTCDateTime("2023-08-18T19:02:34.000Z"), - "end_time": None, - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "TUC", - "start_time": None, - "end_time": UTCDateTime("2023-03-29T00:00:00.000Z"), - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 500}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 500}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 500}, - ], - }, - }, - }, - { - "network": "NT", - "station": "TUC", - "start_time": UTCDateTime("2023-03-29T00:00:00.000Z"), - "end_time": UTCDateTime("2023-08-30T00:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 24024, "scale": 978.355}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 965.901}], - "W": [{"channel": "W_Volt", "offset": 40040, "scale": 954.543}], - }, - # this info should get updated when available - "electronics": { - "serial": "E571", - # these scale values are calculated manually - "x-scale": 978.355, # nT/V - "y-scale": 965.901, # nT/V - "z-scale": 954.543, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0446", - # these constants combine with instrument setting for offset - "x-constant": 37471, # nT/mA - "y-constant": 36994, # nT/mA - "z-constant": 36559, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "TUC", - "start_time": UTCDateTime("2023-08-30T00:00:00.000Z"), - "end_time": None, - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 24016.5, "scale": 978.355}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 965.901}], - "W": [{"channel": "W_Volt", "offset": 39953.5, "scale": 954.543}], - }, - # this info should get updated when available - "electronics": { - "serial": "E571", - # these scale values are calculated manually - "x-scale": 978.355, # nT/V - "y-scale": 965.901, # nT/V - "z-scale": 954.543, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0446", - # these constants combine with instrument setting for offset - "x-constant": 37471, # nT/mA - "y-constant": 36994, # nT/mA - "z-constant": 36559, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "BRW", - "start_time": None, - "end_time": UTCDateTime("2023-10-23T20:00:00.000Z"), - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 100}, - {"channel": "U_Bin", "offset": 0, "scale": 506}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 100}, - {"channel": "V_Bin", "offset": 0, "scale": 505.6}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100}, - {"channel": "W_Bin", "offset": 0, "scale": 506}, - ], - }, - }, - }, - { - "network": "NT", - "station": "BRW", - "start_time": UTCDateTime("2023-10-23T19:00:00.000Z"), - "end_time": UTCDateTime("2023-10-24T22:45:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 9217, "scale": 5797.3}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 5777.6}], - "W": [{"channel": "W_Volt", "offset": 56442, "scale": 5895.6}], - }, - "electronics": { - "serial": "????", - # these scale values are calculated manually. - "x-scale": 5797.3, # nT/V - "y-scale": 5777.6, # nT/V - "z-scale": 5895.6, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "????", - # these constants combine with instrument setting for offset - "x-constant": None, # nT/mA - "y-constant": None, # nT/mA - "z-constant": None, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "CMO", - "start_time": None, - "end_time": UTCDateTime("2023-10-26T21:00:00.000Z"), - "instrument": { - "type": "Narod", - "channels": { - "U": [ - {"channel": "U_Volt", "offset": 0, "scale": 99.4}, - {"channel": "U_Bin", "offset": 0, "scale": 502.5}, - ], - "V": [ - {"channel": "V_Volt", "offset": 0, "scale": 101.5}, - {"channel": "V_Bin", "offset": 0, "scale": 512.5}, - ], - "W": [ - {"channel": "W_Volt", "offset": 0, "scale": 100.98}, - {"channel": "W_Bin", "offset": 0, "scale": 509.15}, - ], - }, - }, - }, - { - "network": "NT", - "station": "CMT", - "start_time": None, - "end_time": UTCDateTime("2023-10-26T21:00:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 0, "scale": 967.7}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 969.7}], - "W": [{"channel": "W_Volt", "offset": 0, "scale": 973.4}], - }, - "electronics": { - "serial": "E0568", - # these scale values are used to convert voltage - "x-scale": 967.7, # nT/V - "y-scale": 969.7, # nT/V - "z-scale": 973.4, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0443", - # these constants combine with instrument setting for offset - "x-constant": 37062, # nT/mA - "y-constant": 37141, # nT/mA - "z-constant": 37281, # nT/mA - }, - }, - }, - { - "network": "NT", - "station": "CMO", - "start_time": UTCDateTime("2023-10-26T21:00:00.000Z"), - "end_time": UTCDateTime("2023-10-27T16:20:00.000Z"), - "instrument": { - "type": "FGE", - "channels": { - # each channel maps to a list of components to calculate nT - # TODO: calculate these lists based on "FGE" type - "U": [{"channel": "U_Volt", "offset": 0, "scale": 967.7}], - "V": [{"channel": "V_Volt", "offset": 0, "scale": 969.7}], - "W": [{"channel": "W_Volt", "offset": 0, "scale": 973.4}], - }, - "electronics": { - "serial": "E0568", - # these scale values are used to convert voltage - "x-scale": 967.7, # nT/V - "y-scale": 969.7, # nT/V - "z-scale": 973.4, # nT/V - "temperature-scale": 0.01, # V/K - }, - "sensor": { - "serial": "S0443", - # these constants combine with instrument setting for offset - "x-constant": 37062, # nT/mA - "y-constant": 37141, # nT/mA - "z-constant": 37281, # nT/mA - }, - }, - }, -] diff --git a/geomagio/ObservatoryMetadata.py b/geomagio/ObservatoryMetadata.py index 735a232998d7deb57a7ed7a766c5c33b6e1b9528..91fcd14cb3467cf71c95101dabd479aa76ada798 100644 --- a/geomagio/ObservatoryMetadata.py +++ b/geomagio/ObservatoryMetadata.py @@ -38,7 +38,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "40.137", "geodetic_longitude": "254.763", "elevation": "1682", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 5527, "is_gin": False, @@ -57,7 +57,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "40.137", "geodetic_longitude": "254.763", "elevation": "1682", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 5527, "is_gin": False, @@ -76,7 +76,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "40.137", "geodetic_longitude": "254.763", "elevation": "1682", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 10000.0, "declination_base": 5527, "is_gin": False, @@ -95,7 +95,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "71.322", "geodetic_longitude": "203.378", "elevation": "10", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 10589, "is_gin": False, @@ -114,7 +114,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "71.322", "geodetic_longitude": "203.378", "elevation": "10", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 10000.0, "declination_base": 10589, "is_gin": False, @@ -133,7 +133,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "30.350", "geodetic_longitude": "270.365", "elevation": "8", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 215772, "is_gin": False, @@ -152,7 +152,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "64.874", "geodetic_longitude": "212.140", "elevation": "197", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 12151, "is_gin": False, @@ -171,7 +171,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "64.874", "geodetic_longitude": "212.140", "elevation": "197", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 10000.0, "declination_base": 12151, "is_gin": False, @@ -190,7 +190,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "70.355", "geodetic_longitude": "211.207", "elevation": "10", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 10755, "is_gin": False, @@ -209,7 +209,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "70.355", "geodetic_longitude": "211.207", "elevation": "10", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 10000.0, "declination_base": 10755, "is_gin": False, @@ -228,7 +228,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "38.205", "geodetic_longitude": "282.627", "elevation": "69", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 209690, "is_gin": False, @@ -247,7 +247,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "38.205", "geodetic_longitude": "282.627", "elevation": "69", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 209690, "is_gin": False, @@ -266,7 +266,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "37.091", "geodetic_longitude": "240.282", "elevation": "331", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 8097, "is_gin": False, @@ -285,7 +285,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "13.588", "geodetic_longitude": "144.867", "elevation": "140", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 764, "is_gin": False, @@ -304,7 +304,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "13.588", "geodetic_longitude": "144.867", "elevation": "140", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 764, "is_gin": False, @@ -323,7 +323,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "21.316", "geodetic_longitude": "202.000", "elevation": "4", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 5982, "is_gin": False, @@ -342,7 +342,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "21.316", "geodetic_longitude": "202.000", "elevation": "4", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 5982, "is_gin": False, @@ -361,8 +361,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "36.232", "geodetic_longitude": "140.186", "elevation": "36", - "sensor_orientation": "HDZF", - "reported": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 0.01, "declination_base": None, "is_gin": False, @@ -381,7 +380,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "48.265", "geodetic_longitude": "242.878", "elevation": "770", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 9547, "is_gin": False, @@ -400,7 +399,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "55.348", "geodetic_longitude": "199.538", "elevation": "80", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 7386, "is_gin": False, @@ -419,7 +418,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "57.058", "geodetic_longitude": "224.675", "elevation": "24", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 12349, "is_gin": False, @@ -438,7 +437,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "18.113", "geodetic_longitude": "293.849", "elevation": "424", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 208439, "is_gin": False, @@ -457,7 +456,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "18.113", "geodetic_longitude": "293.849", "elevation": "424", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 208439, "is_gin": False, @@ -476,7 +475,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "32.174", "geodetic_longitude": "249.267", "elevation": "946", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": 5863, "is_gin": False, @@ -495,7 +494,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "40.137", "geodetic_longitude": "254.764", "elevation": "1682", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -514,8 +513,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "64.300", "geodetic_longitude": "264.000", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -534,8 +532,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "49.600", "geodetic_longitude": "262.900", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -554,8 +551,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "69.200", "geodetic_longitude": "255.000", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -574,8 +570,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "55.300", "geodetic_longitude": "282.300", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -594,8 +589,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "58.800", "geodetic_longitude": "265.900", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -614,8 +608,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "51.000", "geodetic_longitude": "355.500", "elevation": "0", - "sensor_orientation": "HDZF", - "reported": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -634,8 +627,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "-34.400", "geodetic_longitude": "19.200", "elevation": "0", - "sensor_orientation": "HDZF", - "reported": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -654,8 +646,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "63.800", "geodetic_longitude": "291.500", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -674,8 +665,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "54.600", "geodetic_longitude": "246.700", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -694,8 +684,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "45.400", "geodetic_longitude": "284.500", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -714,8 +703,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "74.700", "geodetic_longitude": "265.100", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -734,8 +722,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "62.400", "geodetic_longitude": "245.500", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -754,8 +741,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "47.600", "geodetic_longitude": "307.300", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -774,8 +760,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "48.600", "geodetic_longitude": "236.600", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, @@ -794,8 +779,7 @@ DEFAULT_METADATA = { "geodetic_latitude": "62.400", "geodetic_longitude": "245.500", "elevation": "0", - "sensor_orientation": "XYZF", - "reported": "XYZF", + "sensor_orientation": "XYZ", "sensor_sampling_rate": 100.0, "declination_base": None, "is_gin": False, diff --git a/geomagio/api/app.py b/geomagio/api/app.py index 6cf83e96b3c6c65f909760d73a1892155f45bcee..d13f8b92be9a37c8547dd66ab9498568f98442c9 100644 --- a/geomagio/api/app.py +++ b/geomagio/api/app.py @@ -10,6 +10,7 @@ and can be run using uvicorn, or any other ASGI server: import logging import os +from contextlib import asynccontextmanager from fastapi import FastAPI from starlette.responses import RedirectResponse @@ -21,19 +22,20 @@ LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") if LOG_BASIC_CONFIG == "true": logging.basicConfig(level=LOG_LEVEL) -app = FastAPI() -app.mount("/ws/secure", secure.app) -app.mount("/ws", ws.app) - -@app.on_event("startup") -async def on_startup(): +@asynccontextmanager +async def lifespan(app: FastAPI): + # on startup await database.connect() + yield + # on shutdown + await database.disconnect() -@app.on_event("shutdown") -async def on_shutdown(): - await database.disconnect() +app = FastAPI(lifespan=lifespan) + +app.mount("/ws/secure", secure.app) +app.mount("/ws", ws.app) @app.get("/", include_in_schema=False) diff --git a/geomagio/api/secure/login.py b/geomagio/api/secure/login.py index 1d0eeff9941ace4b44ee8ac77f0f917a7f9694b8..e1e57477ff819f1797f32d72dfde4abffe778f0b 100644 --- a/geomagio/api/secure/login.py +++ b/geomagio/api/secure/login.py @@ -54,7 +54,7 @@ class User(BaseModel): """Information about a logged in user.""" email: str - sub: str # unique outh id + sub: int # unique outh id groups: List[str] = [] name: Optional[str] = None nickname: Optional[str] = None @@ -143,7 +143,6 @@ def require_user( if not user: # not logged in raise HTTPException( - detail=request.url_for("login"), headers={"Cache-Control": "no-cache"}, status_code=401, ) diff --git a/geomagio/api/ws/Observatory.py b/geomagio/api/ws/Observatory.py index 2b1797e0012f07e93ede82d586551e2cd948b173..158e1b4d9dc0de7ab76852fdd2ecfae12a1ac578 100644 --- a/geomagio/api/ws/Observatory.py +++ b/geomagio/api/ws/Observatory.py @@ -15,6 +15,7 @@ class Observatory(BaseModel): elevation: Optional[int] = None latitude: Optional[float] = None longitude: Optional[float] = None + sensor_sampling_rate: Optional[float] = None # Rather than use validator for populating the agency short name we resorted to using the __init__ function here because the validator mehtod would not overwrite the default None values assigned to agency above. # logic I followed is here https://stackoverflow.com/questions/76286148/how-do-custom-init-functions-work-in-pydantic-with-inheritance @@ -61,7 +62,7 @@ class Observatory(BaseModel): if agency == "GSC": sensor_orientation = "XYZF" else: - sensor_orientation = "HDZF" + sensor_orientation = "HDZ" return sensor_orientation def geojson(self) -> Dict: @@ -73,7 +74,7 @@ class Observatory(BaseModel): "agency": self.agency, "agency_name": self.agency_name, "sensor_orientation": self.sensor_orientation, - "sensor_sampling_rate": 0.01, + "sensor_sampling_rate": self.sensor_sampling_rate, "declination_base": self.declination_base, }, "geometry": ( @@ -103,6 +104,7 @@ for observatory_code, observatory_data in DEFAULT_METADATA.items(): agency_name=metadata["agency_name"], sensor_orientation=metadata["sensor_orientation"], declination_base=metadata.get("declination_base"), + sensor_sampling_rate=metadata["sensor_sampling_rate"], ) OBSERVATORIES.append(observatory) diff --git a/geomagio/metadata/MetadataFactory.py b/geomagio/metadata/MetadataFactory.py index 2ffdeda706cf20dd7e5b356d89d10a336cac6b91..3e3dce3f7af86a0a434ff5755c4ee85354ee1279 100644 --- a/geomagio/metadata/MetadataFactory.py +++ b/geomagio/metadata/MetadataFactory.py @@ -1,5 +1,6 @@ import os import requests +import datetime from typing import List, Union import json @@ -9,6 +10,9 @@ from pydantic import TypeAdapter from .Metadata import Metadata from .MetadataQuery import MetadataQuery +# Force IPV4 in requests package +requests.packages.urllib3.util.connection.HAS_IPV6 = False + # Set the API host and URL for the Geomagnetic Metadata service GEOMAG_API_HOST = os.getenv("GEOMAG_API_HOST", "geomag.usgs.gov") GEOMAG_API_URL = f"https://{GEOMAG_API_HOST}/ws/secure/metadata" @@ -155,7 +159,7 @@ class MetadataFactory(object): """ response = requests.post( url=self.url, - data=metadata.json(), + data=metadata.model_dump_json(), headers=self._get_headers(), timeout=timeout, ) @@ -183,7 +187,7 @@ class MetadataFactory(object): """ response = requests.put( url=f"{self.url}/{metadata.id}", - data=metadata.json(), + data=metadata.model_dump_json(), headers=self._get_headers(), timeout=timeout, ) @@ -209,7 +213,7 @@ def parse_params(query: MetadataQuery) -> str: for key in query.keys(): element = query[key] # Convert times to ISO format strings - if isinstance(element, UTCDateTime): + if isinstance(element, UTCDateTime) or isinstance(element, datetime.datetime): element = element.isoformat() # Serialize the metadata dictionary to a JSON string elif key == "metadata" and isinstance(element, dict): diff --git a/geomagio/metadata/instrument/Instrument.py b/geomagio/metadata/instrument/Instrument.py index 378ed7da0f2cf7107bcfb2eead7a28c0b413f836..4214667e8e7f1adae0a4c31d49e9ff699c156333 100644 --- a/geomagio/metadata/instrument/Instrument.py +++ b/geomagio/metadata/instrument/Instrument.py @@ -1,4 +1,4 @@ -from types import Optional +from typing import Optional from pydantic import BaseModel, Field from enum import Enum diff --git a/geomagio/processing/copy_absolutes.py b/geomagio/processing/copy_absolutes.py index a438c24644c71663829e92deb269181485578901..2addce461f9d35e7b4679f88dab0f232ea814f97 100644 --- a/geomagio/processing/copy_absolutes.py +++ b/geomagio/processing/copy_absolutes.py @@ -116,7 +116,7 @@ def create_reading_metadata(reading: Reading, created_by_label: str) -> Metadata category=MetadataCategory.READING, created_by=(created_by_label), endtime=max(measurement_times), - metadata=json.loads(reading.json()), + metadata=json.loads(reading.model_dump_json()), network="NT", starttime=min(measurement_times), station=reading.metadata["station"], diff --git a/geomagio/processing/copy_instrument.py b/geomagio/processing/copy_instrument.py index 32c2c71e779b119590eaa354987b07f991b2cc5b..1e0f0e582cde7b5ef5f4bfc638386237e32b5630 100644 --- a/geomagio/processing/copy_instrument.py +++ b/geomagio/processing/copy_instrument.py @@ -45,7 +45,7 @@ def copy_instrument( show_default="environment variable GITLAB_API_TOKEN", ), metadata_url: str = typer.Option( - default="https://staging-geomag.cr.usgs.gov/ws/secure/metadata", + default="https://geomag.usgs.gov/ws/secure/metadata", help="URL to metadata web service", metavar="URL", ), @@ -129,7 +129,7 @@ def create_metadata( category=MetadataCategory.INSTRUMENT, created_by=created_by_label, endtime=endtime, - metadata=metadata_class(**metadata), + metadata=(metadata_class(**metadata)).model_dump(), network="NT", location="R0", starttime=starttime, @@ -201,8 +201,7 @@ def upload_instrument_metadata( print("Updating metadata") return factory.update_metadata(metadata=instrument) - print("pretending to upload") - # return factory.create_metadata(metadata=instrument) + return factory.create_metadata(metadata=instrument) if __name__ == "__main__": diff --git a/localdev/local_development.md b/localdev/local_development.md index ae659a92f78f1f98dad4157d9c0847ff206b992b..487984eadcbe7a4d1f58e15f293feed89ad02ba1 100644 --- a/localdev/local_development.md +++ b/localdev/local_development.md @@ -4,10 +4,18 @@ This docker-compose uses the main Dockerfile to create a `localdev-web-1` container and creates a mysql container called `localdev-database-1` and an edge container called `localdev-edge-1`. ## Prerequisites +1. Download docker without Docker Desktop, at least version 27.0.1. + For mac development: 1. Download colima using homebrew. 2. Start colima and edit virtual machine sizes using `colima start --edit`. Increase the number of CPUs to 16 and the memory to 16. -3. Add the following env vars to your .bashrc or .zshrc or an .env file. See the instructions [here](../docs/metadata_webservice.md) for instructions on creating the OPENID_CLIENT_ID and OPENID_CLIENT_SECRET. The rest of the values can be set to strings of your choice. If you set the values in your .bashrc or .zshrc, run the source command to pick up the new values (ex `source ~/.bashrc`). + +For windows development: +1. Install Docker on WSL2. You can find instructions [here](https://docs.docker.com/engine/install/ubuntu/). + +For both OS: + +Add the following env vars to your .bashrc or .zshrc or an .env file. See the instructions [here](../docs/metadata_webservice.md) for instructions on creating the OPENID_CLIENT_ID and OPENID_CLIENT_SECRET. The rest of the values can be set to strings of your choice. If you set the values in your .bashrc or .zshrc, run the source command to pick up the new values (ex `source ~/.bashrc`). ``` export OPENID_CLIENT_ID="" export OPENID_CLIENT_SECRET="" @@ -17,15 +25,17 @@ export MYSQL_ROOT_PASSWORD="" ``` ## Use -To simply start build and run all the containers, make sure you are in the /localdev directory and run the following command. This includes a reload command for the web container. It will restart the web container when changes are made locally. +To simply build and run all the containers, make sure you are in the /localdev directory and run the following command. This includes a reload command for the web container. It will restart the web container when changes are made locally. ``` docker-compose up ``` +or `docker compose up` if you're not using the docker-compose plugin. If you're not developing locally, use the following command to run the containers in the background. Reload will not work this way. ``` -docker-compmose up -d +docker-compose up -d ``` +or `docker compose up -d` if not using the docker-compose plugin. ## Helpful Docker Commands `docker ps` shows the running containers. diff --git a/poetry.lock b/poetry.lock index 74cc612c809120f424e93dbb51e1c5fb26fda85a..d2d17532d28de155a8a215cf90f1dbc421d0a6b5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -38,13 +38,13 @@ docs = ["sphinx (==7.2.6)", "sphinx-mdinclude (==0.5.3)"] [[package]] name = "alembic" -version = "1.13.3" +version = "1.14.0" description = "A database migration tool for SQLAlchemy." optional = false python-versions = ">=3.8" files = [ - {file = "alembic-1.13.3-py3-none-any.whl", hash = "sha256:908e905976d15235fae59c9ac42c4c5b75cfcefe3d27c0fbf7ae15a37715d80e"}, - {file = "alembic-1.13.3.tar.gz", hash = "sha256:203503117415561e203aa14541740643a611f641517f0209fcae63e9fa09f1a2"}, + {file = "alembic-1.14.0-py3-none-any.whl", hash = "sha256:99bd884ca390466db5e27ffccff1d179ec5c05c965cfefc0607e69f9e411cb25"}, + {file = "alembic-1.14.0.tar.gz", hash = "sha256:b00892b53b3642d0b8dbedba234dbf1924b69be83a9a769d5a624b01094e304b"}, ] [package.dependencies] @@ -656,13 +656,13 @@ files = [ [[package]] name = "dparse" -version = "0.6.3" +version = "0.6.4" description = "A parser for Python dependency files" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "dparse-0.6.3-py3-none-any.whl", hash = "sha256:0d8fe18714056ca632d98b24fbfc4e9791d4e47065285ab486182288813a5318"}, - {file = "dparse-0.6.3.tar.gz", hash = "sha256:27bb8b4bcaefec3997697ba3f6e06b2447200ba273c0b085c3d012a04571b528"}, + {file = "dparse-0.6.4-py3-none-any.whl", hash = "sha256:fbab4d50d54d0e739fbb4dedfc3d92771003a5b9aa8545ca7a7045e3b174af57"}, + {file = "dparse-0.6.4.tar.gz", hash = "sha256:90b29c39e3edc36c6284c82c4132648eaf28a01863eb3c231c2512196132201a"}, ] [package.dependencies] @@ -670,18 +670,20 @@ packaging = "*" tomli = {version = "*", markers = "python_version < \"3.11\""} [package.extras] +all = ["pipenv", "poetry", "pyyaml"] conda = ["pyyaml"] -pipenv = ["pipenv (<=2022.12.19)"] +pipenv = ["pipenv"] +poetry = ["poetry"] [[package]] name = "et-xmlfile" -version = "1.1.0" +version = "2.0.0" description = "An implementation of lxml.xmlfile for the standard library" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"}, - {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"}, + {file = "et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa"}, + {file = "et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54"}, ] [[package]] @@ -700,13 +702,13 @@ test = ["pytest (>=6)"] [[package]] name = "fastapi" -version = "0.115.3" +version = "0.115.6" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi-0.115.3-py3-none-any.whl", hash = "sha256:8035e8f9a2b0aa89cea03b6c77721178ed5358e1aea4cd8570d9466895c0638c"}, - {file = "fastapi-0.115.3.tar.gz", hash = "sha256:c091c6a35599c036d676fa24bd4a6e19fa30058d93d950216cdc672881f6f7db"}, + {file = "fastapi-0.115.6-py3-none-any.whl", hash = "sha256:e9240b29e36fa8f4bb7290316988e90c381e5092e0cbe84e7818cc3713bcf305"}, + {file = "fastapi-0.115.6.tar.gz", hash = "sha256:9ec46f7addc14ea472958a96aae5b5de65f39721a46aaf5705c480d9a8b76654"}, ] [package.dependencies] @@ -720,59 +722,61 @@ standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "htt [[package]] name = "fonttools" -version = "4.54.1" +version = "4.55.3" description = "Tools to manipulate font files" optional = false python-versions = ">=3.8" files = [ - {file = "fonttools-4.54.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ed7ee041ff7b34cc62f07545e55e1468808691dddfd315d51dd82a6b37ddef2"}, - {file = "fonttools-4.54.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41bb0b250c8132b2fcac148e2e9198e62ff06f3cc472065dff839327945c5882"}, - {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7965af9b67dd546e52afcf2e38641b5be956d68c425bef2158e95af11d229f10"}, - {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:278913a168f90d53378c20c23b80f4e599dca62fbffae4cc620c8eed476b723e"}, - {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0e88e3018ac809b9662615072dcd6b84dca4c2d991c6d66e1970a112503bba7e"}, - {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4aa4817f0031206e637d1e685251ac61be64d1adef111060df84fdcbc6ab6c44"}, - {file = "fonttools-4.54.1-cp310-cp310-win32.whl", hash = "sha256:7e3b7d44e18c085fd8c16dcc6f1ad6c61b71ff463636fcb13df7b1b818bd0c02"}, - {file = "fonttools-4.54.1-cp310-cp310-win_amd64.whl", hash = "sha256:dd9cc95b8d6e27d01e1e1f1fae8559ef3c02c76317da650a19047f249acd519d"}, - {file = "fonttools-4.54.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5419771b64248484299fa77689d4f3aeed643ea6630b2ea750eeab219588ba20"}, - {file = "fonttools-4.54.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:301540e89cf4ce89d462eb23a89464fef50915255ece765d10eee8b2bf9d75b2"}, - {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ae5091547e74e7efecc3cbf8e75200bc92daaeb88e5433c5e3e95ea8ce5aa7"}, - {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82834962b3d7c5ca98cb56001c33cf20eb110ecf442725dc5fdf36d16ed1ab07"}, - {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d26732ae002cc3d2ecab04897bb02ae3f11f06dd7575d1df46acd2f7c012a8d8"}, - {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58974b4987b2a71ee08ade1e7f47f410c367cdfc5a94fabd599c88165f56213a"}, - {file = "fonttools-4.54.1-cp311-cp311-win32.whl", hash = "sha256:ab774fa225238986218a463f3fe151e04d8c25d7de09df7f0f5fce27b1243dbc"}, - {file = "fonttools-4.54.1-cp311-cp311-win_amd64.whl", hash = "sha256:07e005dc454eee1cc60105d6a29593459a06321c21897f769a281ff2d08939f6"}, - {file = "fonttools-4.54.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:54471032f7cb5fca694b5f1a0aaeba4af6e10ae989df408e0216f7fd6cdc405d"}, - {file = "fonttools-4.54.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fa92cb248e573daab8d032919623cc309c005086d743afb014c836636166f08"}, - {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a911591200114969befa7f2cb74ac148bce5a91df5645443371aba6d222e263"}, - {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93d458c8a6a354dc8b48fc78d66d2a8a90b941f7fec30e94c7ad9982b1fa6bab"}, - {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5eb2474a7c5be8a5331146758debb2669bf5635c021aee00fd7c353558fc659d"}, - {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9c563351ddc230725c4bdf7d9e1e92cbe6ae8553942bd1fb2b2ff0884e8b714"}, - {file = "fonttools-4.54.1-cp312-cp312-win32.whl", hash = "sha256:fdb062893fd6d47b527d39346e0c5578b7957dcea6d6a3b6794569370013d9ac"}, - {file = "fonttools-4.54.1-cp312-cp312-win_amd64.whl", hash = "sha256:e4564cf40cebcb53f3dc825e85910bf54835e8a8b6880d59e5159f0f325e637e"}, - {file = "fonttools-4.54.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6e37561751b017cf5c40fce0d90fd9e8274716de327ec4ffb0df957160be3bff"}, - {file = "fonttools-4.54.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:357cacb988a18aace66e5e55fe1247f2ee706e01debc4b1a20d77400354cddeb"}, - {file = "fonttools-4.54.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e953cc0bddc2beaf3a3c3b5dd9ab7554677da72dfaf46951e193c9653e515a"}, - {file = "fonttools-4.54.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58d29b9a294573d8319f16f2f79e42428ba9b6480442fa1836e4eb89c4d9d61c"}, - {file = "fonttools-4.54.1-cp313-cp313-win32.whl", hash = "sha256:9ef1b167e22709b46bf8168368b7b5d3efeaaa746c6d39661c1b4405b6352e58"}, - {file = "fonttools-4.54.1-cp313-cp313-win_amd64.whl", hash = "sha256:262705b1663f18c04250bd1242b0515d3bbae177bee7752be67c979b7d47f43d"}, - {file = "fonttools-4.54.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ed2f80ca07025551636c555dec2b755dd005e2ea8fbeb99fc5cdff319b70b23b"}, - {file = "fonttools-4.54.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9dc080e5a1c3b2656caff2ac2633d009b3a9ff7b5e93d0452f40cd76d3da3b3c"}, - {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d152d1be65652fc65e695e5619e0aa0982295a95a9b29b52b85775243c06556"}, - {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8583e563df41fdecef31b793b4dd3af8a9caa03397be648945ad32717a92885b"}, - {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0d1d353ef198c422515a3e974a1e8d5b304cd54a4c2eebcae708e37cd9eeffb1"}, - {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:fda582236fee135d4daeca056c8c88ec5f6f6d88a004a79b84a02547c8f57386"}, - {file = "fonttools-4.54.1-cp38-cp38-win32.whl", hash = "sha256:e7d82b9e56716ed32574ee106cabca80992e6bbdcf25a88d97d21f73a0aae664"}, - {file = "fonttools-4.54.1-cp38-cp38-win_amd64.whl", hash = "sha256:ada215fd079e23e060157aab12eba0d66704316547f334eee9ff26f8c0d7b8ab"}, - {file = "fonttools-4.54.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f5b8a096e649768c2f4233f947cf9737f8dbf8728b90e2771e2497c6e3d21d13"}, - {file = "fonttools-4.54.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e10d2e0a12e18f4e2dd031e1bf7c3d7017be5c8dbe524d07706179f355c5dac"}, - {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31c32d7d4b0958600eac75eaf524b7b7cb68d3a8c196635252b7a2c30d80e986"}, - {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c39287f5c8f4a0c5a55daf9eaf9ccd223ea59eed3f6d467133cc727d7b943a55"}, - {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a7a310c6e0471602fe3bf8efaf193d396ea561486aeaa7adc1f132e02d30c4b9"}, - {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d3b659d1029946f4ff9b6183984578041b520ce0f8fb7078bb37ec7445806b33"}, - {file = "fonttools-4.54.1-cp39-cp39-win32.whl", hash = "sha256:e96bc94c8cda58f577277d4a71f51c8e2129b8b36fd05adece6320dd3d57de8a"}, - {file = "fonttools-4.54.1-cp39-cp39-win_amd64.whl", hash = "sha256:e8a4b261c1ef91e7188a30571be6ad98d1c6d9fa2427244c545e2fa0a2494dd7"}, - {file = "fonttools-4.54.1-py3-none-any.whl", hash = "sha256:37cddd62d83dc4f72f7c3f3c2bcf2697e89a30efb152079896544a93907733bd"}, - {file = "fonttools-4.54.1.tar.gz", hash = "sha256:957f669d4922f92c171ba01bef7f29410668db09f6c02111e22b2bce446f3285"}, + {file = "fonttools-4.55.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1dcc07934a2165ccdc3a5a608db56fb3c24b609658a5b340aee4ecf3ba679dc0"}, + {file = "fonttools-4.55.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f7d66c15ba875432a2d2fb419523f5d3d347f91f48f57b8b08a2dfc3c39b8a3f"}, + {file = "fonttools-4.55.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e4ae3592e62eba83cd2c4ccd9462dcfa603ff78e09110680a5444c6925d841"}, + {file = "fonttools-4.55.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62d65a3022c35e404d19ca14f291c89cc5890032ff04f6c17af0bd1927299674"}, + {file = "fonttools-4.55.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d342e88764fb201286d185093781bf6628bbe380a913c24adf772d901baa8276"}, + {file = "fonttools-4.55.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:dd68c87a2bfe37c5b33bcda0fba39b65a353876d3b9006fde3adae31f97b3ef5"}, + {file = "fonttools-4.55.3-cp310-cp310-win32.whl", hash = "sha256:1bc7ad24ff98846282eef1cbeac05d013c2154f977a79886bb943015d2b1b261"}, + {file = "fonttools-4.55.3-cp310-cp310-win_amd64.whl", hash = "sha256:b54baf65c52952db65df39fcd4820668d0ef4766c0ccdf32879b77f7c804d5c5"}, + {file = "fonttools-4.55.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8c4491699bad88efe95772543cd49870cf756b019ad56294f6498982408ab03e"}, + {file = "fonttools-4.55.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5323a22eabddf4b24f66d26894f1229261021dacd9d29e89f7872dd8c63f0b8b"}, + {file = "fonttools-4.55.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5480673f599ad410695ca2ddef2dfefe9df779a9a5cda89503881e503c9c7d90"}, + {file = "fonttools-4.55.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da9da6d65cd7aa6b0f806556f4985bcbf603bf0c5c590e61b43aa3e5a0f822d0"}, + {file = "fonttools-4.55.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e894b5bd60d9f473bed7a8f506515549cc194de08064d829464088d23097331b"}, + {file = "fonttools-4.55.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:aee3b57643827e237ff6ec6d28d9ff9766bd8b21e08cd13bff479e13d4b14765"}, + {file = "fonttools-4.55.3-cp311-cp311-win32.whl", hash = "sha256:eb6ca911c4c17eb51853143624d8dc87cdcdf12a711fc38bf5bd21521e79715f"}, + {file = "fonttools-4.55.3-cp311-cp311-win_amd64.whl", hash = "sha256:6314bf82c54c53c71805318fcf6786d986461622dd926d92a465199ff54b1b72"}, + {file = "fonttools-4.55.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f9e736f60f4911061235603a6119e72053073a12c6d7904011df2d8fad2c0e35"}, + {file = "fonttools-4.55.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7a8aa2c5e5b8b3bcb2e4538d929f6589a5c6bdb84fd16e2ed92649fb5454f11c"}, + {file = "fonttools-4.55.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07f8288aacf0a38d174445fc78377a97fb0b83cfe352a90c9d9c1400571963c7"}, + {file = "fonttools-4.55.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8d5e8916c0970fbc0f6f1bece0063363bb5857a7f170121a4493e31c3db3314"}, + {file = "fonttools-4.55.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ae3b6600565b2d80b7c05acb8e24d2b26ac407b27a3f2e078229721ba5698427"}, + {file = "fonttools-4.55.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:54153c49913f45065c8d9e6d0c101396725c5621c8aee744719300f79771d75a"}, + {file = "fonttools-4.55.3-cp312-cp312-win32.whl", hash = "sha256:827e95fdbbd3e51f8b459af5ea10ecb4e30af50221ca103bea68218e9615de07"}, + {file = "fonttools-4.55.3-cp312-cp312-win_amd64.whl", hash = "sha256:e6e8766eeeb2de759e862004aa11a9ea3d6f6d5ec710551a88b476192b64fd54"}, + {file = "fonttools-4.55.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a430178ad3e650e695167cb53242dae3477b35c95bef6525b074d87493c4bf29"}, + {file = "fonttools-4.55.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:529cef2ce91dc44f8e407cc567fae6e49a1786f2fefefa73a294704c415322a4"}, + {file = "fonttools-4.55.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e75f12c82127486fac2d8bfbf5bf058202f54bf4f158d367e41647b972342ca"}, + {file = "fonttools-4.55.3-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:859c358ebf41db18fb72342d3080bce67c02b39e86b9fbcf1610cca14984841b"}, + {file = "fonttools-4.55.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:546565028e244a701f73df6d8dd6be489d01617863ec0c6a42fa25bf45d43048"}, + {file = "fonttools-4.55.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:aca318b77f23523309eec4475d1fbbb00a6b133eb766a8bdc401faba91261abe"}, + {file = "fonttools-4.55.3-cp313-cp313-win32.whl", hash = "sha256:8c5ec45428edaa7022f1c949a632a6f298edc7b481312fc7dc258921e9399628"}, + {file = "fonttools-4.55.3-cp313-cp313-win_amd64.whl", hash = "sha256:11e5de1ee0d95af4ae23c1a138b184b7f06e0b6abacabf1d0db41c90b03d834b"}, + {file = "fonttools-4.55.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:caf8230f3e10f8f5d7593eb6d252a37caf58c480b19a17e250a63dad63834cf3"}, + {file = "fonttools-4.55.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b586ab5b15b6097f2fb71cafa3c98edfd0dba1ad8027229e7b1e204a58b0e09d"}, + {file = "fonttools-4.55.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8c2794ded89399cc2169c4d0bf7941247b8d5932b2659e09834adfbb01589aa"}, + {file = "fonttools-4.55.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf4fe7c124aa3f4e4c1940880156e13f2f4d98170d35c749e6b4f119a872551e"}, + {file = "fonttools-4.55.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:86721fbc389ef5cc1e2f477019e5069e8e4421e8d9576e9c26f840dbb04678de"}, + {file = "fonttools-4.55.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:89bdc5d88bdeec1b15af790810e267e8332d92561dce4f0748c2b95c9bdf3926"}, + {file = "fonttools-4.55.3-cp38-cp38-win32.whl", hash = "sha256:bc5dbb4685e51235ef487e4bd501ddfc49be5aede5e40f4cefcccabc6e60fb4b"}, + {file = "fonttools-4.55.3-cp38-cp38-win_amd64.whl", hash = "sha256:cd70de1a52a8ee2d1877b6293af8a2484ac82514f10b1c67c1c5762d38073e56"}, + {file = "fonttools-4.55.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bdcc9f04b36c6c20978d3f060e5323a43f6222accc4e7fcbef3f428e216d96af"}, + {file = "fonttools-4.55.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c3ca99e0d460eff46e033cd3992a969658c3169ffcd533e0a39c63a38beb6831"}, + {file = "fonttools-4.55.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22f38464daa6cdb7b6aebd14ab06609328fe1e9705bb0fcc7d1e69de7109ee02"}, + {file = "fonttools-4.55.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed63959d00b61959b035c7d47f9313c2c1ece090ff63afea702fe86de00dbed4"}, + {file = "fonttools-4.55.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5e8d657cd7326eeaba27de2740e847c6b39dde2f8d7cd7cc56f6aad404ddf0bd"}, + {file = "fonttools-4.55.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:fb594b5a99943042c702c550d5494bdd7577f6ef19b0bc73877c948a63184a32"}, + {file = "fonttools-4.55.3-cp39-cp39-win32.whl", hash = "sha256:dc5294a3d5c84226e3dbba1b6f61d7ad813a8c0238fceea4e09aa04848c3d851"}, + {file = "fonttools-4.55.3-cp39-cp39-win_amd64.whl", hash = "sha256:aedbeb1db64496d098e6be92b2e63b5fac4e53b1b92032dfc6988e1ea9134a4d"}, + {file = "fonttools-4.55.3-py3-none-any.whl", hash = "sha256:f412604ccbeee81b091b420272841e5ec5ef68967a9790e80bffd0e30b8e2977"}, + {file = "fonttools-4.55.3.tar.gz", hash = "sha256:3983313c2a04d6cc1fe9251f8fc647754cf49a61dac6cb1e7249ae67afaafc45"}, ] [package.extras] @@ -1369,13 +1373,13 @@ source = ["Cython (>=3.0.11)"] [[package]] name = "mako" -version = "1.3.6" +version = "1.3.8" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." optional = false python-versions = ">=3.8" files = [ - {file = "Mako-1.3.6-py3-none-any.whl", hash = "sha256:a91198468092a2f1a0de86ca92690fb0cfc43ca90ee17e15d93662b4c04b241a"}, - {file = "mako-1.3.6.tar.gz", hash = "sha256:9ec3a1583713479fae654f83ed9fa8c9a4c16b7bb0daba0e6bbebff50c0d983d"}, + {file = "Mako-1.3.8-py3-none-any.whl", hash = "sha256:42f48953c7eb91332040ff567eb7eea69b22e7a4affbc5ba8e845e8f730f6627"}, + {file = "mako-1.3.8.tar.gz", hash = "sha256:577b97e414580d3e088d47c2dbbe9594aa7a5146ed2875d4dfa9075af2dd3cc8"}, ] [package.dependencies] @@ -1688,13 +1692,13 @@ typing-extensions = ">=3.7.4" [[package]] name = "packaging" -version = "24.1" +version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] [[package]] @@ -2073,13 +2077,13 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "7.4.4" +version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, + {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, ] [package.dependencies] @@ -2087,11 +2091,29 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +pluggy = ">=1.5,<2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-asyncio" +version = "0.24.0" +description = "Pytest support for asyncio" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b"}, + {file = "pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276"}, +] + +[package.dependencies] +pytest = ">=8.2,<9" [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] name = "pytest-cov" @@ -2111,6 +2133,23 @@ pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +[[package]] +name = "pytest-mock" +version = "3.14.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, + {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -2379,33 +2418,33 @@ test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeo [[package]] name = "setuptools" -version = "75.2.0" +version = "75.3.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"}, - {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, + {file = "setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd"}, + {file = "setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686"}, ] [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.12.*)", "pytest-mypy"] [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] @@ -2525,13 +2564,13 @@ SQLAlchemy = ">=0.9.0" [[package]] name = "starlette" -version = "0.41.0" +version = "0.41.3" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.41.0-py3-none-any.whl", hash = "sha256:a0193a3c413ebc9c78bff1c3546a45bb8c8bcb4a84cae8747d650a65bd37210a"}, - {file = "starlette-0.41.0.tar.gz", hash = "sha256:39cbd8768b107d68bfe1ff1672b38a2c38b49777de46d2a592841d58e3bf7c2a"}, + {file = "starlette-0.41.3-py3-none-any.whl", hash = "sha256:44cedb2b7c77a9de33a8b74b2b90e9f50d11fcf25d8270ea525ad71a25374ff7"}, + {file = "starlette-0.41.3.tar.gz", hash = "sha256:0e4ab3d16522a255be6b28260b938eae2482f98ce5cc934cb08dce8dc3ba5835"}, ] [package.dependencies] @@ -2543,13 +2582,43 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7 [[package]] name = "tomli" -version = "2.0.2" +version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" files = [ - {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, - {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] @@ -2574,13 +2643,13 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6. [[package]] name = "types-python-dateutil" -version = "2.9.0.20241003" +version = "2.9.0.20241206" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.8" files = [ - {file = "types-python-dateutil-2.9.0.20241003.tar.gz", hash = "sha256:58cb85449b2a56d6684e41aeefb4c4280631246a0da1a719bdbe6f3fb0317446"}, - {file = "types_python_dateutil-2.9.0.20241003-py3-none-any.whl", hash = "sha256:250e1d8e80e7bbc3a6c99b907762711d1a1cdd00e978ad39cb5940f6f0a87f3d"}, + {file = "types_python_dateutil-2.9.0.20241206-py3-none-any.whl", hash = "sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53"}, + {file = "types_python_dateutil-2.9.0.20241206.tar.gz", hash = "sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb"}, ] [[package]] @@ -2916,4 +2985,4 @@ pycurl = ["pycurl"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.12" -content-hash = "fd766e42eaeb0d161fb69ba57b8df09adbf265f37bd0f65321bfad3aee9f2130" +content-hash = "5d6aca195743faf8f75339d35cda6989c5cafeaa07beb5c26511411f4dd77236" diff --git a/pyproject.toml b/pyproject.toml index cf5cbc54a8ec015debf2dfc960fceac362ad6a3b..d9ef175b026facbd7178e9f9ad308c08e77e211f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ packages = [ {include = "geomagio" } ] repository="https://code.usgs.gov/ghsc/geomag/geomag-algorithms" -version = "1.11.1" +version = "1.12.1" [tool.poetry.dependencies] @@ -51,8 +51,10 @@ black = "^24.3.0" isort = "^5.10.1" mypy = "^0.982" poethepoet = "^0.16.4" -pytest = "^7.1.3" +pytest = "^8.3.4" pytest-cov = "^4.0.0" +pytest-asyncio = "^0.24.0" +pytest-mock = "^3.14.0" safety = "^2.2.0" # type hints data-science-types = "^0.2.23" diff --git a/pytest.ini b/pytest.ini index 34aed1adcac890918324838e3dd99c8f1fce0e66..3d8cf70409816af31181c2160f79f4d3b8b4b17e 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,7 +1,5 @@ [pytest] norecursedirs = */site-packages testpaths = test -filterwarnings = - # This happens in many qutebrowser dependencies... - ignore:Using or importing the ABCs from 'collections'.*:DeprecationWarning - ignore:the imp module is deprecated in favour of importlib.*:DeprecationWarning \ No newline at end of file +asyncio_mode=auto +asyncio_default_fixture_loop_scope="function" diff --git a/test/ObservatoryMetadata_test.py b/test/ObservatoryMetadata_test.py index ca3d5ada427824296aef9b8547a27b8c828a5448..795a0128e7129645455b5da3064a0b586347e4de 100644 --- a/test/ObservatoryMetadata_test.py +++ b/test/ObservatoryMetadata_test.py @@ -13,7 +13,7 @@ METADATA = { "geodetic_latitude": "-90", "geodetic_longitude": "-180", "elevation": "-1000", - "sensor_orientation": "HDZF", + "sensor_orientation": "HDZ", "sensor_sampling_rate": "0.01 second", "declination_base": 20000, "is_gin": False, diff --git a/test/api_test/secure_test/login_test.py b/test/api_test/secure_test/login_test.py new file mode 100644 index 0000000000000000000000000000000000000000..6097219b51dcd50d2116893b4e63e06a0034f27d --- /dev/null +++ b/test/api_test/secure_test/login_test.py @@ -0,0 +1,268 @@ +import pytest +import httpx +from unittest.mock import ANY +from fastapi.testclient import TestClient +from authlib.integrations.base_client.errors import MismatchingStateError +from requests import Response + +from geomagio.api.secure import app +from geomagio.api.secure.SessionMiddleware import SessionMiddleware +from geomagio.api.secure.login import User + +client = TestClient(app) + + +@pytest.fixture() +def valid_token(): + return { + "access_token": "test_access_token", + "token_type": "Bearer", + "expires_in": 7200, + "refresh_token": "test_refresh_toekn", + "scope": "openid email profile", + "created_at": 1733244369, + "id_token": "test_id_token", + "expires_at": 1733251569, + "userinfo": { + "iss": "http://test_url", + "sub": "1234", + "aud": "test_aud", + "exp": 1733244489, + "iat": 1733244369, + "nonce": "test_nonce", + "auth_time": 1733244368, + "sub_legacy": "test_sub_legacy", + "name": "test_user", + "nickname": "test_user_nickname", + "preferred_username": "test_preferred_username", + "email": "test_email", + "email_verified": True, + "profile": "http://test_url/user", + "picture": "http://picture_url", + "groups_direct": ["group1", "group2"], + }, + } + + +@pytest.fixture() +def valid_userinfo(): + return { + "sub": "1234", + "sub_legacy": "test_sub_legacy", + "name": "test_user", + "nickname": "test_user_nickname", + "preferred_username": "test_preferred_username", + "email": "test_email", + "email_verified": True, + "profile": "http://test_url/user", + "picture": "http://picture_url", + "groups": ["group1", "group2"], + } + + +@pytest.fixture() +def valid_gitlab_user(): + return { + "id": 1234, + "email": "test_email", + "name": "test_user", + "username": "test_user_nickname", + "avatar_url": "http://picture_url", + } + + +@pytest.mark.asyncio +async def test_authorization_valid(valid_token, valid_userinfo, mocker): + + mock_authorize = mocker.AsyncMock(return_value=valid_token) + mocker.patch( + "geomagio.api.secure.login.oauth.openid.authorize_access_token", mock_authorize + ) + + mock_userinfo = mocker.AsyncMock(return_value=valid_userinfo) + mocker.patch("geomagio.api.secure.login.oauth.openid.userinfo", mock_userinfo) + + mock_save_session = mocker.AsyncMock() + mocker.patch.object(SessionMiddleware, "save_session", mock_save_session) + + response = client.get("/authorize") + assert response.status_code == 200 + + valid_session = { + "token": valid_token, + "user": valid_userinfo, + } + + # assert the session data is correct + mock_save_session.assert_called_once_with(ANY, valid_session) + + +@pytest.mark.asyncio +async def test_authorization_invalid_authorize_access_token(): + # assert that requests directly to GET /authorize cause an exception + with pytest.raises(MismatchingStateError) as err: + client.get("/authorize") + + assert ( + str(err.value) + == "mismatching_state: CSRF Warning! State not equal in request and response." + ) + + +@pytest.mark.asyncio +async def test_login_redirects(mocker): + mock_save_session = mocker.AsyncMock() + mocker.patch.object(SessionMiddleware, "save_session", mock_save_session) + + mock_redirect = mocker.AsyncMock(return_value={"status_code": 302}) + mocker.patch( + "geomagio.api.secure.login.oauth.openid.authorize_redirect", mock_redirect + ) + + header = "https://testserver/ws/secure/metadata/1" + client.get("/login", headers={"Referer": header}) + + # assert oauth is called with the correct redirect url + mock_redirect.assert_called_once_with( + ANY, "https://testserver/ws/secure/authorize", prompt="login" + ) + + # assert session is saved with correct referrer header + mock_save_session.assert_called_once_with(ANY, {"after_authorize_redirect": header}) + + +@pytest.mark.asyncio +async def test_logout(valid_token, valid_userinfo, mocker): + valid_session = {"token": valid_token, "user": valid_userinfo} + mock_get_session = mocker.AsyncMock(return_value=valid_session) + mocker.patch.object(SessionMiddleware, "get_session", mock_get_session) + + mock_delete_session = mocker.AsyncMock() + mocker.patch.object(SessionMiddleware, "delete_session", mock_delete_session) + + client.get(url="/logout", headers={"Cookie": "PHPSESSID=valid_session_id"}) + + mock_get_session.assert_called_once_with("valid_session_id") + mock_delete_session.assert_called_once_with("valid_session_id") + + +@pytest.mark.asyncio +async def test_user_with_valid_session(valid_token, valid_userinfo, mocker): + valid_session = {"token": valid_token, "user": valid_userinfo} + mock_get_session = mocker.AsyncMock(return_value=valid_session) + mocker.patch.object(SessionMiddleware, "get_session", mock_get_session) + + mock_save_session = mocker.AsyncMock(return_value=valid_session) + mocker.patch.object(SessionMiddleware, "save_session", mock_save_session) + + response = client.get(url="/user", headers={"Cookie": "PHPSESSID=valid_session_id"}) + + assert response.status_code == 200 + mock_get_session.assert_called_once_with("valid_session_id") + + user = User(**response.json()) + assert user.email == "test_email" + assert user.sub == 1234 + assert user.groups == ["group1", "group2"] + + +@pytest.mark.asyncio +async def test_user_with_no_session_and_valid_token( + valid_token, valid_userinfo, valid_gitlab_user, mocker +): + valid_user_response = httpx.Response(status_code=200, json=valid_gitlab_user) + + valid_groups = [ + { + "id": 1, + "full_path": "group1", + }, + {"id": 2, "full_path": "group2"}, + ] + + valid_groups_response = httpx.Response(status_code=200, json=valid_groups) + + mock_gitlab_request = mocker.AsyncMock( + side_effect=[ + valid_user_response, + valid_groups_response, + httpx.Response(status_code=200, json={}), + ] + ) + mocker.patch("httpx.AsyncClient.get", mock_gitlab_request) + + valid_session = {"token": valid_token, "user": valid_userinfo} + + mock_save_session = mocker.AsyncMock(return_value=valid_session) + mocker.patch.object(SessionMiddleware, "save_session", mock_save_session) + + response = client.get(url="/user", headers={"Authorization": "valid_gitlab_token"}) + + session_user = { + "email": "test_email", + "sub": 1234, + "groups": ["group1", "group2"], + "name": "test_user", + "nickname": "test_user_nickname", + "picture": "http://picture_url", + } + + assert response.status_code == 200 + mock_save_session.assert_called_once_with(ANY, {"user": session_user}) + + user = User(**response.json()) + assert user.email == "test_email" + assert user.sub == 1234 + assert user.groups == ["group1", "group2"] + + +@pytest.mark.asyncio +async def test_user_with_no_session(mocker): + mock_get_session = mocker.AsyncMock() + mocker.patch.object(SessionMiddleware, "get_session", mock_get_session) + + # do not pass in cookie + response = client.get(url="/user") + assert response.status_code == 401 + + mock_get_session.assert_not_called() + + +@pytest.mark.asyncio +async def test_user_with_no_session_and_invalid_token(mocker): + mock_get_session = mocker.AsyncMock() + mocker.patch.object(SessionMiddleware, "get_session", mock_get_session) + + mock_gitlab_request = mocker.AsyncMock(return_value=None) + mocker.patch("geomagio.api.secure.login.get_gitlab_user", mock_gitlab_request) + + # do not pass in cookie + response = client.get( + url="/user", headers={"Authorization": "invalid_gitlab_token"} + ) + assert response.status_code == 401 + + mock_get_session.assert_not_called() + mock_gitlab_request.assert_called_once_with(token="invalid_gitlab_token") + + +@pytest.mark.asyncio +async def test_user_invalid_session(mocker): + # mock invalid session. this is created when users GET /metadata without logging in + invalid_session = { + "redirect_uri": "redirect_uri", + "nonce": "nonce_str", + "url": "test_url", + } + mock_get_session = mocker.AsyncMock(return_value=invalid_session) + mocker.patch.object(SessionMiddleware, "get_session", mock_get_session) + + mock_save_session = mocker.AsyncMock() + mocker.patch.object(SessionMiddleware, "save_session", mock_save_session) + + response = client.get( + url="/user", headers={"Cookie": "PHPSESSID=invalid_session_id"} + ) + + assert response.status_code == 401 + mock_get_session.assert_called_once_with("invalid_session_id") diff --git a/test/api_test/ws_test/elements_test.py b/test/api_test/ws_test/elements_test.py new file mode 100644 index 0000000000000000000000000000000000000000..5549fb76f7c0db2155369e57d9c0581e1da9ae04 --- /dev/null +++ b/test/api_test/ws_test/elements_test.py @@ -0,0 +1,22 @@ +from fastapi.testclient import TestClient + +from geomagio.api.ws import app + +client = TestClient(app) + + +def test_get_elements(): + response = client.get("/elements/") + + assert response.status_code == 200 + + body = response.json() + assert body["type"] == "FeatureCollection" + + elements = body["features"] + for e in elements: + assert e["type"] == "Feature" + assert e["id"] != None + assert e["properties"]["name"] != None + assert e["properties"]["units"] != None + assert e["geometry"] == None diff --git a/test/api_test/ws_test/observatories_test.py b/test/api_test/ws_test/observatories_test.py new file mode 100644 index 0000000000000000000000000000000000000000..dbe95cda17342936a88b3c6080f6c156907dd2b3 --- /dev/null +++ b/test/api_test/ws_test/observatories_test.py @@ -0,0 +1,41 @@ +from fastapi.testclient import TestClient + +from geomagio.api.ws import app + +client = TestClient(app) + + +def test_get_all_observatories(): + response = client.get("/observatories/") + + assert response.status_code == 200 + body = response.json() + assert body["type"] == "FeatureCollection" + + observatories = body["features"] + for o in observatories: + assert o["type"] == "Feature" + assert o["id"] != None + assert o["properties"]["name"] != None + assert o["properties"]["agency"] != None + assert o["properties"]["agency_name"] != None + assert o["properties"]["sensor_orientation"] != None + assert o["properties"]["sensor_sampling_rate"] != None + + +def test_get_observatory_by_id(): + response = client.get("/observatories/SIT") + + assert response.status_code == 200 + + body = response.json() + assert body["type"] == "Feature" + assert body["id"] == "SIT" + assert body["properties"]["name"] == "Sitka" + assert body["properties"]["agency"] == "USGS" + assert body["properties"]["agency_name"] == "United States Geological Survey (USGS)" + assert body["properties"]["sensor_orientation"] == "HDZ" + assert body["properties"]["sensor_sampling_rate"] == 100.0 + assert body["properties"]["declination_base"] == 12349 + assert body["geometry"]["type"] == "Point" + assert body["geometry"]["coordinates"] == [224.675, 57.058, 24] diff --git a/test/api_test/ws_test/variometers_test.py b/test/api_test/ws_test/variometers_test.py new file mode 100644 index 0000000000000000000000000000000000000000..c8b90cd90796e8cbd834a83fa3c7d4526e464b49 --- /dev/null +++ b/test/api_test/ws_test/variometers_test.py @@ -0,0 +1,44 @@ +from fastapi.testclient import TestClient + +from geomagio.api.ws import app + +client = TestClient(app) + + +def test_get_all_variometers(): + response = client.get("/variometers/") + + assert response.status_code == 200 + body = response.json() + assert body["type"] == "FeatureCollection" + + variometers = body["features"] + for v in variometers: + assert v["type"] == "Feature" + assert v["id"] != None + assert v["properties"]["name"] != None + assert v["properties"]["agency"] != None + assert v["properties"]["agency_name"] != None + assert v["properties"]["sensor_orientation"] != None + assert v["properties"]["sensor_sampling_rate"] == None + assert v["properties"]["declination_base"] == None + assert v["geometry"]["type"] == "Point" + assert len(v["geometry"]["coordinates"]) > 0 + + +def test_get_variometer_by_id(): + response = client.get("/variometers/DWPF") + + assert response.status_code == 200 + + body = response.json() + assert body["type"] == "Feature" + assert body["id"] == "DWPF" + assert body["properties"]["name"] == "Disney Wilderness Preserve, Florida, USA" + assert body["properties"]["agency"] == "USGS" + assert body["properties"]["agency_name"] == "United States Geological Survey (USGS)" + assert body["properties"]["sensor_orientation"] == "HDZ" + assert body["properties"]["sensor_sampling_rate"] == None + assert body["properties"]["declination_base"] == None + assert body["geometry"]["type"] == "Point" + assert body["geometry"]["coordinates"] == [-81.4327, 28.1103, 30] diff --git a/test/iaga2002_test/IAGA2002Parser_test.py b/test/iaga2002_test/IAGA2002Parser_test.py index 8cfde259f8eca7ba9997d58eeb80d0f744e5be78..04ccc9c3a5818059dd72f2e218eea0d5284a75b3 100644 --- a/test/iaga2002_test/IAGA2002Parser_test.py +++ b/test/iaga2002_test/IAGA2002Parser_test.py @@ -12,7 +12,7 @@ IAGA2002_EXAMPLE = """ Format IAGA-2002 Geodetic Longitude 254.764 | Elevation 1682 | Reported HDZF | - Sensor Orientation HDZF | + Sensor Orientation HDZ | Digital Sampling 0.01 second | Data Interval Type filtered 1-minute (00:15-01:45) | Data Type variation | diff --git a/test/imfjson_test/IMFJSONWriter_test.py b/test/imfjson_test/IMFJSONWriter_test.py index ff8b19d6d91bb7f341fc93ef7674317214d827ec..7792ded4542886badb21f24529776e48ebd412a7 100644 --- a/test/imfjson_test/IMFJSONWriter_test.py +++ b/test/imfjson_test/IMFJSONWriter_test.py @@ -27,8 +27,10 @@ def test_metadata(): assert_equal(metadata["status"], 200) # Test intermagnet parameters intermag = metadata["intermagnet"] - assert_equal(intermag["reported_orientation"], "HDZF") - assert_equal(intermag["sensor_orientation"], "HDZF") + assert_equal(intermag["reported_orientation"], "".join(EXAMPLE_CHANNELS)) + assert intermag[ + "sensor_orientation" + ] # writer does not validate Iaga2002 data, so assert for existence of values instead. assert_equal(intermag["data_type"], "variation") assert_equal(intermag["sampling_period"], 60) assert_equal(intermag["digital_sampling_rate"], 0.01) diff --git a/test/metadata/MetadataFactory_test.py b/test/metadata/MetadataFactory_test.py new file mode 100644 index 0000000000000000000000000000000000000000..cde42da539556cdabe34dff1d6e8d2a1ff57509f --- /dev/null +++ b/test/metadata/MetadataFactory_test.py @@ -0,0 +1,31 @@ +import datetime +from obspy import UTCDateTime + +from geomagio.metadata import MetadataQuery +from geomagio.metadata.MetadataFactory import parse_params + + +def test_parse_params_with_UTCDateTime(): + query = MetadataQuery( + station="TUC", + starttime=UTCDateTime(2024, 11, 7), + endtime=UTCDateTime(2024, 11, 8), + ) + + params = parse_params(query) + + assert params["starttime"] == "2024-11-07T00:00:00+00:00" + assert params["endtime"] == "2024-11-08T00:00:00+00:00" + + +def test_parse_params_with_datetime(): + query = MetadataQuery( + station="TUC", + starttime=datetime.datetime(2024, 11, 7), + endtime=datetime.datetime(2024, 11, 8), + ) + + params = parse_params(query) + + assert params["starttime"] == "2024-11-07T00:00:00+00:00" + assert params["endtime"] == "2024-11-08T00:00:00+00:00"