caic_python package

Submodules

caic_python.client module

An async HTTP client to interface with the CAIC website.

CAIC Website Avy Obs request:

 /**
 * @param startDatetime a utc date string in format YYYY-MM-DD HH:mm:ss
 * @param endDatetime a utc date string in format YYYY-MM-DD HH:mm:ss
 * @param header the caic auth header (shared between all of the pagination requests should be fine)
 * @param page offset page
 * @return raw caic response json (including pagination data so we can call this function again if there is more data)
 */
async getCaicPaginated (startDatetime, endDatetime, headers, page = 1) {
    queryArgs = new URLSearchParams({
    per: 1000,
    page,
    observed_after: startDatetime,
    observed_before: endDatetime,
    t: Date.now()
    });
    const result = await fetch(`https://api.avalanche.state.co.us/api/avalanche_observations?${queryArgs}`, { headers });
    return await result.json();
},

There’s a V2 of the avalanche_observations endpoint that we should switch to:

https://api.avalanche.state.co.us/api/v2/avalanche_observations?

A field reports example API call:

https://api.avalanche.state.co.us/api/v2/observation_reports?page=1&per=250&r[observed_at_gteq]=2023-05-14T06%3A00%3A00.000Z&r[observed_at_lteq]=2023-05-22T05%3A59%3A59.999Z&r[sorts][]=observed_at+desc&r[sorts][]=created_at+desc
https://api.avalanche.state.co.us/api/v2/observation_reports?page=1&per=250&r[backcountry_zone_title_in][]=Front+Range&r[snowpack_observations_cracking_in][]=Minor&r[snowpack_observations_collapsing_in][]=Rumbling&r[observed_at_gteq]=2023-05-14T06:00:00.000Z&r[observed_at_lteq]=2023-05-22T05:59:59.999Z&r[sorts][]=observed_at+desc&r[sorts][]=created_at+desc
https://api.avalanche.state.co.us/api/v2/observation_reports?page=1&per=250&r[observed_at_gteq]=2023-05-14T06:00:00.000Z&r[observed_at_lteq]=2023-05-22T05:59:59.999Z&r[saw_avalanche_eq]=true&r[sorts][]=observed_at%20desc&r[sorts][]=created_at%20desc

A forecast API call - must use the proxy for these - the avid API is behind auth:

https://avalanche.state.co.us/api-proxy/avid?_api_proxy_uri=/products/all?datetime=2023-01-22T12:00:00.000Z&includeExpired=true

Weather dispatches API call - also a different domain:

https://m.avalanche.state.co.us/api/dispatches/current?type=zone-weather-forecast

Example weather plot download:

https://classic.avalanche.state.co.us/caic/obs_stns/hplot.php?title=VailResort%20CAVMM%20(10303%20ft)%20-%20Vail%20&%20Summit%20County&st=CAVMM&date=2023-05-22-06

Example Wind Rose download:

https://classic.avalanche.state.co.us/caic/obs_stns/windrose.php?st=UP396&date=2023-01-12+17&elev=6325&unit=e&area=caic

Example Weather Station Tables - would require webpage scraping, but may be helpful:

https://classic.avalanche.state.co.us/caic/obs_stns/zones.php?date=2023-05-25+17&stnlink=hourly&unit=e&flag=on&area=caic&span=6
class caic_python.client.CaicApiEndpoints

Bases: object

Endpoints for the CAIC API (api.avalanche.state.co.us).

AVY_OBS: str = '/api/v2/avalanche_observations'
OBS_REPORT: str = '/api/v2/observation_reports'
SNOWPACK_OBS: str = '/api/v2/snowpack_observations'
V1_AVY_OBS: str = '/api/avalanche_observations'
WEATHER_OBS: str = '/api/v2/weather_observations'
ZONES: str = '/api/v2/zones'
ZONES_MAP: str = '/api/v2/zones/map'
class caic_python.client.CaicClient

Bases: object

An async HTTP client for the CAIC API(s).

async avy_forecast(date: str) list[caic_python.models.AvalancheForecast | caic_python.models.RegionalDiscussionForecast]

Get the avalanche forecasts as they were on the given date.

Forecasts cover the date given + the following two days.

Parameters

datestr

The date that the avalanche forecast was produced for.

Returns

list[models.AvalancheForecast | models.RegionalDiscussionForecast]

A list of returned forecasts. The list should contain two types. The localized forecast for detailed areas of CO, and the regional discussion pieces that cover broader portions of the state.

async avy_obs(start: str, end: str, page_limit: int = 1000, ver1: bool = False) list[caic_python.models.AvalancheObservation]

Query for avalanche observations on the CAIC website.

Supports both the v1 and v2 APIs. FWIW, the website still uses v1 for this particular endpoint. My guess is because it supports proper pagination unlike v2, which supports pagination but does not return pagination info in response objects so clients have to guess when they’re done paging.

start and end arguments should be in this format - YYYY-MM-DD HH:mm:ss. However, the return of a datetime.datetime.isoformat() call works as well.

Parameters

startstr

Query for avalanches observed after at this day (and time).

endstr

Query for avalanches observed before this day (and time).

page_limitint, optional

Limit per page results to this amount, by default 1000.

ver1bool, optional

Use the v1 endpoint instead, not recommended, by default False.

Returns

list[models.AvalancheObservation]

A list of all avalanche observations returned by the query.

async avy_observation(obs_id: str) AvalancheObservation | None

Get a single avalanche observation by UUID.

Parameters

obs_idstr

The UUID of the avalanche observation.

Returns

models.AvalancheObservation | None

The retrieved avalanche observation, or None if there was an error validating response.

async bc_zone(zone_slug: str) BackcountryZone | None

Get a single backcountry zone by UUID.

Parameters

zone_slugstr

The zone’s slug name.

Returns

models.BackcountryZone | None

The backcountry zone, or None if there was an error validating response.

async close() None

Close the underlying session.

async field_report(report_id: str) FieldReport | None

Get a single CAIC Feild Report (aka Observation Report) by UUID.

Parameters

report_idstr

The UUID of the field report to retrieve.

Returns

models.FieldReport | None

The retrieved field report, or None if there was an error validating response.

async field_reports(start: str, end: str, bc_zones: list[str] = [], cracking_obs: list[str] = [], collapsing_obs: list[str] = [], query: str = '', avy_seen: bool | None = None, page_limit: int = 100) list[caic_python.models.FieldReport]

Search CAIC field reports.

Replicates the search on the CAIC View Field Reports page.

Parameters

startstr

The start time for the query (observations after this date[+time]).

endstr

The end time for the query (observations before this date[+time]).

bc_zoneslist[str], optional

One or more Backcountry Zones to limit the search results by. Should be one of enums.BCZoneTitles. By default [].

cracking_obslist[str], optional

One or more Cracking Observations to limit the search results by. Should be one of enums.CrackingObsNames. By default [].

collapsing_obslist[str], optional

One or more Collapsing Observations to limit the search results by. Should be one of enums.CollapsingObsNames. By default [].

querystr, optional

A query string to limit searches by, by default “”.

avy_seenbool | None, optional

Whether an avalanche was seen, or None to disable this search modifier, by default None.

page_limitint, optional

Limit the number of pages returned by the API. Must be at least 1 or a value error is raised. By default 100.

Returns

list[models.FieldReport]

All field reports returned by the search.

Raises

ValueError

If page_limit is less than 1.

async highway_zone(zone_slug: str) HighwayZone | None

Get a single highway zone by UUID.

Parameters

zone_slugstr

The zone’s slug name.

Returns

models.HighwayZone | None

The highway zone, or None if there was an error validating response.

