From 849d26df8109702c3803a19a3a0ef01c53029186 Mon Sep 17 00:00:00 2001 From: Shravya A <53599350+sysknock@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:38:53 +0530 Subject: [PATCH 1/6] api-tests1 --- examples/api_test/api-main.py | 23 + examples/api_test/api-schema.json | 4182 ++++++++++++++++++++++ kaizen/actors/api_test_runner.py | 136 + kaizen/generator/api_test.py | 199 + kaizen/llms/prompts/API_tests_prompts.py | 17 + 5 files changed, 4557 insertions(+) create mode 100644 examples/api_test/api-main.py create mode 100644 examples/api_test/api-schema.json create mode 100644 kaizen/actors/api_test_runner.py create mode 100644 kaizen/generator/api_test.py create mode 100644 kaizen/llms/prompts/API_tests_prompts.py diff --git a/examples/api_test/api-main.py b/examples/api_test/api-main.py new file mode 100644 index 00000000..41e4d004 --- /dev/null +++ b/examples/api_test/api-main.py @@ -0,0 +1,23 @@ +from kaizen.generator.api_test import APITestGenerator + +generator = APITestGenerator() + +generator.generate_tests( + file_path="./examples/api_test/api-schema.json", + base_url="http://api.weatherbit.io/v2.0/", + enable_critique=True, + verbose=True, + max_critique=1 +) + +test_results = generator.run_tests() + +for file_path, result in test_results.items(): + print(f"Results for {file_path}:") + if "error" in result: + print(f" Error: {result['error']}") + else: + print(f" Tests run: {result.get('tests_run', 'N/A')}") + print(f" Failures: {result.get('failures', 'N/A')}") + print(f" Errors: {result.get('errors', 'N/A')}") + print() \ No newline at end of file diff --git a/examples/api_test/api-schema.json b/examples/api_test/api-schema.json new file mode 100644 index 00000000..db402880 --- /dev/null +++ b/examples/api_test/api-schema.json @@ -0,0 +1,4182 @@ +{ + "swagger": "2.0", + "info": { + "title": "Weatherbit - Interactive Swagger UI Documentation", + "description": "This an interactive version of the documentation for the Weatherbit API. The base URL for the API is [http://api.weatherbit.io/v2.0/](http://api.weatherbit.io/v2.0/) or [https://api.weatherbit.io/v2.0/](http://api.weatherbit.io/v2.0/). Below is the Swagger UI documentation for the API. All API requests require the `key` parameter. An Example for a 48 hour forecast for London, UK would be `http://api.weatherbit.io/v2.0/forecast/hourly?lat=51.5072`&`lon=-0.1276`. See our [Weather API description page](https://www.weatherbit.io/api) for the full documentation.", + "version": "2.0.0" + }, + "host": "api.weatherbit.io", + "schemes": [ + "https", + "http" + ], + "basePath": "/v2.0", + "produces": [ + "application/json" + ], + "paths": { + "/alerts": { + "get": { + "summary": "Returns severe weather alerts issued by meteorological agencies - Given a lat/lon.", + "description": "Returns severe weather alerts issued by meteorological agencies - given a lat, and a lon.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "station", + "in": "query", + "description": "Station Call ID.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Alerts" + ], + "responses": { + "200": { + "description": "Weather Alert Object.", + "schema": { + "$ref": "#/definitions/WeatherAlert" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/current": { + "get": { + "summary": "Returns a Current Observation - Given a lat/lon.", + "description": "Returns a Current Observation - given a lat, and a lon.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "include", + "in": "query", + "description": "Include 1 hour - minutely precip forecast in the response, or severe weather alerts", + "required": false, + "enum": ["minutely", "alerts"], + "type": "string", + "format": "string" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "station", + "in": "query", + "description": "Station Call ID.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "stations", + "in": "query", + "description": "Comma separated list of Station Call ID's. Example: KRDU,KBFI,KVNY", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "points", + "in": "query", + "description": "Comma separated list of points. Example: (35.5, -75.5),(45, 65),(45.12, -130.5)", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "cities", + "in": "query", + "description": "Comma separated list of City ID's. Example: 4487042, 4494942, 4504871", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "lang", + "in": "query", + "description": "Language (Default: English) See language field description", + "required": false, + "enum": ["ar", "az","be","bg","bs","ca","cs","de","fi","fr","el","es","et","hr","hu","id","it","is","kw","nb","nl","pl","pt","ro","ru","sk","sl","sr","sv","tr","uk","zh","zh-tw"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Current Weather Data" + ], + "responses": { + "200": { + "description": "An Observation Group object.", + "schema": { + "$ref": "#/definitions/CurrentObsGroup" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/current/lightning": { + "get": { + "summary": "Returns nearest and most recent lightning observations - Given a lat/lon.", + "description": "Returns nearest and most recent lightning observations - Given a lat/lon.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "limit", + "in": "query", + "description": "Limit result lightning. (Default 20)", + "required": false, + "type": "integer" + }, + { + "name": "search_dist_km", + "in": "query", + "description": "Radial search distance from point in KM. (Default 50 - Max 150)", + "required": false, + "type": "integer" + }, + { + "name": "search_mins", + "in": "query", + "description": "Search time backwards from current time in minutes. (Default 30 - Max 240)", + "required": false, + "type": "integer" + }, + { + "name": "sort", + "in": "query", + "description": "Sort results by either most recent occurrence, or least distance from point. (Default distance)", + "required": false, + "enum":["distance","time"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Lightning" + ], + "responses": { + "200": { + "description": "Lightning data.", + "schema": { + "$ref": "#/definitions/LightningObsGroup" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/forecast/daily": { + "get": { + "summary": "Returns a daily forecast - Given Lat/Lon.", + "description": "Returns a daily forecast, where each point represents one day (24hr) period. Every point has a datetime string in the format \"YYYY-MM-DD\". One day begins at 00:00 UTC, and ends at 23:59 UTC. \n", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "station", + "in": "query", + "description": "Station Call ID.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "days", + "in": "query", + "description": "Number of days to return. Default 16.", + "required": false, + "type": "number", + "format": "integer" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "lang", + "in": "query", + "description": "Language (Default: English) See language field description", + "required": false, + "enum": ["ar", "az","be","bg","bs","ca","cs","de","fi","fr","el","es","et","hr","hu","id","it","is","kw","nb","nl","pl","pt","ro","ru","sk","sl","sr","sv","tr","uk","zh","zh-tw"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "16 day / daily Forecast" + ], + "responses": { + "200": { + "description": "A forecast object.", + "schema": { + "$ref": "#/definitions/ForecastDay" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/forecast/minutely": { + "get": { + "summary": "Returns a 60 minute precipitation forecast - Given Lat/Lon.", + "description": "Returns a 60 minute precipitation forecast, where each point represents one minute (1 min) period.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "station", + "in": "query", + "description": "Station Call ID.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "60 Minute Rain/Snow Nowcast" + ], + "responses": { + "200": { + "description": "A forecast object.", + "schema": { + "$ref": "#/definitions/FCMinutely" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/forecast/airquality": { + "get": { + "summary": "Returns 72 hour (hourly) Air Quality forecast - Given a geolocation.", + "description": "Returns 72 hour (hourly) Air Quality forecast, where each point represents a one hour period.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "hours", + "in": "query", + "description": "Number of hours to return.", + "required": false, + "type": "integer", + "format": "integer" + } + ], + "tags": [ + "Air Quality Forecast" + ], + "responses": { + "200": { + "description": "A forecast object.", + "schema": { + "$ref": "#/definitions/AQHourly" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/history/airquality": { + "get": { + "summary": "Returns 72 hours of historical air quality conditions - Given a geolocation.", + "description": "Returns historical air quality conditions. See https://www.weatherbit.io/api for API specific rate limits.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Historical Air Quality" + ], + "responses": { + "200": { + "description": "Historical air quality conditions", + "schema": { + "$ref": "#/definitions/AQCurrentGroup" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/current/airquality": { + "get": { + "summary": "Returns current air quality conditions - Given a geolocation.", + "description": "Returns current air quality conditions.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Current Air Quality" + ], + "responses": { + "200": { + "description": "Current air quality conditions", + "schema": { + "$ref": "#/definitions/AQCurrentGroup" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/forecast/hourly": { + "get": { + "summary": "Returns an hourly forecast - Given a lat/lon.", + "description": "Returns an hourly forecast, where each point represents a one hour period. Every point has a datetime string in the format \"YYYY-MM-DD:HH\". Time is UTC. \n", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "station", + "in": "query", + "description": "Station Call ID.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "lang", + "in": "query", + "description": "Language (Default: English) See language field description", + "required": false, + "enum": ["ar", "az","be","bg","bs","ca","cs","de","fi","fr","el","es","et","hr","hu","id","it","is","kw","nb","nl","pl","pt","ro","ru","sk","sl","sr","sv","tr","uk","zh","zh-tw"], + "type": "string", + "format": "string" + }, + { + "name": "hours", + "in": "query", + "description": "Number of hours to return.", + "required": false, + "type": "integer", + "format": "integer" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "240 hour / hourly Forecast" + ], + "responses": { + "200": { + "description": "A forecast object.", + "schema": { + "$ref": "#/definitions/ForecastHourly" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/forecast/agweather": { + "get": { + "summary": "Returns Agweather Forecast - Given a lat/lon.", + "description": "Returns Agweather Forecast - Given a lat, and lon. See https://www.weatherbit.io/api for API specific rate limits.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "start_date", + "in": "query", + "description": "Start Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "end_date", + "in": "query", + "description": "End Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "AgWeather Forecast" + ], + "responses": { + "200": { + "description": "An AGWeather Forecast Data Object.", + "schema": { + "$ref": "#/definitions/ForecastAG" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/history/agweather": { + "get": { + "summary": "Returns Historical Agweather - Given a lat/lon.", + "description": "Returns Historical Agweather Observations - Given a lat, and lon. See https://www.weatherbit.io/api for API specific rate limits.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "start_date", + "in": "query", + "description": "Start Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "end_date", + "in": "query", + "description": "End Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "tp", + "in": "query", + "description": "Time period of calculation (daily [DEFAULT], or hourly).", + "required": true, + "enum":["daily","hourly"], + "type": "string", + "format": "string" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Historical AgWeather Data" + ], + "responses": { + "200": { + "description": "An AGWeather Historical Data Object.", + "schema": { + "$ref": "#/definitions/HistoryAG" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/normals": { + "get": { + "summary": "Returns Historical Climate Normals (Averages) - Given a lat/lon.", + "description": "Returns Historical Climate Normals (Averages) - Given a lat, and lon. See https://www.weatherbit.io/api for API specific rate limits.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "start_day", + "in": "query", + "description": "Start Day (MM-DD).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "end_day", + "in": "query", + "description": "End Day (MM-DD).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "tp", + "in": "query", + "description": "Time period of calculation (daily, monthly, or hourly).", + "required": true, + "enum":["daily","hourly","monthly"], + "type": "string", + "format": "string" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "series_year", + "in": "query", + "description": "Series year for calculation. 2020 for 1991-2020. 2010 for 1981-2010.", + "required": true, + "type": "number", + "format": "number" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Climate Normals (Averages)" + ], + "responses": { + "200": { + "description": "An Normals Data Object.", + "schema": { + "$ref": "#/definitions/Normals" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/history/daily": { + "get": { + "summary": "Returns Historical Observations - Given a lat/lon.", + "description": "Returns Historical Observations - Given a lat, and lon. See https://www.weatherbit.io/api for API specific rate limits.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "station", + "in": "query", + "description": "Station Call ID.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "start_date", + "in": "query", + "description": "Start Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "end_date", + "in": "query", + "description": "End Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "lang", + "in": "query", + "description": "Language (Default: English) See language field description", + "required": false, + "enum": ["ar", "az","be","bg","bs","ca","cs","de","fi","fr","el","es","et","hr","hu","id","it","is","kw","nb","nl","pl","pt","ro","ru","sk","sl","sr","sv","tr","uk","zh","zh-tw"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Daily Historical Weather Data" + ], + "responses": { + "200": { + "description": "An Historical Day Data Object.", + "schema": { + "$ref": "#/definitions/HistoryDay" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/history/hourly": { + "get": { + "summary": "Returns Historical Observations - Given a lat/lon.", + "description": "Returns Historical Observations - Given a lat, and lon. See https://www.weatherbit.io/api for API specific rate limits.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "station", + "in": "query", + "description": "Station Call ID.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "start_date", + "in": "query", + "description": "Start Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "end_date", + "in": "query", + "description": "End Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "lang", + "in": "query", + "description": "Language (Default: English) See language field description", + "required": false, + "enum": ["ar", "az","be","bg","bs","ca","cs","de","fi","fr","el","es","et","hr","hu","id","it","is","kw","nb","nl","pl","pt","ro","ru","sk","sl","sr","sv","tr","uk","zh","zh-tw"], + "type": "string", + "format": "string" + }, + { + "name": "tz", + "in": "query", + "description": "Assume utc (default) or local time for start_date, end_date", + "required": false, + "enum": ["local", "utc"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Hourly Historical Weather Data" + ], + "responses": { + "200": { + "description": "An Historical Data Object.", + "schema": { + "$ref": "#/definitions/History" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/history/subhourly": { + "get": { + "summary": "Returns Historical Observations - Given a lat/lon.", + "description": "Returns Historical Observations - Given a lat, and lon. See https://www.weatherbit.io/api for API specific rate limits.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "city_id", + "in": "query", + "description": "City ID. Example: 4487042", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "city", + "in": "query", + "description": "City search.. Example - &city=Raleigh,NC or &city=Berlin,DE or city=Paris&country=FR", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "postal_code", + "in": "query", + "description": "Postal Code. Example: 28546", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "country", + "in": "query", + "description": "Country Code (2 letter) - to be used with postal_code.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "station", + "in": "query", + "description": "Station Call ID.", + "required": false, + "type": "string", + "format": "string" + }, + { + "name": "start_date", + "in": "query", + "description": "Start Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "end_date", + "in": "query", + "description": "End Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "lang", + "in": "query", + "description": "Language (Default: English) See language field description", + "required": false, + "enum": ["ar", "az","be","bg","bs","ca","cs","de","fi","fr","el","es","et","hr","hu","id","it","is","kw","nb","nl","pl","pt","ro","ru","sk","sl","sr","sv","tr","uk","zh","zh-tw"], + "type": "string", + "format": "string" + }, + { + "name": "tz", + "in": "query", + "description": "Assume utc (default) or local time for start_date, end_date", + "required": false, + "enum": ["local", "utc"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Sub-Hourly Historical Weather Data" + ], + "responses": { + "200": { + "description": "An Historical Data Object.", + "schema": { + "$ref": "#/definitions/HistorySubhourly" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/forecast/energy": { + "get": { + "summary": "Returns Energy Forecast API response - Given a single lat/lon. ", + "description": "Retrieve an 8 day forecast relevant to te Energy Sector (degree days, solar radiation, precipitation, wind).", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "threshold", + "in": "query", + "description": "Temperature threshold to use to calculate degree days (default 18 C) ", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "tp", + "in": "query", + "description": "Time period (default: daily)", + "required": false, + "enum":["hourly","daily"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Forecast Degree Day API" + ], + "responses": { + "200": { + "description": "An Energy Data Object.", + "schema": { + "$ref": "#/definitions/EnergyObsGroupForecast" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/history/energy": { + "get": { + "summary": "Returns Energy API response - Given a single lat/lon. ", + "description": "Returns aggregate energy specific historical weather fields, over a specified time period. See https://www.weatherbit.io/api for API specific rate limits.", + "parameters": [ + { + "name": "lat", + "in": "query", + "description": "Latitude component of location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "lon", + "in": "query", + "description": "Longitude component of location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "start_date", + "in": "query", + "description": "Start Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "end_date", + "in": "query", + "description": "End Date (YYYY-MM-DD or YYYY-MM-DD:HH).", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "tp", + "in": "query", + "description": "Time period to aggregate by (daily, monthly)", + "required": false, + "enum":["hourly", "daily","monthly"], + "type": "string", + "format": "string" + }, + { + "name": "threshold", + "in": "query", + "description": "Temperature threshold to use to calculate degree days (default 18 C) ", + "required": false, + "type": "number", + "format": "double" + }, + { + "name": "units", + "in": "query", + "description": "Convert to units. Default Metric See units field description", + "required": false, + "enum":["S","I"], + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Historical Degree Day API" + ], + "responses": { + "200": { + "description": "An Energy Data Object.", + "schema": { + "$ref": "#/definitions/EnergyObsGroup" + } + }, + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/bulk/files": { + "get": { + "summary": "Download pre-generated bulk datasets", + "description": "Downloads bulk data files - OPTIONS: ( current.csv.gz, forecast_hourly.csv.gz, forecast_daily.csv.gz). Units are Metric (Celcius, m/s, etc).", + "parameters": [ + { + "name": "file", + "in": "path", + "description": "Filename (ie. current.csv.gz)", + "required": true, + "type": "string", + "format": "string" + }, + { + "name": "key", + "in": "query", + "description": "Your registered API key.", + "required": true, + "type": "string", + "format": "string" + } + ], + "tags": [ + "Bulk Downloads" + ], + "responses": { + "default": { + "description": "No Data.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + + "definitions": { + "ForecastHour": { + "type": "object", + "properties": { + "ts": { + "type": "number", + "description": "Unix Timestamp", + "example":"1551718800" + }, + "timestamp_local": { + "type": "string", + "description": "Timestamp in local time", + "example":"2019-03-04T12:00:00" + }, + "timestamp_utc": { + "type": "string", + "description": "Timestamp UTC", + "example":"2019-03-04T17:00:00" + }, + "datetime": { + "type": "string", + "description": "Date in format \"YYYY-MM-DD:HH\". All datetime is in (UTC)", + "example":"2019-03-04:17" + }, + "snow": { + "type": "number", + "description": "Accumulated snowfall since last forecast point - Default (mm)", + "example":10.45 + }, + "snow_depth": { + "type": ["number", "null"], + "description": "Snow depth - Default (mm)", + "example":45, + "nullable": true + }, + "precip": { + "type": "number", + "description": "Accumulated precipitation since last forecast point. Default (mm)", + "example":1.1 + }, + "temp": { + "type": "number", + "description": "Temperature - Default (C)", + "example": -1.5 + }, + "dewpt": { + "type": "number", + "description": "Dewpoint - Default (C)", + "example":-4.0 + }, + "app_temp": { + "type": "number", + "description": "Apparent Temperature - Default (C)", + "example":4.5 + }, + "rh": { + "type": "integer", + "description": "Relative Humidity as a percentage (%)", + "example":95 + }, + "clouds": { + "type": "integer", + "description": "Cloud cover as a percentage (%)", + "example": 100 + }, + "weather": { + "type": "object", + "properties": { + "icon": { + "type": "string", + "description": "Icon code for forecast image display", + "example":"s02d" + }, + "code": { + "type": "integer", + "description": "Weather Condition code", + "example":601 + }, + "description": { + "type": "string", + "description": "Weather Condition description", + "example":"Snow" + } + } + }, + "slp": { + "type": "number", + "description": "Mean Sea level pressure (mb)", + "example": 1012.89 + }, + "pres": { + "type": "number", + "description": "Pressure (mb)", + "example": 1005 + }, + "uv": { + "type": "number", + "description": "UV Index", + "example": 6.5 + }, + "solar_rad": { + "type": "number", + "description": "Estimated solar radiation (W/m^2)", + "example":300 + }, + "ghi": { + "type": "number", + "description": "Global horizontal solar irradiance (W/m^2)", + "example":1000 + }, + "dhi": { + "type": "number", + "description": "Diffuse normal solar irradiance (W/m^2)", + "example":200 + }, + "dni": { + "type": "number", + "description": "Direct normal solar irradiance (W/m^2)", + "example":400 + }, + "vis": { + "type": "number", + "description": "Visibility - Default (KM)", + "example": 1 + }, + "pod": { + "type": "string", + "description": "Part of day (d = day, n = night)", + "example":"d" + }, + "pop": { + "type": "number", + "description": "Chance of Precipitation as a percentage (%)", + "example": 75 + }, + "wind_spd": { + "type": "number", + "description": "Wind Speed - Default (m/s)", + "example": 13.85 + }, + "wind_gust_spd": { + "type": "number", + "description": "Wind Gust Speed - Default (m/s)", + "example": 16.85 + }, + "wind_dir": { + "type": "integer", + "description": "Wind direction", + "example": 105 + }, + "wind_cdir": { + "type": "string", + "description": "Cardinal wind direction", + "example":"ENE" + }, + "wind_cdir_full": { + "type": "string", + "description": "Cardinal wind direction (text)", + "example":"East-North-East" + } + } + }, + "Forecast": { + "type": "object", + "properties": { + "ts": { + "type": "number", + "description": "Unix Timestamp", + "example":"1551718800" + }, + "timestamp_local": { + "type": "string", + "description": "Timestamp in local time", + "example":"2019-03-04T12:00:00" + }, + "timestamp_utc": { + "type": "string", + "description": "Timestamp UTC", + "example":"2019-03-04T17:00:00" + }, + "datetime": { + "type": "string", + "description": "Date in format \"YYYY-MM-DD:HH\". All datetime is in (UTC)", + "example":"2019-03-04:17" + }, + "snow": { + "type": "number", + "description": "Accumulated snowfall since last forecast point - default (mm)", + "example": 10.45 + }, + "snow_depth": { + "type": ["number", "null"], + "description": "Snow Depth - default (mm)", + "example": 45, + "nullable": true + }, + "precip": { + "type": "number", + "description": "Accumulated precipitation since last forecast point - default (mm)", + "example": 1.1 + }, + "temp": { + "type": "number", + "description": "Temperature (Average) - default (C)", + "example": 1.0 + }, + "dewpt": { + "type": "number", + "description": "Dewpoint (Average) - default (C)", + "example": 1.0 + }, + "max_temp": { + "type": "number", + "description": "Maximum daily Temperature - default (C)", + "example": 1.5 + }, + "min_temp": { + "type": "number", + "description": "Minimum daily Temperature - default (C)", + "example": -1.23 + }, + "app_max_temp": { + "type": "number", + "description": "Apparent Maximum daily Temperature - default (C)", + "example": 4 + }, + "app_min_temp": { + "type": "number", + "description": "Apparent Minimum daily Temperature - default (C)", + "example": -2 + }, + "rh": { + "type": "integer", + "description": "Relative Humidity as a percentage (%)", + "example": 95 + }, + "clouds": { + "type": "integer", + "description": "Cloud cover as a percentage (%)", + "example": 100 + }, + "weather": { + "type": "object", + "properties": { + "icon": { + "type": "string", + "description": "Icon code for forecast image display", + "example":"s02n" + }, + "code": { + "type": "integer", + "description": "Weather Condition code", + "example":601 + }, + "description": { + "type": "string", + "description": "Weather Condition description", + "example":"Snow" + } + } + }, + "slp": { + "type": "number", + "description": "Mean Sea level pressure (mb)", + "example": 1012.89 + }, + "pres": { + "type": "number", + "description": "Pressure (mb)", + "example": 1005 + }, + "uv": { + "type": "number", + "description": "UV Index", + "example":6.5 + }, + "max_dhi": { + "type": ["number", "null"], + "description": "[Deprecated] Max direct component of solar insolation (W/m^2)", + "example":"655", + "nullable": true + }, + "vis": { + "type": "number", + "description": "Average Visibility default (KM)", + "example": 3.0 + }, + "pop": { + "type": "number", + "description": "Chance of Precipitation as a percentage (%)", + "example": 75 + }, + "moon_phase": { + "type": "number", + "description": "Moon phase", + "example": 0.87 + }, + "sunrise_ts": { + "type": "integer", + "description": "Sunrise unix timestamp", + "example": 1530331260 + }, + "sunset_ts": { + "type": "integer", + "description": "Sunset unix timestamp", + "example": 1530331260 + }, + "moonrise_ts": { + "type": "integer", + "description": "Moonrise unix timestamp", + "example": 1530331260 + }, + "moonset_ts": { + "type": "integer", + "description": "Moonset unix timestamp", + "example": 1530331260 + }, + "pod": { + "type": "string", + "description": "Part of the day (d = day, n = night)", + "example":"n" + }, + "wind_spd": { + "type": "number", + "description": "Wind Speed (default m/s)", + "example": 13.85 + }, + "wind_dir": { + "type": "integer", + "description": "Wind direction", + "example": 105 + }, + "wind_cdir": { + "type": "string", + "description": "Cardinal wind direction", + "example":"ENE" + }, + "wind_cdir_full": { + "type": "string", + "description": "Cardinal wind direction (text)", + "example":"East-North-East" + } + } + }, + + "HistoryObj": { + "type": "object", + "properties": { + "ts": { + "type": "number", + "description": "Unix Timestamp", + "example":"1551718800" + }, + "timestamp_local": { + "type": "string", + "description": "Timestamp in local time", + "example":"2019-03-04T12:00:00" + }, + "timestamp_utc": { + "type": "string", + "description": "Timestamp UTC", + "example":"2019-03-04T17:00:00" + }, + "revision_status": { + "type": "string", + "description": "Data revision status (interim or final)", + "example":"final" + }, + "datetime": { + "type": "string", + "description": "Date in format \"YYYY-MM-DD:HH\". All datetime is in (UTC)", + "example":"2019-03-04:17" + }, + "slp": { + "type": "number", + "description": "Sea level pressure (mb)", + "example": 1020.10 + }, + "pres": { + "type": "number", + "description": "Pressure (mb)", + "example": 845 + }, + "rh": { + "type": "integer", + "description": "Relative Humidity as a percentage (%)", + "example": 85 + }, + "dewpt": { + "type": "number", + "description": "Dew point (Default Celcius)", + "example": -1.5 + }, + "temp": { + "type": "number", + "description": "Temperature (Default Celcius)", + "example": -1.2 + }, + "app_temp": { + "type": "number", + "description": "Apparent Temperature or Wind Chill/Heat Index (Default Celcius)", + "example": -1.5 + }, + "wind_spd": { + "type": "number", + "description": "Wind Speed (Default m/s)", + "example": 14.7 + }, + "wind_gust_spd": { + "type": "number", + "description": "Wind Gust Speed - Default (m/s)", + "example": 16.85 + }, + "wind_dir": { + "type": "integer", + "description": "Wind direction (Degrees)", + "example": 325 + }, + "uv": { + "type": "number", + "description": "UV Index (1-11+)", + "example": 4 + }, + "solar_rad": { + "type": "number", + "description": "Estimated solar radiation (W/m^2)", + "example":300 + }, + "ghi": { + "type": "number", + "description": "Global horizontal solar irradiance (W/m^2)", + "example":1500 + }, + "dhi": { + "type": "number", + "description": "Diffuse normal solar irradiance (W/m^2)", + "example":200 + }, + "dni": { + "type": "number", + "description": "Direct normal solar irradiance (W/m^2)", + "example":400 + }, + "h_angle": { + "type": ["number", "null"], + "description": "Solar hour angle (Degrees)", + "example": 15.0, + "nullable": true + }, + "elev_angle": { + "type": "number", + "description": "Solar elevation angle (Degrees)", + "example": 27.5 + }, + "azimuth": { + "type": "number", + "description": "Azimuth angle (Degrees)", + "example": 50.5 + }, + "vis": { + "type": "number", + "description": "Visibility (KM)", + "example": 10 + }, + "pod": { + "type": "string", + "description": "Part of the day (d = day, n = night)", + "example":"n" + }, + "weather": { + "type": "object", + "properties": { + "icon": { + "type": "string", + "description": "Icon code for forecast image display", + "example":"s01n" + }, + "code": { + "type": "integer", + "description": "Weather Condition code", + "example":601 + }, + "description": { + "type": "string", + "description": "Weather Condition description", + "example":"Light Snow" + } + } + }, + "clouds": { + "type": "integer", + "description": "Cloud Cover 0-100 (%)", + "example": 50 + }, + "precip": { + "type": "number", + "description": "Liquid equivalent precipitation - Default (mm)", + "example": 3 + }, + "snow": { + "type": "number", + "description": "Snowfall - Default (mm)", + "example": 30 + } + } + }, + + "ForecastAG": { + "type": "object", + "properties": { + "lat": { + "type": "number", + "description": "Latitude", + "example": 47.61 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example": -122.33 + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/HistoryAGObj" + } + } + } + }, + "HistoryAG": { + "type": "object", + "properties": { + "lat": { + "type": "number", + "description": "Latitude", + "example": 47.61 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example": -122.33 + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/HistoryAGObj" + } + } + } + }, + "HistoryAGObj": { + "type": "object", + "properties": { + "bulk_soil_density": { + "type": "number", + "description": "Bulk Soil Density", + "example": 1370 + }, + "dlwrf_avg": { + "type": "number", + "description": "Average Downward Longwave Radiation Flux", + "example": 418.656 + }, + "dlwrf_max": { + "type": "number", + "description": "Maximum Downward Longwave Radiation Flux", + "example": 440.25 + }, + "dlwrf_net": { + "type": "number", + "description": "Net Downward Longwave Radiation Flux", + "example": 143 + }, + "dswrf_avg": { + "type": "number", + "description": "Average Downward Shortwave Radiation Flux", + "example": 158.848 + }, + "dswrf_max": { + "type": "number", + "description": "Maximum Downward Shortwave Radiation Flux", + "example": 492.25 + }, + "dswrf_net": { + "type": "number", + "description": "Net Downward Shortwave Radiation Flux", + "example": -50.832 + }, + "evapotranspiration": { + "type": "number", + "description": "Evapotranspiration", + "example": 4.247 + }, + "precip": { + "type": "number", + "description": "Precipitation", + "example": 18.5 + }, + "pres_avg": { + "type": "number", + "description": "Average Pressure", + "example": 1011.644 + }, + "revision_status": { + "type": "string", + "description": "Data revision status", + "example": "final" + }, + "skin_temp_avg": { + "type": "number", + "description": "Average Skin Temperature", + "example": 29.4 + }, + "skin_temp_max": { + "type": "number", + "description": "Maximum Skin Temperature", + "example": 40.4 + }, + "skin_temp_min": { + "type": "number", + "description": "Minimum Skin Temperature", + "example": 25.4 + }, + "soilm_0_10cm": { + "type": "number", + "description": "Soil Moisture (0-10cm depth)", + "example": 25.697 + }, + "soilm_100_200cm": { + "type": "number", + "description": "Soil Moisture (100-200cm depth)", + "example": 273.625 + }, + "soilm_10_40cm": { + "type": "number", + "description": "Soil Moisture (10-40cm depth)", + "example": 72.813 + }, + "soilm_40_100cm": { + "type": "number", + "description": "Soil Moisture (40-100cm depth)", + "example": 152.203 + }, + "soilt_0_10cm": { + "type": "number", + "description": "Soil Temperature (0-10cm depth)", + "example": 29.5 + }, + "soilt_100_200cm": { + "type": "number", + "description": "Soil Temperature (100-200cm depth)", + "example": 24.4 + }, + "soilt_10_40cm": { + "type": "number", + "description": "Soil Temperature (10-40cm depth)", + "example": 29.8 + }, + "soilt_40_100cm": { + "type": "number", + "description": "Soil Temperature (40-100cm depth)", + "example": 27.7 + }, + "specific_humidity": { + "type": "number", + "description": "Specific Humidity", + "example": 0.014513969421387 + }, + "timestamp_local": { + "type": "string", + "description": "Timestamp in local time", + "example":"2023-09-08T00:00:00" + }, + "timestamp_utc": { + "type": "string", + "description": "Timestamp UTC", + "example":"2023-09-08T00:00:00" + }, + "temp_2m_avg": { + "type": "number", + "description": "Average Temperature at 2 meters", + "example": 26.6 + }, + "v_soilm_0_10cm": { + "type": "number", + "description": "Volumetric Soil Moisture (0-10cm depth)", + "example": 0.257 + }, + "v_soilm_100_200cm": { + "type": "number", + "description": "Volumetric Soil Moisture (100-200cm depth)", + "example": 0.274 + }, + "v_soilm_10_40cm": { + "type": "number", + "description": "Volumetric Soil Moisture (10-40cm depth)", + "example": 0.243 + }, + "v_soilm_40_100cm": { + "type": "number", + "description": "Volumetric Soil Moisture (40-100cm depth)", + "example": 0.254 + }, + "valid_date": { + "type": "string", + "description": "Valid Date", + "example": "2023-09-08" + }, + "wind_10m_spd_avg": { + "type": "number", + "description": "Average Wind Speed at 10 meters", + "example": 2.505 + } + } + }, + "ForecastAGObj": { + "type": "object", + "properties": { + "bulk_soil_density": { + "type": "number", + "description": "Bulk Soil Density", + "example": 1370 + }, + "dlwrf_avg": { + "type": "number", + "description": "Average Downward Longwave Radiation Flux", + "example": 418.656 + }, + "dlwrf_max": { + "type": "number", + "description": "Maximum Downward Longwave Radiation Flux", + "example": 440.25 + }, + "dlwrf_net": { + "type": "number", + "description": "Net Downward Longwave Radiation Flux", + "example": 143 + }, + "dswrf_avg": { + "type": "number", + "description": "Average Downward Shortwave Radiation Flux", + "example": 158.848 + }, + "dswrf_max": { + "type": "number", + "description": "Maximum Downward Shortwave Radiation Flux", + "example": 492.25 + }, + "dswrf_net": { + "type": "number", + "description": "Net Downward Shortwave Radiation Flux", + "example": -50.832 + }, + "evapotranspiration": { + "type": "number", + "description": "Evapotranspiration", + "example": 4.247 + }, + "precip": { + "type": "number", + "description": "Precipitation", + "example": 18.5 + }, + "pres_avg": { + "type": "number", + "description": "Average Pressure", + "example": 1011.644 + }, + "revision_status": { + "type": "string", + "description": "Data revision status", + "example": "final" + }, + "skin_temp_avg": { + "type": "number", + "description": "Average Skin Temperature", + "example": 29.4 + }, + "skin_temp_max": { + "type": "number", + "description": "Maximum Skin Temperature", + "example": 40.4 + }, + "skin_temp_min": { + "type": "number", + "description": "Minimum Skin Temperature", + "example": 25.4 + }, + "soilm_0_10cm": { + "type": "number", + "description": "Soil Moisture (0-10cm depth)", + "example": 25.697 + }, + "soilm_100_200cm": { + "type": "number", + "description": "Soil Moisture (100-200cm depth)", + "example": 273.625 + }, + "soilm_10_40cm": { + "type": "number", + "description": "Soil Moisture (10-40cm depth)", + "example": 72.813 + }, + "soilm_40_100cm": { + "type": "number", + "description": "Soil Moisture (40-100cm depth)", + "example": 152.203 + }, + "soilt_0_10cm": { + "type": "number", + "description": "Soil Temperature (0-10cm depth)", + "example": 29.5 + }, + "soilt_100_200cm": { + "type": "number", + "description": "Soil Temperature (100-200cm depth)", + "example": 24.4 + }, + "soilt_10_40cm": { + "type": "number", + "description": "Soil Temperature (10-40cm depth)", + "example": 29.8 + }, + "soilt_40_100cm": { + "type": "number", + "description": "Soil Temperature (40-100cm depth)", + "example": 27.7 + }, + "specific_humidity": { + "type": "number", + "description": "Specific Humidity", + "example": 0.014513969421387 + }, + "temp_2m_avg": { + "type": "number", + "description": "Average Temperature at 2 meters", + "example": 26.6 + }, + "v_soilm_0_10cm": { + "type": "number", + "description": "Volumetric Soil Moisture (0-10cm depth)", + "example": 0.257 + }, + "v_soilm_100_200cm": { + "type": "number", + "description": "Volumetric Soil Moisture (100-200cm depth)", + "example": 0.274 + }, + "v_soilm_10_40cm": { + "type": "number", + "description": "Volumetric Soil Moisture (10-40cm depth)", + "example": 0.243 + }, + "v_soilm_40_100cm": { + "type": "number", + "description": "Volumetric Soil Moisture (40-100cm depth)", + "example": 0.254 + }, + "valid_date": { + "type": "string", + "description": "Valid Date", + "example": "2023-09-08" + }, + "wind_10m_spd_avg": { + "type": "number", + "description": "Average Wind Speed at 10 meters", + "example": 2.505 + } + } + }, + "HistorySubhourlyObj": { + "type": "object", + "properties": { + "ts": { + "type": "number", + "description": "Unix Timestamp", + "example":"1551718800" + }, + "timestamp_local": { + "type": "string", + "description": "Timestamp in local time", + "example":"2019-03-04T12:15:00" + }, + "timestamp_utc": { + "type": "string", + "description": "Timestamp UTC", + "example":"2019-03-04T17:15:00" + }, + "revision_status": { + "type": "string", + "description": "Data revision status (interim or final)", + "example":"final" + }, + "slp": { + "type": "number", + "description": "Sea level pressure (mb)", + "example": 1020.10 + }, + "pres": { + "type": "number", + "description": "Pressure (mb)", + "example": 845 + }, + "rh": { + "type": "integer", + "description": "Relative Humidity as a percentage (%)", + "example": 85 + }, + "dewpt": { + "type": "number", + "description": "Dew point (Default Celcius)", + "example": -1.5 + }, + "temp": { + "type": "number", + "description": "Temperature (Default Celcius)", + "example": -1.2 + }, + "app_temp": { + "type": "number", + "description": "Apparent Temperature or Wind Chill/Heat Index (Default Celcius)", + "example": -1.5 + }, + "wind_spd": { + "type": "number", + "description": "Wind Speed (Default m/s)", + "example": 14.7 + }, + "wind_gust_spd": { + "type": "number", + "description": "Wind Gust Speed - Default (m/s)", + "example": 16.85 + }, + "wind_dir": { + "type": "integer", + "description": "Wind direction (Degrees)", + "example": 325 + }, + "uv": { + "type": "number", + "description": "UV Index (1-11+)", + "example": 4 + }, + "solar_rad": { + "type": "number", + "description": "Estimated solar radiation (W/m^2)", + "example":300 + }, + "ghi": { + "type": "number", + "description": "Global horizontal solar irradiance (W/m^2)", + "example":1500 + }, + "dhi": { + "type": "number", + "description": "Diffuse normal solar irradiance (W/m^2)", + "example":200 + }, + "dni": { + "type": "number", + "description": "Direct normal solar irradiance (W/m^2)", + "example":400 + }, + "elev_angle": { + "type": "number", + "description": "Solar elevation angle (Degrees)", + "example": 27.5 + }, + "azimuth": { + "type": "number", + "description": "Solar azimuth angle (Degrees)", + "example": 40.5 + }, + "vis": { + "type": "number", + "description": "Visibility (KM)", + "example": 10 + }, + "pod": { + "type": "string", + "description": "Part of the day (d = day, n = night)", + "example":"n" + }, + "weather": { + "type": "object", + "properties": { + "icon": { + "type": "string", + "description": "Icon code for forecast image display", + "example":"s01n" + }, + "code": { + "type": "integer", + "description": "Weather Condition code", + "example":601 + }, + "description": { + "type": "string", + "description": "Weather Condition description", + "example":"Light Snow" + } + } + }, + "clouds": { + "type": "integer", + "description": "Cloud Cover 0-100 (%)", + "example": 50 + }, + "precip_rate": { + "type": "number", + "description": "Liquid equivalent precipitation rate - Default (mm/hr)", + "example": 3 + }, + "snow_rate": { + "type": "number", + "description": "Snowfall Rate - Default (mm/hr)", + "example": 30 + } + } + }, + "HistoryDayObj": { + "type": "object", + "properties": { + "datetime": { + "type": "string", + "description": "Date in format \"YYYY-MM-DD\". All datetime is in (UTC)", + "example":"2015-01-03" + }, + "ts": { + "type": "integer", + "description": "Unix timestamp of datetime (Midnight UTC)", + "example": 1501970516 + }, + "revision_status": { + "type": "string", + "description": "Data revision status (interim or final)", + "example":"final" + }, + "slp": { + "type": "number", + "description": "Average sea level pressure (mb)", + "example": 1020.1 + }, + "pres": { + "type": "number", + "description": "Average pressure (mb)", + "example": 885.1 + }, + "rh": { + "type": "number", + "description": "Average relative humidity as a percentage (%)", + "example": 85 + }, + "dewpt": { + "type": "number", + "description": "Average dewpoint - Default (C)", + "example": -1.5 + }, + "temp": { + "type": "number", + "description": "Average temperature - Default (C)", + "example": 1.0 + }, + "max_temp": { + "type": "number", + "description": "Max temperature - Default (C)", + "example": 1.5 + }, + "max_temp_ts": { + "type": "number", + "description": "Time of max memperature - Unix Timestamp", + "example": 1501970816 + }, + "min_temp": { + "type": "number", + "description": "Min temperature - Default (C)", + "example": 11.7 + }, + "min_temp_ts": { + "type": "number", + "description": "Time of max temperature - unix timestamp", + "example": 1501970516 + }, + "wind_spd": { + "type": "number", + "description": "Average wind speed - default (m/s)", + "example": 14.98 + }, + "wind_dir": { + "type": "integer", + "description": "Average wind direction (degrees)", + "example": 325 + }, + "wind_gust_spd": { + "type": "number", + "description": "Wind gust speed - default (m/s)", + "example": 40.98 + }, + "max_wind_spd": { + "type": "number", + "description": "Max 2min Wind Speed - default (m/s)", + "example": 19.98 + }, + "max_wind_dir": { + "type": "integer", + "description": "Direction of wind at time of max 2min wind (degrees)", + "example": 325 + }, + "max_wind_spd_ts": { + "type": "number", + "description": "Time of max 2min wind - unix timestamp", + "example": 1501970516 + }, + "ghi": { + "type": "integer", + "description": "Average hourly global horizontal solar irradiance (W/m^2)", + "example": 125 + }, + "t_ghi": { + "type": "integer", + "description": "Total global horizontal solar irradiance (W/m^2)", + "example": 4500 + }, + "dni": { + "type": "integer", + "description": "Average direct normal solar irradiance (W/m^2)", + "example": 125 + }, + "t_dni": { + "type": "integer", + "description": "Total direct normal solar irradiance (W/m^2)", + "example": 4500 + }, + "dhi": { + "type": "integer", + "description": "Average hourly diffuse horizontal solar irradiance (W/m^2)", + "example": 125 + }, + "t_dhi": { + "type": "integer", + "description": "Total diffuse horizontal solar irradiance (W/m^2)", + "example": 4500 + }, + "max_uv": { + "type": "number", + "description": "Max UV Index (1-11+)", + "example": 6 + }, + "precip": { + "type": "number", + "description": "Liquid equivalent precipitation - default (mm)", + "example": 3 + }, + "precip_gpm": { + "type": "number", + "description": "Satellite estimated liquid equivalent precipitation - default (mm)", + "example": 3 + }, + "snow": { + "type": "number", + "description": "Snowfall - default (mm)", + "example": 30 + }, + "snow_depth": { + "type": ["number", "null"], + "description": "Snow Depth - default (mm)", + "example": 60, + "nullable": true + } + } + }, + "NormalsObj": { + "type": "object", + "properties": { + "day": { + "type": ["number", "null"], + "description": "Day number", + "example":5, + "nullable": true + }, + "month": { + "type": "number", + "description": "Month number", + "example":2 + }, + "hour": { + "type": ["number", "null"], + "description": "Hour number", + "example":23, + "nullable": true + }, + "temp": { + "type": "number", + "description": "Average temperature", + "example": 30.0 + }, + "dewpt": { + "type": "number", + "description": "Average dew point", + "example": 25.0 + }, + "max_wind_spd": { + "type": "number", + "description": "Maximum wind speed", + "example": 5.0 + }, + "min_wind_spd": { + "type": "number", + "description": "Minimum wind speed", + "example": 0.0 + }, + "wind_spd": { + "type": "number", + "description": "Average wind speed", + "example": 2.0 + }, + "wind_dir": { + "type": "number", + "description": "Average wind direction", + "example": 200.0 + }, + "precip": { + "type": "number", + "description": "Average Liquid equivalent precipitation - Default (mm)", + "example": 3.1 + }, + "snow": { + "type": "number", + "description": "Average Snowfall - Default (mm)", + "example": 30.5 + } + } + }, + "Normals": { + "type": "object", + "properties": { + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "sources": { + "type": "array", + "description": "List of data sources used in response", + "items": { + "type": "string", + "example": "era5" + } + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/NormalsObj" + } + } + } + }, + "ForecastDay": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City Name", + "example":"Raleigh" + }, + "state_code": { + "type": "string", + "description": "State Abbreviation", + "example":"NC" + }, + "country_code": { + "type": "string", + "description": "Country Abbreviation", + "example":"US" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example":38.25 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example":-78.00 + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/Forecast" + } + } + } + }, + "ForecastHourly": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City Name", + "example":"Raleigh" + }, + "state_code": { + "type": "string", + "description": "State Abbreviation", + "example":"NC" + }, + "country_code": { + "type": "string", + "description": "Country Abbreviation", + "example":"US" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example":38.25 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example":-78.00 + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/ForecastHour" + } + } + } + }, + + "AQCurrent": { + "type": "object", + "properties": { + "aqi": { + "type": "integer", + "description": "Cloud cover as a percentage (%)", + "example": 100 + }, + "so2": { + "type": "number", + "description": "Concentration of SO2 (µg/m³)", + "example": 50 + }, + "no2": { + "type": "number", + "description": "Concentration of NO2 (µg/m³)", + "example": 25.0 + }, + "o3": { + "type": "number", + "description": "Concentration of O3 (µg/m³)", + "example": 2 + }, + "pm25": { + "type": "number", + "description": "Concentration of PM 2.5 (µg/m³)", + "example": 230 + }, + "pm10": { + "type": "number", + "description": "Concentration of PM 10 (µg/m³)", + "example": 150 + } + } + }, + "AQCurrentGroup": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City Name", + "example":"Raleigh" + }, + "state_code": { + "type": "string", + "description": "State Abbreviation", + "example":"NC" + }, + "country_code": { + "type": "string", + "description": "Country Abbreviation", + "example":"US" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example":38.25 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example":-78.00 + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/AQCurrent" + } + } + } + }, + + "AQHour": { + "type": "object", + "properties": { + "ts": { + "type": "number", + "description": "Unix Timestamp", + "example":"1551718800" + }, + "timestamp_local": { + "type": "string", + "description": "Timestamp in local time", + "example":"2019-03-04T12:00:00" + }, + "timestamp_utc": { + "type": "string", + "description": "Timestamp UTC", + "example":"2019-03-04T17:00:00" + }, + "aqi": { + "type": "integer", + "description": "Cloud cover as a percentage (%)", + "example": 100 + }, + "so2": { + "type": "number", + "description": "Concentration of SO2 (µg/m³)", + "example": 50 + }, + "no2": { + "type": "number", + "description": "Concentration of NO2 (µg/m³)", + "example": 25.0 + }, + "o3": { + "type": "number", + "description": "Concentration of O3 (µg/m³)", + "example": 2 + }, + "pm25": { + "type": "number", + "description": "Concentration of PM 2.5 (µg/m³)", + "example": 230 + }, + "pm10": { + "type": "number", + "description": "Concentration of PM 10 (µg/m³)", + "example": 150 + } + } + }, + "AQHourly": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City Name", + "example":"Raleigh" + }, + "state_code": { + "type": "string", + "description": "State Abbreviation", + "example":"NC" + }, + "country_code": { + "type": "string", + "description": "Country Abbreviation", + "example":"US" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example":38.25 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example":-78.00 + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/AQHour" + } + } + } + }, + "FCMinutelyOb": { + "type": "object", + "properties": { + "timestamp_utc": { + "type": "string", + "description": "Full time (UTC) of forecast point (YYYY-MM-DD HH:MM)", + "example":"2017-03-15 13:11" + }, + "timestamp_local": { + "type": "string", + "description": "Full local time of forecast point (YYYY-MM-DD HH:MM)", + "example":"2017-03-15 13:11" + }, + "ts": { + "type": "number", + "description": "Unix Timestamp", + "example":"1551718800" + }, + "precip": { + "type": "number", + "description": "Precipitation rate - Default (mm/hr)", + "example": 2 + }, + "temp": { + "type": "number", + "description": "Temperature - Default (C)", + "example": 13.85 + }, + "snow": { + "type": "number", + "description": "Snowfall rate - Default (mm/hr)", + "example": 10 + } + } + }, + "FCMinutely": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City Name", + "example":"Raleigh" + }, + "state_code": { + "type": "string", + "description": "State Abbreviation", + "example":"NC" + }, + "country_code": { + "type": "string", + "description": "Country Abbreviation", + "example":"US" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example":38.25 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example":-78.00 + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/FCMinutelyOb" + } + } + } + }, + "CurrentObs": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City name (closest)", + "example":"Raleigh" + }, + "state_code": { + "type": "string", + "description": "State abbreviation", + "example":"NC" + }, + "country_code": { + "type": "string", + "description": "Country abbreviation", + "example":"US" + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example": 38.00 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example": -78.25 + }, + "station": { + "type": "string", + "description": "Source Station ID", + "example":"KRDU" + }, + + "sources": { + "type": "array", + "description": "List of data sources used in response", + "items": { + "type": "string", + "example": "rtma" + } + }, + + "vis": { + "type": "integer", + "description": "Visibility - default (M)", + "example": 10000 + }, + "rh": { + "type": "integer", + "description": "Relative humidity (%)", + "example": 75 + }, + "dewpt": { + "type": "number", + "description": "Dew point temperature - default (C)", + "example": 12.0 + }, + "wind_dir": { + "type": "integer", + "description": "Wind direction (degrees)", + "example": 125 + }, + "wind_cdir": { + "type": "string", + "description": "Cardinal wind direction", + "example":"ENE" + }, + "wind_cdir_full": { + "type": "string", + "description": "Cardinal wind direction (text)", + "example":"East-North-East" + }, + "wind_speed": { + "type": "number", + "description": "Wind speed - Default (m/s)", + "example": 5.85 + }, + "gust": { + "type": ["number", "null"], + "description": "Wind gust speed - Default (m/s)", + "example": 9.0, + "nullable": true + }, + "temp": { + "type": "number", + "description": "Temperature - Default (C)", + "example": 13.85 + }, + "app_temp": { + "type": "number", + "description": "Apparent temperature - Default (C)", + "example": 14.85 + }, + "clouds": { + "type": "integer", + "description": "Cloud cover (%)", + "example": 42 + }, + "weather": { + "type": "object", + "properties": { + "icon": { + "type": "string", + "description": "Icon code for forecast image display", + "example":"c02" + }, + "code": { + "type": "integer", + "description": "Weather Condition code", + "example": 802 + }, + "description": { + "type": "string", + "description": "Weather Condition description", + "example":"Broken clouds" + } + } + }, + "datetime": { + "type": "string", + "description": "Cycle Hour (UTC) of observation", + "example":"2017-03-15:13" + }, + "ob_time": { + "type": "string", + "description": "Full time (UTC) of observation (YYYY-MM-DD HH:MM)", + "example":"2017-03-15 13:11" + }, + "ts": { + "type": "number", + "description": "Unix Timestamp", + "example": 1490990400 + }, + "sunrise": { + "type": "string", + "description": "Time (UTC) of Sunrise (HH:MM)", + "example":"06:22" + }, + "sunset": { + "type": "string", + "description": "Time (UTC) of Sunset (HH:MM)", + "example":"19:34" + }, + "slp": { + "type": "number", + "description": "Mean sea level pressure in millibars (mb)", + "example": 1013.12 + }, + "pres": { + "type": "number", + "description": "Pressure (mb)", + "example": 1010 + }, + "aqi": { + "type": "number", + "description": "Air quality index (US EPA standard 0 to +500)", + "example": 50 + }, + "uv": { + "type": "number", + "description": "UV Index", + "example": 6.5 + }, + "solar_rad": { + "type": "number", + "description": "Estimated solar radiation (W/m^2)", + "example": 300.4 + }, + "ghi": { + "type": "number", + "description": "Global horizontal irradiance (W/m^2)", + "example": 450.4 + }, + "dni": { + "type": "number", + "description": "Direct normal irradiance (W/m^2)", + "example": 450.4 + }, + "dhi": { + "type": "number", + "description": "Diffuse horizontal irradiance (W/m^2)", + "example": 450.4 + }, + "elev_angle": { + "type": "number", + "description": "Current solar elevation angle (Degrees)", + "example": 37 + }, + "hour_angle": { + "type": ["number", "null"], + "description": "Current solar hour angle (Degrees)", + "example": 45, + "nullable": true + }, + "pod": { + "type":"string", + "description": "Part of the day (d = day, n = night)" + }, + "precip": { + "type": "number", + "description": "Precipitation in last hour - Default (mm)", + "example": 2 + }, + "snow": { + "type": "number", + "description": "Snowfall in last hour - Default (mm)", + "example": 10 + } + } + }, + "LightningObs": { + "type": "object", + "properties": { + "lat": { + "type": "number", + "description": "Latitude of lightning", + "example": 36.00 + }, + "lon": { + "type": "number", + "description": "Longitude of lightning", + "example": -78.25 + }, + "bearing_cardinal": { + "type": "string", + "description": "Cardinal direction of lightning relative to point", + "example": "WSW" + }, + "bearing_degrees": { + "type": "integer", + "description": "Direction of lightning relative to point in degrees", + "example": 258 + }, + "distance_km": { + "type": "number", + "description": "Distance of lightning from point in kilometers", + "example": 19.21 + }, + "distance_mi": { + "type": "number", + "description": "Distance of lightning from point in miles", + "example": 11.94 + }, + "id": { + "type": "integer", + "description": "Internal identifier of lightning", + "example": 61326 + }, + "timestamp_utc": { + "type": "string", + "description": "Timestamp of lightning at UTC timezone (YYYY-MM-DDTHH:MM:SS)", + "example":"2024-08-17T15:35:52" + }, + "timestamp_local": { + "type": "string", + "description": "Timestamp of lightning at local timezone (YYYY-MM-DDTHH:MM:SS)", + "example":"2024-08-17T10:35:52" + }, + "past_mins": { + "type": "number", + "description": "Amount of time passed since lightning lightning (in minutes).", + "example":20.5 + }, + "type": { + "type": "string", + "description": "Type of lightning data", + "example":"flash" + }, + "source": { + "type": "string", + "description": "Source of lightning data", + "example":"sat" + } + } + }, + "CurrentObsGroup": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Count of found observations", + "example":"1" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/CurrentObs" + } + } + } + }, + "LightningObsGroup": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Count of lightning events.", + "example": 20 + }, + "limit": { + "type": "integer", + "description": "Count of results in response (determined by limit parameter).", + "example": 100 + }, + "lat": { + "type": "number", + "description": "Latitude of point.", + "example":35.5 + }, + "lon": { + "type": "number", + "description": "Longitude of point.", + "example":-78.5 + }, + "search_distance_km": { + "type": "integer", + "description": "Distance searched for lightning (radially) in KM.", + "example": 100 + }, + "search_mins": { + "type": "integer", + "description": "Time backwards from current time searched for lightning.", + "example": 15 + }, + "sort": { + "type": "string", + "description": "Ascending sort key of data (time or distance).", + "example": "distance" + }, + "lightning": { + "type": "array", + "items": { + "$ref": "#/definitions/LightningObs" + } + } + } + }, + "EnergyObsSeries": { + "type": "object", + "properties": { + "date": { + "type": "string", + "description": "Date", + "example":"2018-06-01" + }, + "cdd": { + "type": "number", + "description": "Cooling degree days", + "example": 10 + }, + "hdd": { + "type": "number", + "description": "Heating degree days", + "example": 120 + }, + "rh": { + "type": "integer", + "description": "Average Relative humidity (%)", + "example": 75 + }, + "dewpt": { + "type": "number", + "description": "Average dew point temperature - Default (C)", + "example": 12 + }, + "wind_dir": { + "type": "integer", + "description": "Average wind direction (Degrees)", + "example": 125 + }, + "wind_spd": { + "type": "number", + "description": "Average wind speed - Default (m/s)", + "example": 5.85 + }, + "temp": { + "type": "number", + "description": "Average temperature - Default (C)", + "example": 13.85 + }, + "clouds": { + "type": "integer", + "description": "Average cloud cover (%)", + "example": 42 + }, + "t_ghi": { + "type": "number", + "description": "Total global horizontal solar irradiance (W/m^2)", + "example": 3000 + }, + "t_dhi": { + "type": "number", + "description": "Total diffuse horizontal solar irradiance (W/m^2)", + "example": 450 + }, + "t_dni": { + "type": "number", + "description": "Total direct normal solar irradiance (W/m^2)", + "example": 1200 + }, + "sun_hours": { + "type": "number", + "description": "Average number of daily sun hours - # hours where Solar GHI > 1000 W/m^2", + "example": 4.5 + }, + "precip": { + "type": "number", + "description": "Total precipitation in period - Default (mm)", + "example": 2 + }, + "snow": { + "type": "number", + "description": "Total snowfall in period - Default (mm)", + "example": 10 + } + } + }, + "EnergyObs": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City name (closest)", + "example":"Raleigh" + }, + "state_code": { + "type": "string", + "description": "State abbreviation", + "example":"NC" + }, + "country_code": { + "type": "string", + "description": "Country abbreviation", + "example":"US" + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example":38.00 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example":-78.25 + }, + "station_id": { + "type": "string", + "description": "Nearest Station ID [DEPRECATED]", + "example":"12345-999999" + }, + "sources": { + "type": "array", + "description": "List of data sources used in response", + "items": { + "type": "string", + "example": "12345-89083" + } + }, + "cdd": { + "type": "number", + "description": "Cooling degree days", + "example": 10 + }, + "hdd": { + "type": "number", + "description": "Heating degree days", + "example": 120 + }, + "rh": { + "type": "integer", + "description": "Average Relative humidity (%)", + "example": 75 + }, + "dewpt": { + "type": "number", + "description": "Average dew point temperature - Default (C)", + "example": 12 + }, + "wind_dir": { + "type": "integer", + "description": "Average wind direction (Degrees)", + "example": 125 + }, + "wind_spd": { + "type": "number", + "description": "Average wind speed - Default (m/s)", + "example": 5.85 + }, + "temp": { + "type": "number", + "description": "Average temperature - Default (C)", + "example": 13.85 + }, + "clouds": { + "type": "integer", + "description": "Average cloud cover (%)", + "example": 42 + }, + "t_ghi": { + "type": "number", + "description": "Total global horizontal solar irradiance (W/m^2)", + "example": 3000 + }, + "t_dhi": { + "type": "number", + "description": "Total diffuse horizontal solar irradiance (W/m^2)", + "example": 450 + }, + "t_dni": { + "type": "number", + "description": "Total direct normal solar irradiance (W/m^2)", + "example": 1200 + }, + "sun_hours": { + "type": "number", + "description": "Average number of daily sun hours - # hours where Solar GHI > 1000 W/m^2", + "example": 4.5 + }, + "precip": { + "type": "number", + "description": "Total precipitation in period - Default (mm)", + "example": 2 + }, + "snow": { + "type": "number", + "description": "Total snowfall in period - Default (mm)", + "example": 10 + } + } + }, + "WeatherAlert": { + "type": "object", + "properties": { + "lat": { + "type": "number", + "description": "Latitude", + "example": 38.00 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example": -78.25 + }, + "alerts": { + "type": "array", + "items": { + "$ref": "#/definitions/WeatherAlertGroup" + } + } + } + }, + "WeatherAlertGroup": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Brief description of weather alert", + "example":"Flood Warning issued February 8 at 8:51PM CST expiring February 12 at 8:24AM CST by NWS St Louis MO" + }, + "description": { + "type": "string", + "description": "Full description of weather alert", + "example":"Mississippi River at Chester\n\n.This Flood Warning is a result of 1-2 inches of rainfall across\nthe basin earlier this week...\nThe Flood Warning continues for\nthe Mississippi River at Chester\n* until Tuesday morning.\n* At 8:30 PM Friday the stage was 26.8 feet.\n* Flood stage is 27.0 feet.\n* Minor flooding is forecast.\n* The river is forecast to rise above flood stage by tonight and to\ncrest near 29.0 feet by Saturday evening. The river is forecast to\nfall below flood stage by Monday morning.\n* Impact: At 28.0 feet...Unleveed islands near Chester and the prison\nfarm floods.\n* Impact: At 27.0 feet...Flood Stage. Unprotected farmland on right\nbank begins to flood." + }, + "severity": { + "type": "string", + "description": "Severity of weather. (Advisory | Watch | Warning)", + "example":"Warning" + }, + "effective_utc": { + "type": "string", + "description": "Issued time UTC", + "example":"2019-02-09T02:51:00" + }, + "effective_local": { + "type": "string", + "description": "Issued time local", + "example":"2019-02-08T21:51:00" + }, + "expires_utc": { + "type": "string", + "description": "Expiration time UTC", + "example":"2019-02-10T02:51:00" + }, + "expires_local": { + "type": "string", + "description": "Expiration time local", + "example":"2019-02-09T21:51:00" + }, + "uri": { + "type": "string", + "description": "URI to weather alert", + "example":"https://api.weather.gov/alerts/NWS-IDP-PROD-3361975-2942026" + }, + "alerts": { + "type": "array", + "items": { + "$ref": "#/definitions/AlertRegionGroup" + } + } + + } + }, + "AlertRegionGroup": { + "type": "string", + "description": "List of impacted regions", + "example": "St Louis, MO" + }, + "EnergyObsGroup": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "description": "Count of found observations", + "example":"1" + }, + "start_date": { + "type": "integer", + "description": "Start Date", + "example":"2017-01-01" + }, + "end_date": { + "type": "integer", + "description": "End Date", + "example":"2017-01-30" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/EnergyObs" + } + } + } + }, + "EnergyObsGroupForecast": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City name (closest)", + "example":"Raleigh" + }, + "state_code": { + "type": "string", + "description": "State abbreviation", + "example":"NC" + }, + "country_code": { + "type": "string", + "description": "Country abbreviation", + "example":"US" + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example":38.00 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example":-78.25 + }, + "threshold_units": { + "type": "string", + "description": "Degree day threshold units", + "example":"C" + }, + "threshold_value": { + "type": "string", + "description": "Degree day threshold", + "example":"18" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/EnergyObsSeries" + } + } + } + }, + "History": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City name (Closest)", + "example":"Seattle" + }, + "state_code": { + "type": "string", + "description": "State abbreviation", + "example":"WA" + }, + "country_code": { + "type": "string", + "description": "Country abbreviation", + "example":"US" + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example": 47.61 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example": -122.33 + }, + "sources": { + "type": "array", + "description": "List of data sources used in response", + "items": { + "type": "string", + "example": "12345-89083" + } + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/HistoryObj" + } + } + } + }, + "HistorySubhourly": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City name (Closest)", + "example":"Seattle" + }, + "state_code": { + "type": "string", + "description": "State abbreviation", + "example":"WA" + }, + "country_code": { + "type": "string", + "description": "Country abbreviation", + "example":"US" + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example": 47.61 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example": -122.33 + }, + "sources": { + "type": "array", + "description": "List of data sources used in response", + "items": { + "type": "string", + "example": "12345-89083" + } + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/HistoryObj" + } + } + } + }, + "HistoryDay": { + "type": "object", + "properties": { + "city_name": { + "type": "string", + "description": "City name (Closest)", + "example":"Seattle" + }, + "state_code": { + "type": "string", + "description": "State abbreviation", + "example":"WA" + }, + "country_code": { + "type": "string", + "description": "Country abbreviation", + "example":"US" + }, + "timezone": { + "type": "string", + "description": "Local IANA time zone", + "example":"America/New_York" + }, + "lat": { + "type": "number", + "description": "Latitude", + "example": 47.61 + }, + "lon": { + "type": "number", + "description": "Longitude", + "example": -122.33 + }, + "sources": { + "type": "array", + "description": "List of data sources used in response", + "items": { + "type": "string", + "example": "12345-89083" + } + }, + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/HistoryDayObj" + } + } + } + }, + "Error": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/kaizen/actors/api_test_runner.py b/kaizen/actors/api_test_runner.py new file mode 100644 index 00000000..ff2872bd --- /dev/null +++ b/kaizen/actors/api_test_runner.py @@ -0,0 +1,136 @@ +import shlex +import os +import re +import subprocess +import logging +from kaizen.helpers.general import safe_path_join + + +class APITestRunner: + def __init__(self, test_directory="./.kaizen/api_test/"): + self.test_directory = test_directory + self.logger = logging.getLogger(__name__) + + self.logger.info( + f"APITestRunner initialized with test directory: {test_directory}" + ) + + def discover_and_run_tests(self, test_file=None): + if test_file is None: + self.logger.warning("No test file specified. Running all tests.") + self.logger.info("Starting test discovery and execution") + results = {} + for root, dirs, files in os.walk(self.test_directory): + for file in files: + if file.startswith("test_") and file.endswith(".py"): + file_path = safe_path_join(root, file) + self.logger.debug(f"Found test file: {file_path}") + if test_file and file not in test_file: + self.logger.debug("Skipping file test") + continue + + self.logger.info(f"Running tests for: {file_path}") + result = self.run_python_tests(file_path) + results[str(file_path)] = result + + self.logger.info("Test discovery and execution completed") + return results + + def run_python_tests(self, file_path): + self.logger.info(f"Running Python tests for: {file_path}") + project_root = self.find_project_root(file_path) + if not project_root: + self.logger.error("Could not find project root (no pytest.ini found)") + return {"error": "Could not find project root (no pytest.ini found)"} + + relative_path = os.path.relpath(file_path, project_root) + code, stdout, stderr = self.run_command( + ["pytest", relative_path, "-v"], cwd=project_root + ) + + if code != 0 and code != 1: + self.logger.error(f"pytest exited with code {code} for {file_path}") + return {"error": f"pytest exited with code {code}. Stderr: {stderr}"} + self.logger.info(f"pytest output: {stdout}") + # Parse pytest output + + # Get failed test details + passed_tests = re.findall(r"(.*?) PASSED", stdout) + failed_tests = re.findall(r"(.*?) FAILED", stdout) + error_tests = re.findall(r"(.*?) ERROR", stderr) + tests_run = len(passed_tests) + len(failed_tests) + len(error_tests) + + # Extract failure and error details + # Extract failure and error details + failure_details = {} + for match in re.findall( + r"FAILED (.*?) - Failed:(.*?)(?:\n|$)", stdout + stderr, re.MULTILINE + ): + test_path, reason = match + file_name = test_path.split("::")[0] + test_name = test_path.split("::")[-1] + failure_details[file_name] = failure_details.get(file_name, {}) + failure_details[file_name][test_name] = reason.strip() + + error_details = re.findall(r"_{20,}\n(.*?)\n\n", stderr, re.DOTALL) + + self.logger.info( + f"Python tests completed. Tests run: {tests_run}, Failures: {len(failed_tests)}, Errors: {len(error_tests)}" + ) + return { + "tests_run": tests_run, + "passed_tests": passed_tests, + "failed_tests": failed_tests, + "error_tests": error_tests, + "failure_details": failure_details, + "error_details": error_details, + } + + def find_project_root(self, file_path): + self.logger.debug(f"Searching for project root from: {file_path}") + current_dir = os.path.dirname(os.path.abspath(file_path)) + while current_dir != "/": + if ( + os.path.exists(os.path.join(current_dir, "package.json")) + or os.path.exists(os.path.join(current_dir, "Cargo.toml")) + or os.path.exists(os.path.join(current_dir, "pytest.ini")) + or os.path.exists(os.path.join(current_dir, "setup.py")) + or os.path.exists(os.path.join(current_dir, "setup.cfg")) + or os.path.exists(os.path.join(current_dir, "tox.ini")) + or os.path.exists(os.path.join(current_dir, "pyproject.toml")) + ): + self.logger.info(f"Project root found: {current_dir}") + return current_dir + current_dir = os.path.dirname(current_dir) + self.logger.warning("Project root not found") + return None + + def run_command(self, command, cwd=None): + self.logger.debug(f"Running command: {' '.join(command)} in directory: {cwd}") + try: + # Use shlex.split() to properly handle command arguments + if isinstance(command, str): + command = shlex.split(command) + + result = subprocess.run( + command, + capture_output=True, + text=True, + cwd=cwd, + shell=False, + timeout=300, + ) + self.logger.debug( + f"Command completed with return code: {result.returncode}" + ) + return result.returncode, result.stdout, result.stderr + except FileNotFoundError: + self.logger.error(f"Command not found: {command[0]}") + return 1, "", f"Command not found: {command[0]}" + except subprocess.CalledProcessError as e: + self.logger.error(f"Command failed with return code {e.returncode}: {e}") + return e.returncode, e.stdout, e.stderr + except subprocess.TimeoutExpired: + self.logger.error(f"Command timed out after {self.timeout} seconds") + return 124, "", f"Command timed out after {self.timeout} seconds" + diff --git a/kaizen/generator/api_test.py b/kaizen/generator/api_test.py new file mode 100644 index 00000000..5399b300 --- /dev/null +++ b/kaizen/generator/api_test.py @@ -0,0 +1,199 @@ +import os +import logging +from datetime import datetime +from tqdm import tqdm +import json +from dataclasses import dataclass +from typing import List, Dict +from kaizen.llms.provider import LLMProvider +from kaizen.helpers.parser import extract_code_from_markdown +from kaizen.actors.api_test_runner import APITestRunner +from kaizen.llms.prompts.API_tests_prompts import ( + API_TEST_SYSTEM_PROMPT, + API_METHOD_PROMPT +) + + +@dataclass +class APITestOutput: + tests: Dict + files: List + failed: List + usage: Dict[str, int] + model_name: str + cost: Dict[str, float] + + +class APITestGenerator: + def __init__(self, verbose=False): + self.output_folder = "./.kaizen/api_test/" + self.total_usage = { + "prompt_tokens": 0, + "completion_tokens": 0, + "total_tokens": 0, + } + self.logger = logging.getLogger(__name__) + self.provider = LLMProvider(system_prompt=API_TEST_SYSTEM_PROMPT) + self.verbose = verbose + self.log_dir = "./.kaizen/logs" + self.max_critique = 3 + self.enable_critique = False + self._setup_directories() + + def _setup_directories(self): + os.makedirs(self.log_dir, exist_ok=True) + self._create_output_folder(self.output_folder) + + def _create_output_folder(self, folder_name): + os.makedirs(folder_name, exist_ok=True) + print("Output folder created") + + def generate_tests( + self, + file_path: str, + base_url: str, + content: str = None, + max_critique: int = 3, + output_path: str = None, + verbose: bool = False, + enable_critique: bool = False, + temp_dir: str = "", + max_actions: int = 100000, + ): + self.max_critique = max_critique + self.enable_critique = enable_critique + self.verbose = verbose if verbose else self.verbose + self.output_folder = output_path if output_path else self.output_folder + self.temp_dir = temp_dir + self.max_actions = max_actions + self.base_url = base_url if base_url else "https://api.example.com" + content = content or self._read_file_content(file_path) + self.generate_test_files(content, file_path) + return {}, self.total_usage + + def _read_file_content(self, file_path): + try: + with open(file_path, 'r') as file: + api_schema = json.load(file) + except UnicodeDecodeError: + print(f"Error reading file: {file_path}") + return api_schema + + def generate_test_files(self, file_data, file_path): + folder_path = "/".join(file_path.split("/")[:-1]) + test_files = {} + actions_used = 0 + for path, path_item in tqdm(file_data['paths'].items(), desc="Processing Endpoints(Paths)", unit="paths"): + try: + test_code, count = self._process_item( + path, path_item, folder_path + ) + test_files[file_path] = test_code + actions_used += count + except Exception as e: + self.logger.error(f"Failed to generate test case for item: {path}. Error: {str(e)}") + break + + print( + f"\nAll items processed successfully!\n Total Tokens Spent: {self.total_usage}" + ) + return test_files, actions_used + + def _process_item(self, path, path_item, folder_path): + print(f"\n{'=' * 50}\nProcessing Item: {path}\n{'=' * 50}") + file_path = path.replace('/', '_').replace('{', '').replace('}', '') + test_file_path = self._prepare_test_file_path(file_path, folder_path) + test_code = "" + totalcount = 0 + for method, method_code in path_item.items(): + print("Processing method:", method) + individual_test_code, count = self.generate_ai_tests(path, method, method_code) + test_code += individual_test_code + totalcount += count + + test_code = test_code.replace(self.temp_dir, "") + test_code = self._correct_imports(test_code) + + self._write_test_file(test_file_path, test_code) + + print("\n✓ Item processing complete") + return test_code, totalcount + + def _prepare_test_file_path(self, path, folder_path): + print("Preparing test file path") + test_file_name = f"test_{path.lower()}.py" + test_file_path = os.path.join(self.output_folder, test_file_name) + self._create_output_folder("/".join(test_file_path.split("/")[:-1])) + print(f" ✓ File will be saved as: {test_file_path}") + return test_file_path + + def generate_ai_tests(self, path, method, method_code): + print(f"• Generating AI tests for {method.upper()} {path} ...") + test_generation_prompt = API_METHOD_PROMPT.format(path=path, method=method, method_code=method_code, base_url=self.base_url) + response, usage = self.provider.chat_completion_with_json(test_generation_prompt, model="default") + self.update_usage(usage) + test_code = extract_code_from_markdown(response) + print(f" ✓ AI tests generated successfully for {method.upper()} {path}") + self.log_step("Generate AI tests", f"Generated test code:\n{response}") + #generating only one set of tests per method + return test_code, 1 + + def run_tests(self, test_file=None): + runner = APITestRunner(self.output_folder) + return runner.discover_and_run_tests(test_file=test_file) + + def _correct_imports(self, test_code): + # Split the test_code into lines + lines = test_code.split("\n") + corrected_lines = [] + for line in lines: + if line.startswith("from /"): + # Remove the leading slash and change to relative import + corrected_line = "from " + line[6:] + corrected_lines.append(corrected_line) + else: + corrected_lines.append(line) + return "\n".join(corrected_lines) + + def format_test_scenarios(self, scenarios): + count = 0 + formatted_scenarios = "" + for category in [ + "critical_cases", + "edge_cases", + "error_handling", + "boundary_conditions", + ]: + count += 1 + cases = scenarios.get(category, []) + if cases: + formatted_scenarios += f"{category.replace('_', ' ').title()}:\n" + formatted_scenarios += "\n".join(f"- {case}" for case in cases) + formatted_scenarios += "\n\n" + return formatted_scenarios.strip(), count + + def log_step(self, step_name, data): + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + log_message = f"[{timestamp}] Step: {step_name}\n{data}\n{'=' * 50}\n" + + log_file = os.path.join(self.log_dir, "api_test_generator_steps.log") + os.makedirs(os.path.dirname(log_file), exist_ok=True) + + if self.verbose: + with open(log_file, "a") as f: + f.write(log_message) + print(f"Logged step: {step_name}") + + def _write_test_file(self, test_file_path, test_code): + print("• Writing test file...") + try: + with open(test_file_path, "w") as test_file: + test_file.write(test_code) + print(" ✓ Test file written successfully") + self.log_step("Write test file", f"Test file written to: {test_file_path}") + except Exception as e: + self.logger.error(f"Failed to write test file. Error: {str(e)}") + + def update_usage(self, usage): + self.total_usage = self.provider.update_usage(self.total_usage, usage) + print(f"@ Token usage: current_step: {usage}, total: {self.total_usage}") \ No newline at end of file diff --git a/kaizen/llms/prompts/API_tests_prompts.py b/kaizen/llms/prompts/API_tests_prompts.py new file mode 100644 index 00000000..46b42f96 --- /dev/null +++ b/kaizen/llms/prompts/API_tests_prompts.py @@ -0,0 +1,17 @@ +API_TEST_SYSTEM_PROMPT = """ +You are an advanced AI assistant specializing in writing API tests using Pytest. +Your task is to write clear, efficient and meaningful API tests only for the given API endpoint. """ + +API_METHOD_PROMPT = """ +Analyze the HTTP {method} method for endpoint {path} with the following schema: +{method_code} +BASE-URL: {base_url} +Generate comprehensive pytest-style API tests for this endpoint. Include the following: +1. Identify key test cases for the method schema. +2. Test for both valid and invalid request formats. +3. Provide detailed assert messages for both successful and error responses. +4. Identify key edge cases (boundary values, unusual inputs) that shall potentially fail. +5. If applicable write authentication test cases but use pytest decorator: @pytest.mark.skip stating reason as Authentication tests disabled. +Use pytest best practices and decorators. +Provide your tests as a well structured Python file containing all the test code. +""" \ No newline at end of file From a31196bc6a1a4ccac8936ceb2abc2bc355e9ed4e Mon Sep 17 00:00:00 2001 From: Shravya A <53599350+sysknock@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:30:37 +0530 Subject: [PATCH 2/6] fixed linting issues --- kaizen/actors/api_test_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kaizen/actors/api_test_runner.py b/kaizen/actors/api_test_runner.py index ff2872bd..45b33c30 100644 --- a/kaizen/actors/api_test_runner.py +++ b/kaizen/actors/api_test_runner.py @@ -133,4 +133,4 @@ def run_command(self, command, cwd=None): except subprocess.TimeoutExpired: self.logger.error(f"Command timed out after {self.timeout} seconds") return 124, "", f"Command timed out after {self.timeout} seconds" - + From fe20a1eafed79fed6f309f52db2caf72f49434b9 Mon Sep 17 00:00:00 2001 From: Shravya A <53599350+sysknock@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:31:11 +0530 Subject: [PATCH 3/6] fixed linting issues --- examples/api_test/api-main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/api_test/api-main.py b/examples/api_test/api-main.py index 41e4d004..4ba37d61 100644 --- a/examples/api_test/api-main.py +++ b/examples/api_test/api-main.py @@ -20,4 +20,5 @@ print(f" Tests run: {result.get('tests_run', 'N/A')}") print(f" Failures: {result.get('failures', 'N/A')}") print(f" Errors: {result.get('errors', 'N/A')}") - print() \ No newline at end of file + print() + From e3d0f5d42780f8410c2ded10ce44de2670789a7a Mon Sep 17 00:00:00 2001 From: Shravya A <53599350+sysknock@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:32:28 +0530 Subject: [PATCH 4/6] fixed linting issues --- kaizen/generator/api_test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kaizen/generator/api_test.py b/kaizen/generator/api_test.py index 5399b300..5fa4ba56 100644 --- a/kaizen/generator/api_test.py +++ b/kaizen/generator/api_test.py @@ -134,8 +134,7 @@ def generate_ai_tests(self, path, method, method_code): self.update_usage(usage) test_code = extract_code_from_markdown(response) print(f" ✓ AI tests generated successfully for {method.upper()} {path}") - self.log_step("Generate AI tests", f"Generated test code:\n{response}") - #generating only one set of tests per method + self.log_step("Generate AI tests", f"Generated test code:\n{response}") return test_code, 1 def run_tests(self, test_file=None): @@ -196,4 +195,4 @@ def _write_test_file(self, test_file_path, test_code): def update_usage(self, usage): self.total_usage = self.provider.update_usage(self.total_usage, usage) - print(f"@ Token usage: current_step: {usage}, total: {self.total_usage}") \ No newline at end of file + print(f"@ Token usage: current_step: {usage}, total: {self.total_usage}") From 143e1a6f7fbb80948b9a601ecfb317f4391e84d3 Mon Sep 17 00:00:00 2001 From: Shravya A <53599350+sysknock@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:33:02 +0530 Subject: [PATCH 5/6] fixed linting issues --- kaizen/generator/api_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/kaizen/generator/api_test.py b/kaizen/generator/api_test.py index 5fa4ba56..4ef27fe8 100644 --- a/kaizen/generator/api_test.py +++ b/kaizen/generator/api_test.py @@ -196,3 +196,4 @@ def _write_test_file(self, test_file_path, test_code): def update_usage(self, usage): self.total_usage = self.provider.update_usage(self.total_usage, usage) print(f"@ Token usage: current_step: {usage}, total: {self.total_usage}") + From bc91edb506517e2d76cf384b2639cb9beaa43673 Mon Sep 17 00:00:00 2001 From: Shravya A <53599350+sysknock@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:33:28 +0530 Subject: [PATCH 6/6] fixed linting issues --- kaizen/llms/prompts/API_tests_prompts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kaizen/llms/prompts/API_tests_prompts.py b/kaizen/llms/prompts/API_tests_prompts.py index 46b42f96..06b7e7ec 100644 --- a/kaizen/llms/prompts/API_tests_prompts.py +++ b/kaizen/llms/prompts/API_tests_prompts.py @@ -14,4 +14,4 @@ 5. If applicable write authentication test cases but use pytest decorator: @pytest.mark.skip stating reason as Authentication tests disabled. Use pytest best practices and decorators. Provide your tests as a well structured Python file containing all the test code. -""" \ No newline at end of file +"""