Skip to content

Commit 8dbd5bb

Browse files
authored
Add a new test and an example (#69)
* And observation_by_place example * Add test for observation_by_place
1 parent 6006719 commit 8dbd5bb

File tree

4 files changed

+157
-2
lines changed

4 files changed

+157
-2
lines changed

example.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,20 @@
55
# Get current weather in Kilpisjärvi using coordinates
66
kilpisjarvi_weather = fmi.weather_by_coordinates(69.0478, 20.7982)
77

8-
# Get observation data
8+
# Get observation data by station ID
99
oulu_observation = fmi.observation_by_station_id(101794)
1010

11+
# Get observation data by place name
12+
tampere_observation = fmi.observation_by_place("Tampere")
13+
1114
# Get forecast for Helsinki
1215
helsinki_forecast = fmi.forecast_by_place_name("Helsinki")
1316

1417
# Print current temperature
1518
print()
1619
print(f"Temperature @ {kilpisjarvi_weather.place}: {kilpisjarvi_weather.data.temperature}")
17-
1820
print(f"Temperature @ {oulu_observation.place}: {oulu_observation.data.temperature}")
21+
print(f"Temperature @ {tampere_observation.place}: {tampere_observation.data.temperature}")
1922

2023
# Print temperature forecasts
2124
print()

test/test_data/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ def mock_observation_by_station_id_response(*args, **kwargs):
2626
return __mock_response('valid_observation_by_station_id_response.xml', 200, args, kwargs)
2727

2828

29+
def mock_observation_by_place_response(*args, **kwargs):
30+
return __mock_response('valid_observation_by_place_response.xml', 200, args, kwargs)
31+
32+
2933
def mock_nan_response(*args, **kwargs):
3034
return __mock_response('corner_nan_response.xml', 200, args, kwargs)
3135

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<wfs:FeatureCollection
3+
timeStamp="2025-07-15T15:05:44Z"
4+
numberMatched="1"
5+
numberReturned="1"
6+
xmlns:wfs="http://www.opengis.net/wfs/2.0"
7+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
8+
9+
xmlns:xlink="http://www.w3.org/1999/xlink"
10+
xmlns:om="http://www.opengis.net/om/2.0"
11+
xmlns:ompr="http://inspire.ec.europa.eu/schemas/ompr/3.0"
12+
xmlns:omso="http://inspire.ec.europa.eu/schemas/omso/3.0"
13+
xmlns:gml="http://www.opengis.net/gml/3.2"
14+
xmlns:gmd="http://www.isotc211.org/2005/gmd"
15+
xmlns:gco="http://www.isotc211.org/2005/gco"
16+
xmlns:swe="http://www.opengis.net/swe/2.0"
17+
xmlns:gmlcov="http://www.opengis.net/gmlcov/1.0"
18+
xmlns:sam="http://www.opengis.net/sampling/2.0"
19+
xmlns:sams="http://www.opengis.net/samplingSpatial/2.0"
20+
xmlns:target="http://xml.fmi.fi/namespace/om/atmosphericfeatures/1.1"
21+
xsi:schemaLocation="http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd
22+
http://www.opengis.net/gmlcov/1.0 http://schemas.opengis.net/gmlcov/1.0/gmlcovAll.xsd
23+
http://www.opengis.net/sampling/2.0 http://schemas.opengis.net/sampling/2.0/samplingFeature.xsd
24+
http://www.opengis.net/samplingSpatial/2.0 http://schemas.opengis.net/samplingSpatial/2.0/spatialSamplingFeature.xsd
25+
http://www.opengis.net/swe/2.0 http://schemas.opengis.net/sweCommon/2.0/swe.xsd
26+
http://inspire.ec.europa.eu/schemas/ompr/3.0 https://inspire.ec.europa.eu/schemas/ompr/3.0/Processes.xsd
27+
http://inspire.ec.europa.eu/schemas/omso/3.0 https://inspire.ec.europa.eu/schemas/omso/3.0/SpecialisedObservations.xsd
28+
http://xml.fmi.fi/namespace/om/atmosphericfeatures/1.1 https://xml.fmi.fi/schema/om/atmosphericfeatures/1.1/atmosphericfeatures.xsd">
29+
30+
<wfs:member>
31+
<omso:GridSeriesObservation gml:id="WFS-hFTe2dmkGslUBsikx66I0Bpw3mGJTowroWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dbeuzpp4b9O7pj39svLDnywtLFlz6d1TTty2qf4U69w4zhMbHy51qRaFOO6dNGTVwzsu7JU07ctqn.FOvYPtITO15fPffyyVOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wY5m9ty9Mu.hh5YduXpl5c61qmXbwy8sPTryy1oRMvehv07ulaFDll58.vLLWhI67dOTT081tV9O7JE08suPpp37q1q.ndkp8MuXJNp1oV9O7JH68.lblfLh6aMvKn524t.xnW9U39MOyHs39ckPf2y8q3qHLLj08NPTD0079zHQ1tunnz07s9TL46VjTsM5tbuu2fmp9MPTTv3c5wmZw2YceXnWdUw7eGXlla3Hrh2aenmTuzb4mtz6YemnfuqeeGWtDfwy7smHphbnPpv5ZcnHrl5eb.nJW6Fm26XTrfi55eXbD00793N0675cPTRl5OnW3rs6aeG_Tu6Y9_bLyw58rQ6aduWn0y8J1Gh007ctrfuy1jVakMA--">
32+
33+
<om:phenomenonTime>
34+
<gml:TimePeriod gml:id="time1-1-1">
35+
<gml:beginPosition>2025-07-15T14:43:28Z</gml:beginPosition>
36+
<gml:endPosition>2025-07-15T15:03:28Z</gml:endPosition>
37+
</gml:TimePeriod>
38+
</om:phenomenonTime>
39+
<om:resultTime>
40+
<gml:TimeInstant gml:id="time2-1-1">
41+
<gml:timePosition>2025-07-15T15:03:28Z</gml:timePosition>
42+
</gml:TimeInstant>
43+
</om:resultTime>
44+
45+
<om:procedure xlink:href="http://xml.fmi.fi/inspire/process/opendata"/>
46+
<om:parameter>
47+
<om:NamedValue>
48+
<om:name xlink:href="https://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent"/>
49+
<om:value>
50+
atmosphere
51+
</om:value>
52+
</om:NamedValue>
53+
</om:parameter>
54+
55+
<om:observedProperty xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=Temperature,DewPoint,Pressure,Humidity,WindDirection,WindSpeedMS,WindGust,WeatherSymbol3,TotalCloudCover,Precipitation1h&amp;language=eng"/>
56+
<om:featureOfInterest>
57+
<sams:SF_SpatialSamplingFeature gml:id="sampling-feature-1-1-fmisid">
58+
59+
<sam:sampledFeature>
60+
<target:LocationCollection gml:id="sampled-target-1-1">
61+
<target:member>
62+
<target:Location gml:id="obsloc-fmisid-101311-pos">
63+
<gml:identifier codeSpace="http://xml.fmi.fi/namespace/stationcode/fmisid">101311</gml:identifier>
64+
<gml:name codeSpace="http://xml.fmi.fi/namespace/locationcode/name">Tampere Siilinkari</gml:name>
65+
<gml:name codeSpace="http://xml.fmi.fi/namespace/locationcode/geoid">-16000074</gml:name>
66+
<gml:name codeSpace="http://xml.fmi.fi/namespace/locationcode/wmo">2943</gml:name>
67+
<target:representativePoint xlink:href="#point-101311"/>
68+
69+
70+
<target:region codeSpace="http://xml.fmi.fi/namespace/location/region">Tampere</target:region>
71+
72+
</target:Location></target:member>
73+
</target:LocationCollection>
74+
</sam:sampledFeature>
75+
<sams:shape>
76+
<gml:MultiPoint gml:id="mp-1-1-fmisid">
77+
<gml:pointMember>
78+
<gml:Point gml:id="point-101311" srsName="http://www.opengis.net/def/crs/EPSG/0/4258" srsDimension="2">
79+
<gml:name>Tampere Siilinkari</gml:name>
80+
<gml:pos>61.51757 23.75388 </gml:pos>
81+
</gml:Point>
82+
</gml:pointMember>
83+
</gml:MultiPoint>
84+
</sams:shape>
85+
</sams:SF_SpatialSamplingFeature>
86+
</om:featureOfInterest>
87+
88+
<om:result>
89+
<gmlcov:MultiPointCoverage gml:id="mpcv1-1-1">
90+
<gml:domainSet>
91+
<gmlcov:SimpleMultiPoint gml:id="mp1-1-1" srsName="http://xml.fmi.fi/gml/crs/compoundCRS.php?crs=4258&amp;time=unixtime" srsDimension="3">
92+
<gmlcov:positions>
93+
61.51757 23.75388 1752591000
94+
61.51757 23.75388 1752591600
95+
</gmlcov:positions>
96+
</gmlcov:SimpleMultiPoint>
97+
</gml:domainSet>
98+
<gml:rangeSet>
99+
<gml:DataBlock>
100+
<gml:rangeParameters/>
101+
<gml:doubleOrNilReasonTupleList>
102+
26.3 19.8 1010.3 67.0 348.0 3.0 3.4 NaN NaN NaN
103+
26.3 19.0 1010.2 64.0 344.0 3.3 3.7 NaN NaN NaN
104+
</gml:doubleOrNilReasonTupleList>
105+
</gml:DataBlock>
106+
</gml:rangeSet>
107+
<gml:coverageFunction>
108+
<gml:CoverageMappingRule>
109+
<gml:ruleDefinition>Linear</gml:ruleDefinition>
110+
</gml:CoverageMappingRule>
111+
</gml:coverageFunction>
112+
<gmlcov:rangeType>
113+
<swe:DataRecord>
114+
<swe:field name="Temperature" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=Temperature&amp;language=eng"/>
115+
<swe:field name="DewPoint" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=DewPoint&amp;language=eng"/>
116+
<swe:field name="Pressure" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=Pressure&amp;language=eng"/>
117+
<swe:field name="Humidity" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=Humidity&amp;language=eng"/>
118+
<swe:field name="WindDirection" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=WindDirection&amp;language=eng"/>
119+
<swe:field name="WindSpeedMS" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=WindSpeedMS&amp;language=eng"/>
120+
<swe:field name="WindGust" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=WindGust&amp;language=eng"/>
121+
<swe:field name="WeatherSymbol3" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=WeatherSymbol3&amp;language=eng"/>
122+
<swe:field name="TotalCloudCover" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=TotalCloudCover&amp;language=eng"/>
123+
<swe:field name="Precipitation1h" xlink:href="https://opendata.fmi.fi/meta?observableProperty=observation&amp;param=Precipitation1h&amp;language=eng"/>
124+
</swe:DataRecord>
125+
</gmlcov:rangeType>
126+
</gmlcov:MultiPointCoverage>
127+
</om:result>
128+
129+
</omso:GridSeriesObservation>
130+
</wfs:member>
131+
</wfs:FeatureCollection>

test/test_init.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ def test_async_get_observation_by_station_id(self, mock_get):
6666
weather = loop.run_until_complete(fmi_weather_client.async_observation_by_station_id(101794))
6767
self.assert_observation_id(weather)
6868

69+
@mock.patch('requests.get', side_effect=test_data.mock_observation_by_place_response)
70+
def test_get_observation_by_place(self, mock_get):
71+
weather = fmi_weather_client.observation_by_place("Tampere")
72+
self.assert_observation_place(weather)
73+
74+
@mock.patch('requests.get', side_effect=test_data.mock_observation_by_place_response)
75+
def test_async_get_observation_by_place(self, mock_get):
76+
loop = asyncio.get_event_loop()
77+
weather = loop.run_until_complete(fmi_weather_client.async_observation_by_place("Tampere"))
78+
self.assert_observation_place(weather)
79+
6980
# CORNER CASES
7081
@mock.patch('requests.get', side_effect=test_data.mock_nan_response)
7182
def test_nil_weather_response(self, mock_get):
@@ -174,6 +185,12 @@ def assert_observation_id(self, weather):
174185
self.assertEqual(weather.data.temperature.value, -7.2)
175186
self.assertEqual(weather.data.wind_speed.value, 2.6)
176187

188+
def assert_observation_place(self, weather):
189+
self.assertEqual(weather.place, 'Tampere Siilinkari')
190+
self.assertEqual(weather.data.time.timestamp(), 1752591600)
191+
self.assertEqual(weather.data.temperature.value, 26.3)
192+
self.assertEqual(weather.data.wind_speed.value, 3.3)
193+
177194

178195
if __name__ == '__main__':
179196
unittest.main()

0 commit comments

Comments
 (0)