async snowpack_observation(obs_id: str) SnowpackObservation | None

Get a single snowpack observation by UUID.

Parameters

obs_idstr

The ID of the snowpack observation.

Returns

models.SnowpackObservation | None

The retrieved snowpack observation, or None if there was an error validating response.

async weather_observation(obs_id: str) WeatherObservation | None

Get a single weather observation by UUID.

Parameters

obs_idstr

The UUID of the weather observation.

Returns

models.WeatherObservation | None

The retrieved weather observation, or None if there was an error validating response.

class caic_python.client.CaicURLs

Bases: object

All the different CAIC URLs that the client needs.

With the exception of the attr for the “home” site’s URL, the other class attrs are named after their subdomain.

API: str = 'https://api.avalanche.state.co.us'
CLSC: str = 'https://classic.avalanche.state.co.us'
HOME: str = 'https://avalanche.state.co.us'
M: str = 'https://m.avalanche.state.co.us'
class caic_python.client.ProxyEndpoints

Bases: object

The known CAIC proxy URLs.

Some underlying APIs (eg. avid) require auth, and this proxy auths for you.

AVID: str = '/api-proxy/avid'
DATA: str = '/api-proxy/caic_data_api'
caic_python.client.list_to_plus_args(argslist: list) str

Join a list of strings using +.

caic_python.definitions module

Mappings of abbreviations to definitions/long-names.

See more on the CAIC website

caic_python.definitions.ASPECT_DESC = {'ALL': 'All aspects', 'All': 'All aspects', 'E': 'East', 'N': 'North', 'NE': 'Northeast', 'NW': 'Northwest', 'S': 'South', 'SE': 'Southeast', 'SW': 'Southwest', 'U': 'Unknown', 'UNK': 'Unknown', 'W': 'West'}

The codes for types of avalanche triggers mapped to their descriptive names.

caic_python.definitions.AVALANCHE_TYPES = {'C': 'Cornice Fall', 'G': 'Glide', 'HS': 'Hard Slab', 'I': 'Ice Fall', 'L': 'Loose', 'R': 'Roof', 'SF': 'Slush Flow', 'SS': 'Soft Slab', 'U': 'Unknown', 'WL': 'Wet Loose', 'WS': 'Wet Slab'}

The codes for types of avalanches mapped to their descriptive names.

caic_python.definitions.D_SIZE_DESC = {'D1': 'Relatively harmless to people', 'D1.5': 'Relatively harmless to people ', 'D2': 'Could bury, injure, or kill a person', 'D2.5': 'Could bury, injure, or kill a person', 'D3': 'Could bury and destroy a car, damage a truck, destroy a wood frame house, or break a few trees', 'D3.5': 'Could bury and destroy a car, damage a truck, destroy a wood frame house, or break a few trees', 'D4': 'Could destroy a railway car, large truck, several buildings, or a substantial amount of trees', 'D4.5': 'Could destroy a railway car, large truck, several buildings, or a substantial amount of trees', 'D5': 'Could gouge the landscape, largest snow avalanche known', 'U': 'Unknown', 'UNK': 'Unknown'}

The codes for avalanche D size mapped to their descriptive names.

caic_python.definitions.ELEV_DESC = {'<TL': 'Below treeline', '>TL': 'Above Treeline', 'TL': 'Near Treeline'}

The codes for elevation bands mapped to their descriptive names.

The API returns the < and > URL encoded - so this object isn’t useful for comparing to API responses.

caic_python.definitions.PRIMARY_TRIGGER_DESC = {'A': 'Unknown', 'AA': 'Artillery', 'AB': 'An explosive detonated above the surface (air blast)', 'AC': 'Cornice fall triggered by explosive action', 'AE': 'An explosive thrown or placed on or under the snow surface by hand', 'AF': 'Foot penetration', 'AH': 'Explosive placed via helicopter', 'AI': 'Snowshoer', 'AK': 'Snowcat', 'AL': 'Avalauncher', 'AM': 'Snowmobile', 'AO': 'Unclassified artificial trigger (Specified in comments)', 'AP': 'Pre-placed, remotely detonated explosive charge', 'AR': 'Snowboarder', 'AS': 'Skier', 'AU': 'Unknown artificial trigger', 'AV': 'Vehicle (Specified in comments)', 'AW': 'Wildlife', 'AX': 'Gas exploder', 'N': 'Natural', 'UKN': 'Unknown'}

The codes for types of primary avalanche triggers mapped to their descriptive names.

caic_python.definitions.R_SIZE_DESC = {'R1': 'Very small, relative to the path', 'R2': 'Small, relative to the path', 'R3': 'Medium, relative to the path', 'R4': 'Large, relative to the path', 'R5': 'Major or maximum, relative to path', 'U': 'Unknown', 'UNK': 'Unknown'}

The codes for avalanche R size mapped to their descriptive names.

caic_python.definitions.SECONDARY_TRIGGER_DESC = {'c': 'A controlled or intentional release', 'r': 'A remote avalanche released by the indicated trigger', 'u': 'An unintentional release', 'y': 'An avalanche released in sympathy with another avalanche'}

The codes for types of secondary avalanche triggers mapped to their descriptive names.

caic_python.enums module

Shared enums for typing/validation.

The CAIC API can return multiple values when the particular code is not known. It is up to callers to normalize these values. They can be any of the following:

U
Un
Unknown
Unkn
UNKNOWN
UNK
---
--
class caic_python.enums.Aspect(value)

Bases: Enum

Slope aspect values.

ALL: str = 'ALL'
All: str = 'All'
DASHES2: str = '--'
DASHES3: str = '---'
E: str = 'E'
N: str = 'N'
NE: str = 'NE'
NW: str = 'NW'
S: str = 'S'
SE: str = 'SE'
SW: str = 'SW'
U: str = 'U'
UNK: str = 'UNK'
UNKNOWN: str = 'UNKNOWN'
Un: str = 'Un'
Unkn: str = 'Unkn'
Unknown: str = 'Unknown'
W: str = 'W'
class caic_python.enums.BCZoneTitles(value)

Bases: Enum

Titles for backcountry zones.

ASPEN = 'Aspen'
FRONT_RANGE = 'Front Range'
GRAND_MESA = 'Grand Mesa'
GUNNINSON = 'Gunnison'
N_SAN_JAUN = 'Northern San Juan'
SANGRE = 'Sangre de Cristo'
SAWATCH = 'Sawatch'
STEAMBOAT = 'Steamboat & Flat Tops'
S_SAN_JAUN = 'Southern San Juan'
VAIL_SUMMIT = 'Vail & Summit County'
class caic_python.enums.DSize(value)

Bases: Enum

Avalanche desctructive size values.

Because these can have half values, P is a substitute for decimals.

D1: str = 'D1'
D1P5: str = 'D1.5'
D2: str = 'D2'
D2P5: str = 'D2.5'
D3: str = 'D3'
D3P5: str = 'D3.5'
D4: str = 'D4'
D4P5: str = 'D4.5'
D5: str = 'D5'
DASHES2: str = '--'
DASHES3: str = '---'
U: str = 'U'
UNK: str = 'UNK'
UNKNOWN: str = 'UNKNOWN'
Un: str = 'Un'
Unkn: str = 'Unkn'
Unknown: str = 'Unknown'
class caic_python.enums.DetailsTypes(value)

Bases: Enum

The types of details objects from Field Reports.

AVY = 'avalanche_detail'
SNOW = 'snowpack_detail'
WEATHER = 'weather_detail'
class caic_python.enums.ObsTypes(value)

Bases: Enum

The types that CAIC observation objects can have.

AVY_OBS: str = 'avalanche_observation'
BC_ZONE: str = 'backcountry_zone'
HWY_ZONE: str = 'highway_zone'
IMAGE_ASSET: str = 'image_asset'
OBS_REPORT: str = 'observation_report'
REPORT_OBS: str = 'report_observation'
SNOWPACK_OBS: str = 'snowpack_observation'
SNOWPIT_ASSET: str = 'snowpit_asset'
VIDEO_ASSET: str = 'video_asset'
WEATHER_OBS: str = 'weather_observation'
class caic_python.enums.PrimaryTrigger(value)

Bases: Enum

Avalanche primary trigger codes.

A: str = 'A'
AA: str = 'AA'
AB: str = 'AB'
AC: str = 'AC'
AE: str = 'AE'
AF: str = 'AF'
AH: str = 'AH'
AI: str = 'AI'
AK: str = 'AK'
AL: str = 'AL'
AM: str = 'AM'
AN: str = 'AN'
AO: str = 'AO'
AP: str = 'AP'
AR: str = 'AR'
AS: str = 'AS'
AU: str = 'AU'
AV: str = 'AV'
AW: str = 'AW'
AX: str = 'AX'
DASHES2: str = '--'
DASHES3: str = '---'
N: str = 'N'
U: str = 'U'
UKN: str = 'UKN'
UNKNOWN: str = 'UNKNOWN'
Un: str = 'Un'
Unkn: str = 'Unkn'
Unknown: str = 'Unknown'
class caic_python.enums.RSize(value)

Bases: Enum

Avalanche relative size values.

DASHES2: str = '--'
DASHES3: str = '---'
R1: str = 'R1'
R2: str = 'R2'
R3: str = 'R3'
R4: str = 'R4'
R5: str = 'R5'
U: str = 'U'
UNK: str = 'UNK'
UNKNOWN: str = 'UNKNOWN'
Un: str = 'Un'
Unkn: str = 'Unkn'
Unknown: str = 'Unknown'
class caic_python.enums.ReportsSearchAvyObs(value)

Bases: Enum

Avalanche observation options in a Field Reports search.

CAUGHT = 'Caught'
SAW = 'Saw'
TRIGGERED = 'Triggered'
class caic_python.enums.ReportsSearchCollapseObs(value)

Bases: Enum

Collapsing observation options in a Field Reports search.

MINOR = 'Minor'
MODERATE = 'Moderate'
NONE = 'None'
RUMBLING = 'Rumbling'
UNKNOWN = 'Unknown'
class caic_python.enums.ReportsSearchCrackObs(value)

Bases: Enum

Cracking observation options in a Field Reports search.

MINOR = 'Minor'
MODERATE = 'Moderate'
NONE = 'None'
SHOOTING = 'Shooting'
UNKNOWN = 'Unknown'
class caic_python.enums.SecondaryTrigger(value)

Bases: Enum

Avalanche secondary trigger codes.

DASHES2: str = '--'
DASHES3: str = '---'
U: str = 'U'
UNK: str = 'UNK'
UNKNOWN: str = 'UNKNOWN'
Un: str = 'Un'
Unkn: str = 'Unkn'
Unknown: str = 'Unknown'
c: str = 'c'
r: str = 'r'
u: str = 'u'
y: str = 'y'
class caic_python.enums.TypeCode(value)

Bases: Enum

Avalanche type codes.

C: str = 'C'
DASHES2: str = '--'
DASHES3: str = '---'
G: str = 'G'
HS: str = 'HS'
I: str = 'I'
L: str = 'L'
R: str = 'R'
SF: str = 'SF'
SS: str = 'SS'
U: str = 'U'
UNK: str = 'UNK'
UNKNOWN: str = 'UNKNOWN'
Un: str = 'Un'
Unkn: str = 'Unkn'
Unknown: str = 'Unknown'
WL: str = 'WL'
WS: str = 'WS'

caic_python.errors module

caic-python errors.

exception caic_python.errors.CaicRequestException

Bases: Exception

An exception that ocurred during a request to the CAIC website.

caic_python.models module

Pydantic models used by caic-python.

class caic_python.models.AvalancheDetail(*, id: str, type: DetailsTypes, description: str | None = None, classic_id: int | None = None)

Bases: DetailObject

Summary details of an observed avalanche.

model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'classic_id': FieldInfo(annotation=Union[int, NoneType], required=False), 'description': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'type': FieldInfo(annotation=DetailsTypes, required=True)}
class caic_python.models.AvalancheForecast(*, id: str, title: str, type: Literal['avalancheforecast'], polygons: list, areaId: str, forecaster: str, issueDateTime: datetime, expiryDateTime: datetime, weatherSummary: ForecastSummary, snowpackSummary: ForecastSummary, avalancheSummary: ForecastSummary, avalancheProblems: AvalancheProblems, terrainAndTravelAdvice: dict, confidence: ForecastConfidences, communication: ForecastComms, dangerRatings: DangerRatings, media: ForecastMedia)

Bases: BaseModel

A CAIC avalanche forecast.

areaId: str
avalancheProblems: AvalancheProblems
avalancheSummary: ForecastSummary
communication: ForecastComms
confidence: ForecastConfidences
dangerRatings: DangerRatings
expiryDateTime: datetime
forecaster: str
id: str
issueDateTime: datetime
media: ForecastMedia
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'areaId': FieldInfo(annotation=str, required=True), 'avalancheProblems': FieldInfo(annotation=AvalancheProblems, required=True), 'avalancheSummary': FieldInfo(annotation=ForecastSummary, required=True), 'communication': FieldInfo(annotation=ForecastComms, required=True), 'confidence': FieldInfo(annotation=ForecastConfidences, required=True), 'dangerRatings': FieldInfo(annotation=DangerRatings, required=True), 'expiryDateTime': FieldInfo(annotation=datetime, required=True), 'forecaster': FieldInfo(annotation=str, required=True), 'id': FieldInfo(annotation=str, required=True), 'issueDateTime': FieldInfo(annotation=datetime, required=True), 'media': FieldInfo(annotation=ForecastMedia, required=True), 'polygons': FieldInfo(annotation=list, required=True), 'snowpackSummary': FieldInfo(annotation=ForecastSummary, required=True), 'terrainAndTravelAdvice': FieldInfo(annotation=dict, required=True), 'title': FieldInfo(annotation=str, required=True), 'type': FieldInfo(annotation=Literal[str], required=True), 'weatherSummary': FieldInfo(annotation=ForecastSummary, required=True)}
polygons: list
snowpackSummary: ForecastSummary
terrainAndTravelAdvice: dict
title: str
type: Literal['avalancheforecast']
weatherSummary: ForecastSummary
class caic_python.models.AvalancheObservation(*, id: str, type: str | None = None, backcountry_zone_id: str | None = None, backcountry_zone: BackcountryZone | None = None, highway_zone_id: str | None = None, observed_at: datetime | None = None, created_at: datetime | None = None, updated_at: datetime | None = None, latitude: float | None = None, longitude: float | None = None, classic_id: int | None = None, classic_observation_report_id: int | None = None, classic_observation_report_url: str | None = None, observation_report_status: str | None = None, observation_report_url: str | None = None, comments: str | None = None, location: str | None = None, lastname: str | None = None, full_name: str | None = None, date_known: str | None = None, time_known: str | None = None, op_name: str | None = None, is_locked: bool | None = None, number: int | None = None, hw_op_bc: str | None = None, path: str | None = None, landmark: str | None = None, type_code: TypeCode | None = None, problem_type: str | None = None, aspect: Aspect | None = None, elevation: str | None = None, relative_size: RSize | None = None, destructive_size: DSize | None = None, primary_trigger: PrimaryTrigger | None = None, secondary_trigger: SecondaryTrigger | None = None, is_incident: bool | None = None, area: str | None = None, angle_average: float | None = None, angle_maximum: float | None = None, elevation_feet: int | None = None, surface: str | None = None, weak_layer: str | None = None, grain_type: str | None = None, crown_average: float | None = None, crown_maximum: float | None = None, crown_units: str | None = None, width_average: float | None = None, width_maximum: float | None = None, width_units: str | None = None, vertical_average: float | None = None, vertical_maximum: float | None = None, vertical_units: str | None = None, terminus: str | None = None, road_status: str | None = None, road_depth: float | None = None, road_units: str | None = None, road_depth_units: str | None = None, road_length: int | float | None = None, road_length_units: str | None = None, observation_report: ObsReport | None = None, avalanche_detail: AvalancheDetail | None = None)

Bases: BaseModel

A single avalanche observation from the CAIC website.

angle_average: float | None
angle_maximum: float | None
area: str | None
aspect: Aspect | None
avalanche_detail: AvalancheDetail | None
backcountry_zone: BackcountryZone | None
backcountry_zone_id: str | None
classic_id: int | None
classic_observation_report_id: int | None
classic_observation_report_url: str | None
comments: str | None
created_at: datetime | None
crown_average: float | None
crown_maximum: float | None
crown_units: str | None
date_known: str | None
destructive_size: DSize | None
elevation: str | None
elevation_feet: int | None
async fieldobs(caic_client) FieldReport | None

Get the associated FieldReport using the provided CaicClient.

full_name: str | None
grain_type: str | None
highway_zone_id: str | None
hw_op_bc: str | None
id: str
is_incident: bool | None
is_locked: bool | None
landmark: str | None
lastname: str | None
latitude: float | None
location: str | None
longitude: float | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'angle_average': FieldInfo(annotation=Union[float, NoneType], required=False), 'angle_maximum': FieldInfo(annotation=Union[float, NoneType], required=False), 'area': FieldInfo(annotation=Union[str, NoneType], required=False), 'aspect': FieldInfo(annotation=Union[Aspect, NoneType], required=False), 'avalanche_detail': FieldInfo(annotation=Union[AvalancheDetail, NoneType], required=False), 'backcountry_zone': FieldInfo(annotation=Union[BackcountryZone, NoneType], required=False), 'backcountry_zone_id': FieldInfo(annotation=Union[str, NoneType], required=False), 'classic_id': FieldInfo(annotation=Union[int, NoneType], required=False, description='V1 only'), 'classic_observation_report_id': FieldInfo(annotation=Union[int, NoneType], required=False, description='V1 only'), 'classic_observation_report_url': FieldInfo(annotation=Union[str, NoneType], required=False, description='V1 only'), 'comments': FieldInfo(annotation=Union[str, NoneType], required=False), 'created_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'crown_average': FieldInfo(annotation=Union[float, NoneType], required=False), 'crown_maximum': FieldInfo(annotation=Union[float, NoneType], required=False), 'crown_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'date_known': FieldInfo(annotation=Union[str, NoneType], required=False), 'destructive_size': FieldInfo(annotation=Union[DSize, NoneType], required=False), 'elevation': FieldInfo(annotation=Union[str, NoneType], required=False), 'elevation_feet': FieldInfo(annotation=Union[int, NoneType], required=False), 'full_name': FieldInfo(annotation=Union[str, NoneType], required=False), 'grain_type': FieldInfo(annotation=Union[str, NoneType], required=False), 'highway_zone_id': FieldInfo(annotation=Union[str, NoneType], required=False), 'hw_op_bc': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'is_incident': FieldInfo(annotation=Union[bool, NoneType], required=False), 'is_locked': FieldInfo(annotation=Union[bool, NoneType], required=False), 'landmark': FieldInfo(annotation=Union[str, NoneType], required=False), 'lastname': FieldInfo(annotation=Union[str, NoneType], required=False), 'latitude': FieldInfo(annotation=Union[float, NoneType], required=False), 'location': FieldInfo(annotation=Union[str, NoneType], required=False), 'longitude': FieldInfo(annotation=Union[float, NoneType], required=False), 'number': FieldInfo(annotation=Union[int, NoneType], required=False), 'observation_report': FieldInfo(annotation=Union[ObsReport, NoneType], required=False), 'observation_report_status': FieldInfo(annotation=Union[str, NoneType], required=False, description='V1 only'), 'observation_report_url': FieldInfo(annotation=Union[str, NoneType], required=False, description='V1 only'), 'observed_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'op_name': FieldInfo(annotation=Union[str, NoneType], required=False), 'path': FieldInfo(annotation=Union[str, NoneType], required=False), 'primary_trigger': FieldInfo(annotation=Union[PrimaryTrigger, NoneType], required=False), 'problem_type': FieldInfo(annotation=Union[str, NoneType], required=False), 'relative_size': FieldInfo(annotation=Union[RSize, NoneType], required=False), 'road_depth': FieldInfo(annotation=Union[float, NoneType], required=False), 'road_depth_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'road_length': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'road_length_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'road_status': FieldInfo(annotation=Union[str, NoneType], required=False), 'road_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'secondary_trigger': FieldInfo(annotation=Union[SecondaryTrigger, NoneType], required=False), 'surface': FieldInfo(annotation=Union[str, NoneType], required=False), 'terminus': FieldInfo(annotation=Union[str, NoneType], required=False), 'time_known': FieldInfo(annotation=Union[str, NoneType], required=False), 'type': FieldInfo(annotation=Union[str, NoneType], required=False), 'type_code': FieldInfo(annotation=Union[TypeCode, NoneType], required=False), 'updated_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'vertical_average': FieldInfo(annotation=Union[float, NoneType], required=False), 'vertical_maximum': FieldInfo(annotation=Union[float, NoneType], required=False), 'vertical_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'weak_layer': FieldInfo(annotation=Union[str, NoneType], required=False), 'width_average': FieldInfo(annotation=Union[float, NoneType], required=False), 'width_maximum': FieldInfo(annotation=Union[float, NoneType], required=False), 'width_units': FieldInfo(annotation=Union[str, NoneType], required=False)}
number: int | None
observation_report: ObsReport | None
observation_report_status: str | None
observation_report_url: str | None
observed_at: datetime | None
op_name: str | None
path: str | None
primary_trigger: PrimaryTrigger | None
problem_type: str | None
relative_size: RSize | None
road_depth: float | None
road_depth_units: str | None
road_length: int | float | None
road_length_units: str | None
road_status: str | None
road_units: str | None
secondary_trigger: SecondaryTrigger | None
surface: str | None
terminus: str | None
time_known: str | None
type: str | None
type_code: TypeCode | None
updated_at: datetime | None
vertical_average: float | None
vertical_maximum: float | None
vertical_units: str | None
weak_layer: str | None
width_average: float | None
width_maximum: float | None
width_units: str | None
class caic_python.models.AvalancheProblem(*, type: str, aspectElevations: list[str], likelihood: str, expectedSize: ExpectedSize, comment: str)

Bases: BaseModel

A described avalanche problem in a forecast.

TODO - enums here for everything

aspectElevations: list[str]
comment: str
expectedSize: ExpectedSize
likelihood: str
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'aspectElevations': FieldInfo(annotation=list[str], required=True), 'comment': FieldInfo(annotation=str, required=True), 'expectedSize': FieldInfo(annotation=ExpectedSize, required=True), 'likelihood': FieldInfo(annotation=str, required=True), 'type': FieldInfo(annotation=str, required=True)}
type: str
class caic_python.models.AvalancheProblems(*, days: list[list[caic_python.models.AvalancheProblem]])

Bases: BaseModel

A collection of the next few days’ avalanche problems.

days: list[list[caic_python.models.AvalancheProblem]]
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'days': FieldInfo(annotation=list[list[AvalancheProblem]], required=True)}
class caic_python.models.BackcountryZone(*, id: str, type: ObsTypes, parent_id: str | None = None, slug: str | None = None, title: str | None = None, category: str | None = None, category_order: int | None = None, is_root: bool | None = None, is_leaf: bool | None = None, tree_level: int | None = None, parent_url: str | None = None, created_at: datetime | None = None, updated_at: datetime | None = None, url: str | None = None, geojson_url: str | None = None)

Bases: BaseModel

A backcountry_zone object - these are in most responses.

category: str | None
category_order: int | None
created_at: datetime | None
geojson_url: str | None
id: str
is_leaf: bool | None
is_root: bool | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'category': FieldInfo(annotation=Union[str, NoneType], required=False), 'category_order': FieldInfo(annotation=Union[int, NoneType], required=False), 'created_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'geojson_url': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'is_leaf': FieldInfo(annotation=Union[bool, NoneType], required=False), 'is_root': FieldInfo(annotation=Union[bool, NoneType], required=False), 'parent_id': FieldInfo(annotation=Union[str, NoneType], required=False), 'parent_url': FieldInfo(annotation=Union[str, NoneType], required=False), 'slug': FieldInfo(annotation=Union[str, NoneType], required=False), 'title': FieldInfo(annotation=Union[str, NoneType], required=False), 'tree_level': FieldInfo(annotation=Union[int, NoneType], required=False), 'type': FieldInfo(annotation=ObsTypes, required=True), 'updated_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'url': FieldInfo(annotation=Union[str, NoneType], required=False)}
parent_id: str | None
parent_url: str | None
slug: str | None
title: str | None
tree_level: int | None
type: ObsTypes
updated_at: datetime | None
url: str | None

Bases: BaseModel

The links portion of a V1AvyResponse.

Contains pagination info.

first: str | None
last: str | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'first': FieldInfo(annotation=Union[str, NoneType], required=False), 'last': FieldInfo(annotation=Union[str, NoneType], required=False), 'next': FieldInfo(annotation=Union[str, NoneType], required=False), 'prev': FieldInfo(annotation=Union[str, NoneType], required=False)}
next: str | None
prev: str | None
class caic_python.models.CaicResponseMeta(*, current_page: int, page_items: int, total_pages: int, total_count: int)

Bases: BaseModel

The meta portion of a V1AvyResponse.

Contains pagination info.

current_page: int
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'current_page': FieldInfo(annotation=int, required=True), 'page_items': FieldInfo(annotation=int, required=True), 'total_count': FieldInfo(annotation=int, required=True), 'total_pages': FieldInfo(annotation=int, required=True)}
page_items: int
total_count: int
total_pages: int
class caic_python.models.Creator(*, id: str, type: str)

Bases: BaseModel

The creator object of a field report.

We’ll want to track this, but it is sparse on details.

id: str
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'id': FieldInfo(annotation=str, required=True), 'type': FieldInfo(annotation=str, required=True)}
type: str
class caic_python.models.DangerRating(*, position: int, alp: str, tln: str, btl: str, date: datetime)

Bases: BaseModel

An avalanche forecast’s danger rating.

TODO - enums for everything here.

alp: str
btl: str
date: datetime
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'alp': FieldInfo(annotation=str, required=True), 'btl': FieldInfo(annotation=str, required=True), 'date': FieldInfo(annotation=datetime, required=True), 'position': FieldInfo(annotation=int, required=True), 'tln': FieldInfo(annotation=str, required=True)}
position: int
tln: str
class caic_python.models.DangerRatings(*, days: list[caic_python.models.DangerRating])

Bases: BaseModel

A list of the avalanche danger ratings for the next few days.

days: list[caic_python.models.DangerRating]
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'days': FieldInfo(annotation=list[DangerRating], required=True)}
class caic_python.models.DetailObject(*, id: str, type: DetailsTypes, description: str | None = None, classic_id: int | None = None)

Bases: BaseModel

A base for several, similar, details objects attached to a field report.

This is where classic_id ended up in the V2 API.

classic_id: int | None
description: str | None
id: str
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'classic_id': FieldInfo(annotation=Union[int, NoneType], required=False), 'description': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'type': FieldInfo(annotation=DetailsTypes, required=True)}
type: DetailsTypes
class caic_python.models.ExpectedSize(*, min: str, max: str)

Bases: BaseModel

Expected avalanche size in an avalanche forecast.

max: str
min: str
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'max': FieldInfo(annotation=str, required=True), 'min': FieldInfo(annotation=str, required=True)}
class caic_python.models.FieldReport(*, id: str, type: ObsTypes, backcountry_zone: BackcountryZone | None = None, url: str | None = None, creator: Creator | None = None, avalanche_observations_count: int | None = None, avalanche_observations: list[caic_python.models.AvalancheObservation] | None = None, avalanche_detail: AvalancheDetail | None = None, weather_observations_count: int | None = None, weather_observations: list[caic_python.models.WeatherObservation] | None = None, weather_detail: WeatherDetail | None = None, snowpack_observations_count: int | None = None, snowpack_observations: list[caic_python.models.SnowpackObservation] | None = None, assets_count: int | None = None, assets: list[caic_python.models.ObservationAsset] | None = None, highway_zone_id: str | None = None, observed_at: datetime | None = None, snowpack_detail: SnowpackDetail | None = None, observation_form: str | None = None, is_anonymous: bool | None = None, firstname: str | None = None, lastname: str | None = None, full_name: str | None = None, organization: str | None = None, status: str | None = None, date_known: str | None = None, time_known: str | None = None, hw_op_bc: str | None = None, area: str | None = None, route: str | None = None, is_locked: bool | None = None, objective: str | None = None, saw_avalanche: bool | None = None, triggered_avalanche: bool | None = None, caught_in_avalanche: bool | None = None, state: str | None = None, landmark: str | None = None, description: str | None = None, created_at: datetime | None = None, updated_at: datetime | None = None, is_anonymous_location: bool | None = None, latitude: float | None = None, longitude: float | None = None)

Bases: BaseModel

A field (or observation) report.

area: str | None
assets: list[caic_python.models.ObservationAsset] | None
assets_count: int | None
avalanche_detail: AvalancheDetail | None
avalanche_observations: list[caic_python.models.AvalancheObservation] | None
avalanche_observations_count: int | None
backcountry_zone: BackcountryZone | None
caught_in_avalanche: bool | None
created_at: datetime | None
creator: Creator | None
date_known: str | None
description: str | None
firstname: str | None
full_name: str | None
highway_zone_id: str | None
hw_op_bc: str | None
id: str
is_anonymous: bool | None
is_anonymous_location: bool | None
is_locked: bool | None
landmark: str | None
lastname: str | None
latitude: float | None
longitude: float | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'area': FieldInfo(annotation=Union[str, NoneType], required=False), 'assets': FieldInfo(annotation=Union[list[ObservationAsset], NoneType], required=False, default_factory=list), 'assets_count': FieldInfo(annotation=Union[int, NoneType], required=False), 'avalanche_detail': FieldInfo(annotation=Union[AvalancheDetail, NoneType], required=False), 'avalanche_observations': FieldInfo(annotation=Union[list[AvalancheObservation], NoneType], required=False, default_factory=list), 'avalanche_observations_count': FieldInfo(annotation=Union[int, NoneType], required=False), 'backcountry_zone': FieldInfo(annotation=Union[BackcountryZone, NoneType], required=False), 'caught_in_avalanche': FieldInfo(annotation=Union[bool, NoneType], required=False), 'created_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'creator': FieldInfo(annotation=Union[Creator, NoneType], required=False), 'date_known': FieldInfo(annotation=Union[str, NoneType], required=False), 'description': FieldInfo(annotation=Union[str, NoneType], required=False), 'firstname': FieldInfo(annotation=Union[str, NoneType], required=False), 'full_name': FieldInfo(annotation=Union[str, NoneType], required=False), 'highway_zone_id': FieldInfo(annotation=Union[str, NoneType], required=False), 'hw_op_bc': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'is_anonymous': FieldInfo(annotation=Union[bool, NoneType], required=False), 'is_anonymous_location': FieldInfo(annotation=Union[bool, NoneType], required=False), 'is_locked': FieldInfo(annotation=Union[bool, NoneType], required=False), 'landmark': FieldInfo(annotation=Union[str, NoneType], required=False), 'lastname': FieldInfo(annotation=Union[str, NoneType], required=False), 'latitude': FieldInfo(annotation=Union[float, NoneType], required=False), 'longitude': FieldInfo(annotation=Union[float, NoneType], required=False), 'objective': FieldInfo(annotation=Union[str, NoneType], required=False), 'observation_form': FieldInfo(annotation=Union[str, NoneType], required=False), 'observed_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'organization': FieldInfo(annotation=Union[str, NoneType], required=False), 'route': FieldInfo(annotation=Union[str, NoneType], required=False), 'saw_avalanche': FieldInfo(annotation=Union[bool, NoneType], required=False), 'snowpack_detail': FieldInfo(annotation=Union[SnowpackDetail, NoneType], required=False), 'snowpack_observations': FieldInfo(annotation=Union[list[SnowpackObservation], NoneType], required=False, default_factory=list), 'snowpack_observations_count': FieldInfo(annotation=Union[int, NoneType], required=False), 'state': FieldInfo(annotation=Union[str, NoneType], required=False), 'status': FieldInfo(annotation=Union[str, NoneType], required=False), 'time_known': FieldInfo(annotation=Union[str, NoneType], required=False), 'triggered_avalanche': FieldInfo(annotation=Union[bool, NoneType], required=False), 'type': FieldInfo(annotation=ObsTypes, required=True), 'updated_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'url': FieldInfo(annotation=Union[str, NoneType], required=False), 'weather_detail': FieldInfo(annotation=Union[WeatherDetail, NoneType], required=False), 'weather_observations': FieldInfo(annotation=Union[list[WeatherObservation], NoneType], required=False, default_factory=list), 'weather_observations_count': FieldInfo(annotation=Union[int, NoneType], required=False)}
objective: str | None
observation_form: str | None
observed_at: datetime | None
organization: str | None
route: str | None
saw_avalanche: bool | None
snowpack_detail: SnowpackDetail | None
snowpack_observations: list[caic_python.models.SnowpackObservation] | None
snowpack_observations_count: int | None
state: str | None
status: str | None
time_known: str | None
triggered_avalanche: bool | None
type: ObsTypes
updated_at: datetime | None
url: str | None
weather_detail: WeatherDetail | None
weather_observations: list[caic_python.models.WeatherObservation] | None
weather_observations_count: int | None
class caic_python.models.ForecastComms(*, headline: str, sms: str)

Bases: BaseModel

Special forecast communications - not sure how this get’s used yet.

headline: str
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'headline': FieldInfo(annotation=str, required=True), 'sms': FieldInfo(annotation=str, required=True)}
sms: str
class caic_python.models.ForecastConfidence(*, date: datetime, rating: str, statements: list[str] = None)

Bases: BaseModel

An avalanche forecast’s confidence details.

date: datetime
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'date': FieldInfo(annotation=datetime, required=True), 'rating': FieldInfo(annotation=str, required=True), 'statements': FieldInfo(annotation=list[str], required=False, default_factory=list)}
rating: str
statements: list[str]
class caic_python.models.ForecastConfidences(*, days: list[caic_python.models.ForecastConfidence])

Bases: BaseModel

The avalanche forecast confidence details for the next few days.

days: list[caic_python.models.ForecastConfidence]
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'days': FieldInfo(annotation=list[ForecastConfidence], required=True)}
class caic_python.models.ForecastImage(*, id: str, url: str, width: int, height: int, credit: str, caption: str, tag: str)

Bases: BaseModel

An image attached to an avalanche forecast.

caption: str
credit: str
height: int
id: str
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'caption': FieldInfo(annotation=str, required=True), 'credit': FieldInfo(annotation=str, required=True), 'height': FieldInfo(annotation=int, required=True), 'id': FieldInfo(annotation=str, required=True), 'tag': FieldInfo(annotation=str, required=True), 'url': FieldInfo(annotation=str, required=True), 'width': FieldInfo(annotation=int, required=True)}
tag: str
url: str
width: int
class caic_python.models.ForecastMedia(*, Images: list[caic_python.models.ForecastImage])

Bases: BaseModel

All of the images attached to an avalanche forecast.

Images: list[caic_python.models.ForecastImage]
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'Images': FieldInfo(annotation=list[ForecastImage], required=True)}
class caic_python.models.ForecastSummary(*, days: list[caic_python.models.ForecastSummaryDay])

Bases: BaseModel

Forecast summaries for several days - base for several forecast types.

days: list[caic_python.models.ForecastSummaryDay]
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'days': FieldInfo(annotation=list[ForecastSummaryDay], required=True)}
class caic_python.models.ForecastSummaryDay(*, date: datetime | None, content: str | None)

Bases: BaseModel

An individual day’s forecast summary - base for several forecast types.

content: str | None
date: datetime | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'content': FieldInfo(annotation=Union[str, NoneType], required=True), 'date': FieldInfo(annotation=Union[datetime, NoneType], required=True)}
class caic_python.models.HighwayZone(*, id: str | None = None, type: str | None = None, parent_id: str | None = None, slug: str | None = None, title: str | None = None, category: str | None = None, category_order: int | None = None, is_root: bool | None = None, is_leaf: bool | None = None, tree_level: int | None = None, parent_url: str | None = None, children_urls: list[str] | None = None, created_at: datetime | None = None, updated_at: datetime | None = None, url: str | None = None, geojson_url: str | None = None)

Bases: BaseModel

A highway avalanche zone - similar to a BC zone but specific to CDOT/CAIC avy control.

category: str | None
category_order: int | None
children_urls: list[str] | None
created_at: datetime | None
geojson_url: str | None
id: str | None
is_leaf: bool | None
is_root: bool | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'category': FieldInfo(annotation=Union[str, NoneType], required=False), 'category_order': FieldInfo(annotation=Union[int, NoneType], required=False), 'children_urls': FieldInfo(annotation=Union[list[str], NoneType], required=False, default_factory=list), 'created_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'geojson_url': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=Union[str, NoneType], required=False), 'is_leaf': FieldInfo(annotation=Union[bool, NoneType], required=False), 'is_root': FieldInfo(annotation=Union[bool, NoneType], required=False), 'parent_id': FieldInfo(annotation=Union[str, NoneType], required=False), 'parent_url': FieldInfo(annotation=Union[str, NoneType], required=False), 'slug': FieldInfo(annotation=Union[str, NoneType], required=False), 'title': FieldInfo(annotation=Union[str, NoneType], required=False), 'tree_level': FieldInfo(annotation=Union[int, NoneType], required=False), 'type': FieldInfo(annotation=Union[str, NoneType], required=False), 'updated_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'url': FieldInfo(annotation=Union[str, NoneType], required=False)}
parent_id: str | None
parent_url: str | None
slug: str | None
title: str | None
tree_level: int | None
type: str | None
updated_at: datetime | None
url: str | None
class caic_python.models.ObsReport(*, id: str | None = None, status: str | None = None, is_locked: bool | None = None, is_anonymous: bool | None = None, url: str | None = None)

Bases: BaseModel

Really a pared down FieldReport.

id: str | None
is_anonymous: bool | None
is_locked: bool | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'id': FieldInfo(annotation=Union[str, NoneType], required=False), 'is_anonymous': FieldInfo(annotation=Union[bool, NoneType], required=False), 'is_locked': FieldInfo(annotation=Union[bool, NoneType], required=False), 'status': FieldInfo(annotation=Union[str, NoneType], required=False), 'url': FieldInfo(annotation=Union[str, NoneType], required=False)}
status: str | None
url: str | None
class caic_python.models.ObservationAsset(*, id: str, type: ObsTypes, status: str | None = None, caption: str | None = None, tags: list[str] | None = None, is_redacted: bool | None = None, is_locked: bool | None = None, is_avalanche: bool | None = None, location_context: str | None = None, full_url: str | None = None, reduced_url: str | None = None, thumb_url: str | None = None, external_url: str | None = None, created_at: datetime | None = None, updated_at: datetime | None = None)

Bases: BaseModel

An asset (image/video) attached to a field report.

caption: str | None
created_at: datetime | None
external_url: str | None
full_url: str | None
id: str
is_avalanche: bool | None
is_locked: bool | None
is_redacted: bool | None
location_context: str | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'caption': FieldInfo(annotation=Union[str, NoneType], required=False), 'created_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'external_url': FieldInfo(annotation=Union[str, NoneType], required=False), 'full_url': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'is_avalanche': FieldInfo(annotation=Union[bool, NoneType], required=False), 'is_locked': FieldInfo(annotation=Union[bool, NoneType], required=False), 'is_redacted': FieldInfo(annotation=Union[bool, NoneType], required=False), 'location_context': FieldInfo(annotation=Union[str, NoneType], required=False), 'reduced_url': FieldInfo(annotation=Union[str, NoneType], required=False), 'status': FieldInfo(annotation=Union[str, NoneType], required=False), 'tags': FieldInfo(annotation=Union[list[str], NoneType], required=False, default_factory=list), 'thumb_url': FieldInfo(annotation=Union[str, NoneType], required=False), 'type': FieldInfo(annotation=ObsTypes, required=True), 'updated_at': FieldInfo(annotation=Union[datetime, NoneType], required=False)}
reduced_url: str | None
status: str | None
tags: list[str] | None
thumb_url: str | None
type: ObsTypes
updated_at: datetime | None
class caic_python.models.RegionalDiscussionForecast(*, id: str, title: str, type: str, polygons: list[str], areaId: str, forecaster: str, issueDateTime: datetime, expiryDateTime: datetime, message: str, communications: ForecastComms, media: ForecastMedia)

Bases: BaseModel

An avalanche forecast discussion covering a regional area.

areaId: str
communications: ForecastComms
expiryDateTime: datetime
forecaster: str
id: str
issueDateTime: datetime
media: ForecastMedia
message: str
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'areaId': FieldInfo(annotation=str, required=True), 'communications': FieldInfo(annotation=ForecastComms, required=True), 'expiryDateTime': FieldInfo(annotation=datetime, required=True), 'forecaster': FieldInfo(annotation=str, required=True), 'id': FieldInfo(annotation=str, required=True), 'issueDateTime': FieldInfo(annotation=datetime, required=True), 'media': FieldInfo(annotation=ForecastMedia, required=True), 'message': FieldInfo(annotation=str, required=True), 'polygons': FieldInfo(annotation=list[str], required=True), 'title': FieldInfo(annotation=str, required=True), 'type': FieldInfo(annotation=str, required=True)}
polygons: list[str]
title: str
type: str
class caic_python.models.SnowpackDetail(*, id: str, type: DetailsTypes, description: str | None = None, classic_id: int | None = None)

Bases: DetailObject

Summary details of the observed snowpack.

model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'classic_id': FieldInfo(annotation=Union[int, NoneType], required=False), 'description': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'type': FieldInfo(annotation=DetailsTypes, required=True)}
class caic_python.models.SnowpackObservation(*, id: str, type: ObsTypes, backcountry_zone_id: str | None = None, backcountry_zone: BackcountryZone | None = None, highway_zone_id: str | None = None, observed_at: datetime | None = None, created_at: datetime | None = None, updated_at: datetime | None = None, latitude: float | None = None, longitude: float | None = None, comments: str | None = None, url: str | None = None, cracking: str | None = None, collapsing: str | None = None, weak_layers: str | None = None, rose: str | None = None)

Bases: BaseModel

An observation about the snowpack in a field report.

backcountry_zone: BackcountryZone | None
backcountry_zone_id: str | None
collapsing: str | None
comments: str | None
cracking: str | None
created_at: datetime | None
highway_zone_id: str | None
id: str
latitude: float | None
longitude: float | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'backcountry_zone': FieldInfo(annotation=Union[BackcountryZone, NoneType], required=False), 'backcountry_zone_id': FieldInfo(annotation=Union[str, NoneType], required=False), 'collapsing': FieldInfo(annotation=Union[str, NoneType], required=False), 'comments': FieldInfo(annotation=Union[str, NoneType], required=False), 'cracking': FieldInfo(annotation=Union[str, NoneType], required=False), 'created_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'highway_zone_id': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'latitude': FieldInfo(annotation=Union[float, NoneType], required=False), 'longitude': FieldInfo(annotation=Union[float, NoneType], required=False), 'observed_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'rose': FieldInfo(annotation=Union[str, NoneType], required=False), 'type': FieldInfo(annotation=ObsTypes, required=True), 'updated_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'url': FieldInfo(annotation=Union[str, NoneType], required=False), 'weak_layers': FieldInfo(annotation=Union[str, NoneType], required=False)}
observed_at: datetime | None
rose: str | None
type: ObsTypes
updated_at: datetime | None
url: str | None
weak_layers: str | None
class caic_python.models.V1AvalancheObservation(*, id: str, type: ObsTypes, attributes: dict, relationships: dict)

Bases: BaseModel

A single avalanche observation from the /api/avalanche_observations endpoint.

The /api/avalanche_observations endpoint returns a slightly different object than the v2 avalanche_observations endpoint.

This object allows us to transform to the standardized AvalancheObservation via to_obs.

attributes: dict
id: str
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'attributes': FieldInfo(annotation=dict, required=True), 'id': FieldInfo(annotation=str, required=True), 'relationships': FieldInfo(annotation=dict, required=True), 'type': FieldInfo(annotation=ObsTypes, required=True)}
relationships: dict
to_obs() AvalancheObservation

Convert this instance to an AvalancheObservation.

type: ObsTypes
class caic_python.models.V1AvyResponse(*, meta: CaicResponseMeta, links: CaicResponseLinks, data: list[caic_python.models.AvalancheObservation])

Bases: BaseModel

A response from the CAIC API.

data: list[caic_python.models.AvalancheObservation]
meta: CaicResponseMeta
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'data': FieldInfo(annotation=list[AvalancheObservation], required=True), 'links': FieldInfo(annotation=CaicResponseLinks, required=True), 'meta': FieldInfo(annotation=CaicResponseMeta, required=True)}
class caic_python.models.WeatherDetail(*, id: str, type: DetailsTypes, description: str | None = None, classic_id: int | None = None)

Bases: DetailObject

Summary details of the observed weather.

There is occasionally data here even when not in weather_observations for a field report.

model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'classic_id': FieldInfo(annotation=Union[int, NoneType], required=False), 'description': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'type': FieldInfo(annotation=DetailsTypes, required=True)}
class caic_python.models.WeatherObservation(*, id: str, type: ObsTypes, backcountry_zone_id: str | None = None, backcountry_zone: BackcountryZone | None = None, highway_zone_id: str | None = None, highway_zone: HighwayZone | None = None, observed_at: datetime | None = None, created_at: datetime | None = None, updated_at: datetime | None = None, latitude: float | None = None, longitude: float | None = None, classic_id: int | None = None, classic_observation_report_id: int | None = None, classic_observation_report_url: str | None = None, comments: str | None = None, url: str | None = None, location: str | None = None, temperature: int | float | None = None, temperature_maximum: int | float | None = None, temperature_minimum: int | float | None = None, temperature_units: str | None = None, temperature_at_negative_20cm: int | float | None = None, temperature_at_negative_20cm_units: str | None = None, relative_humidity: int | float | None = None, precipitation_rate: str | None = None, precipitation_type: str | None = None, sky_cover: str | None = None, height_of_snow: int | float | None = None, height_of_snow_units: str | None = None, height_of_new_snow_12_hours: int | float | None = None, height_of_new_snow_24_hours: int | float | None = None, height_of_new_snow_units: str | None = None, height_of_new_snow_water_equivalent_12_hours: int | float | None = None, height_of_new_snow_water_equivalent_24_hours: int | float | None = None, height_of_new_snow_water_equivalent_units: str | None = None, windspeed_ridgeline: int | float | str | None = None, wind_direction_ridgeline: str | None = None, windspeed: int | float | None = None, wind_direction: str | None = None, windspeed_units: str | None = None, maximum_gust_speed: int | float | str | None = None, maximum_gust_direction: str | None = None, maximum_gust_duration_seconds: int | float | str | None = None, blowing_snow: str | None = None, windloading: str | None = None, weather_detail: WeatherDetail | None = None)

Bases: BaseModel

An observation about the weather in a field report.

backcountry_zone: BackcountryZone | None
backcountry_zone_id: str | None
blowing_snow: str | None
classic_id: int | None
classic_observation_report_id: int | None
classic_observation_report_url: str | None
comments: str | None
created_at: datetime | None
height_of_new_snow_12_hours: int | float | None
height_of_new_snow_24_hours: int | float | None
height_of_new_snow_units: str | None
height_of_new_snow_water_equivalent_12_hours: int | float | None
height_of_new_snow_water_equivalent_24_hours: int | float | None
height_of_new_snow_water_equivalent_units: str | None
height_of_snow: int | float | None
height_of_snow_units: str | None
highway_zone: HighwayZone | None
highway_zone_id: str | None
id: str
latitude: float | None
location: str | None
longitude: float | None
maximum_gust_direction: str | None
maximum_gust_duration_seconds: int | float | str | None
maximum_gust_speed: int | float | str | None
model_config = {}
model_fields: ClassVar[dict[str, FieldInfo]] = {'backcountry_zone': FieldInfo(annotation=Union[BackcountryZone, NoneType], required=False), 'backcountry_zone_id': FieldInfo(annotation=Union[str, NoneType], required=False), 'blowing_snow': FieldInfo(annotation=Union[str, NoneType], required=False), 'classic_id': FieldInfo(annotation=Union[int, NoneType], required=False), 'classic_observation_report_id': FieldInfo(annotation=Union[int, NoneType], required=False), 'classic_observation_report_url': FieldInfo(annotation=Union[str, NoneType], required=False), 'comments': FieldInfo(annotation=Union[str, NoneType], required=False), 'created_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'height_of_new_snow_12_hours': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'height_of_new_snow_24_hours': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'height_of_new_snow_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'height_of_new_snow_water_equivalent_12_hours': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'height_of_new_snow_water_equivalent_24_hours': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'height_of_new_snow_water_equivalent_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'height_of_snow': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'height_of_snow_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'highway_zone': FieldInfo(annotation=Union[HighwayZone, NoneType], required=False), 'highway_zone_id': FieldInfo(annotation=Union[str, NoneType], required=False), 'id': FieldInfo(annotation=str, required=True), 'latitude': FieldInfo(annotation=Union[float, NoneType], required=False), 'location': FieldInfo(annotation=Union[str, NoneType], required=False), 'longitude': FieldInfo(annotation=Union[float, NoneType], required=False), 'maximum_gust_direction': FieldInfo(annotation=Union[str, NoneType], required=False), 'maximum_gust_duration_seconds': FieldInfo(annotation=Union[int, float, str, NoneType], required=False), 'maximum_gust_speed': FieldInfo(annotation=Union[int, float, str, NoneType], required=False), 'observed_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'precipitation_rate': FieldInfo(annotation=Union[str, NoneType], required=False), 'precipitation_type': FieldInfo(annotation=Union[str, NoneType], required=False), 'relative_humidity': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'sky_cover': FieldInfo(annotation=Union[str, NoneType], required=False), 'temperature': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'temperature_at_negative_20cm': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'temperature_at_negative_20cm_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'temperature_maximum': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'temperature_minimum': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'temperature_units': FieldInfo(annotation=Union[str, NoneType], required=False), 'type': FieldInfo(annotation=ObsTypes, required=True), 'updated_at': FieldInfo(annotation=Union[datetime, NoneType], required=False), 'url': FieldInfo(annotation=Union[str, NoneType], required=False), 'weather_detail': FieldInfo(annotation=Union[WeatherDetail, NoneType], required=False), 'wind_direction': FieldInfo(annotation=Union[str, NoneType], required=False), 'wind_direction_ridgeline': FieldInfo(annotation=Union[str, NoneType], required=False), 'windloading': FieldInfo(annotation=Union[str, NoneType], required=False), 'windspeed': FieldInfo(annotation=Union[int, float, NoneType], required=False), 'windspeed_ridgeline': FieldInfo(annotation=Union[int, float, str, NoneType], required=False), 'windspeed_units': FieldInfo(annotation=Union[str, NoneType], required=False)}
observed_at: datetime | None
precipitation_rate: str | None
precipitation_type: str | None
relative_humidity: int | float | None
sky_cover: str | None
temperature: int | float | None
temperature_at_negative_20cm: int | float | None
temperature_at_negative_20cm_units: str | None
temperature_maximum: int | float | None
temperature_minimum: int | float | None
temperature_units: str | None
type: ObsTypes
updated_at: datetime | None
url: str | None
weather_detail: WeatherDetail | None
wind_direction: str | None
wind_direction_ridgeline: str | None
windloading: str | None
windspeed: int | float | None
windspeed_ridgeline: int | float | str | None
windspeed_units: str | None

caic_python.utils module

Helpful methods.

caic_python.utils.find_classic_id(report: FieldReport) int | None

Find a classic ID from a given FieldReport.

Not every field report from the v2 API has an associated classic ID. It is nested in one of several possible child objects, which are not always present themselves. This method looks in all known locations of a FieldReport object for a classic ID. It first checks all *_details attrs, then checks each *Observation in all *_observations attrs. The first classic ID found is returned.

Parameters

reportmodels.FieldReport

The FieldReport to search in.

Returns

int | None

Returns the classic ID, or None if the FieldReport doesn’t have one.

Module contents

The caic-python module.

Also defines __version__:

The current version of caic-python - set by make change-version.

Must map to pyproject.toml’s version. Using make change-version or scripts/change-version.py ensures this.

caic_python.LOGGER = <Logger caic_python (WARNING)>

The logger used by caic-python, by default the level is logging.WARNING.

Callers may change the logging level by importing LOGGER.