Merge branch 'release-v0.7.11'
@ -19,7 +19,7 @@ export DATABASE_TEST_URL=postgresql://fittrackee:fittrackee@fittrackee-db:5432/f
|
||||
export REDIS_URL=redis://redis:6379
|
||||
|
||||
# API rate limits
|
||||
# export API_RATE_LIMITS=300 per 5 minutes
|
||||
# export API_RATE_LIMITS="300 per 5 minutes"
|
||||
|
||||
# Emails
|
||||
export UI_URL=http://0.0.0.0:5000
|
||||
@ -31,6 +31,11 @@ export WORKERS_PROCESSES=2
|
||||
|
||||
# Workouts
|
||||
# export TILE_SERVER_URL=
|
||||
# export STATICMAP_SUBDOMAINS=
|
||||
# export MAP_ATTRIBUTION=
|
||||
# export DEFAULT_STATICMAP=False
|
||||
|
||||
# Weather
|
||||
# available weather API providers: darksky, visualcrossing
|
||||
# export WEATHER_API_PROVIDER=
|
||||
# export WEATHER_API_KEY=
|
@ -20,7 +20,7 @@ export UPLOAD_FOLDER=
|
||||
# export REDIS_URL=
|
||||
|
||||
# API rate limits
|
||||
# export API_RATE_LIMITS=300 per 5 minutes
|
||||
# export API_RATE_LIMITS="300 per 5 minutes"
|
||||
|
||||
# Emails
|
||||
export UI_URL=
|
||||
@ -33,4 +33,8 @@ export SENDER_EMAIL=
|
||||
# export STATICMAP_SUBDOMAINS=
|
||||
# export MAP_ATTRIBUTION=
|
||||
# export DEFAULT_STATICMAP=False
|
||||
|
||||
# Weather
|
||||
# available weather API providers: darksky, visualcrossing
|
||||
# export WEATHER_API_PROVIDER=
|
||||
# export WEATHER_API_KEY=
|
||||
|
21
CHANGELOG.md
@ -1,7 +1,28 @@
|
||||
# Change log
|
||||
|
||||
## Version 0.7.11 (2022/12/31)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
* [PR#265](https://github.com/SamR1/FitTrackee/pull/265) - Implementing alternative weather API (VisualCrossing.com)
|
||||
**Note**: A new environment variable must be to set to configure the weather data provider: `WEATHER_API_PROVIDER` (see [documentation](https://samr1.github.io/FitTrackee/installation.html#weather-data))
|
||||
|
||||
### Translations
|
||||
|
||||
* [PR#287](https://github.com/SamR1/FitTrackee/pull/287) - Translations update from Hosted Weblate (Dutch)
|
||||
* [PR#289](https://github.com/SamR1/FitTrackee/pull/289) - Translations update from Hosted Weblate (German)
|
||||
|
||||
|
||||
Thanks to the contributors:
|
||||
- @bjornclauw
|
||||
- @jat255
|
||||
- @qwerty287
|
||||
|
||||
|
||||
## Version 0.7.10 (2022/12/21)
|
||||
|
||||
FitTrackee is now available in Italian (thanks to @dperruso).
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
* [#92](https://github.com/SamR1/FitTrackee/issues/92) - Add ascent and descent parameters in workout import without GPX file
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 5abf538cacc290d4cea92d1f42946aba
|
||||
config: 042de095012a0d21fe180df7971496bf
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
Before Width: | Height: | Size: 567 KiB After Width: | Height: | Size: 567 KiB |
Before Width: | Height: | Size: 378 KiB After Width: | Height: | Size: 378 KiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 83 KiB |
@ -1,7 +1,28 @@
|
||||
# Change log
|
||||
|
||||
## Version 0.7.11 (2022/12/31)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
* [PR#265](https://github.com/SamR1/FitTrackee/pull/265) - Implementing alternative weather API (VisualCrossing.com)
|
||||
**Note**: A new environment variable must be to set to configure the weather data provider: `WEATHER_API_PROVIDER` (see [documentation](https://samr1.github.io/FitTrackee/installation.html#weather-data))
|
||||
|
||||
### Translations
|
||||
|
||||
* [PR#287](https://github.com/SamR1/FitTrackee/pull/287) - Translations update from Hosted Weblate (Dutch)
|
||||
* [PR#289](https://github.com/SamR1/FitTrackee/pull/289) - Translations update from Hosted Weblate (German)
|
||||
|
||||
|
||||
Thanks to the contributors:
|
||||
- @bjornclauw
|
||||
- @jat255
|
||||
- @qwerty287
|
||||
|
||||
|
||||
## Version 0.7.10 (2022/12/21)
|
||||
|
||||
FitTrackee is now available in Italian (thanks to @dperruso).
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
* [#92](https://github.com/SamR1/FitTrackee/issues/92) - Add ascent and descent parameters in workout import without GPX file
|
||||
|
@ -43,7 +43,7 @@ Workouts
|
||||
| Ascent and descent can also be provided (*new in 0.7.10*).
|
||||
- | A workout with a gpx file can be displayed with map and charts (speed and elevation).
|
||||
| Controls allow full screen view and position reset (*new in 0.5.5*).
|
||||
- | If DarkSky API key is provided, weather is displayed in workout detail.
|
||||
- | If **DarkSky API** or **Visual Crossing** (*new in 0.7.11*) API key is provided, weather is displayed in workout detail. Data source is displayed in About page.
|
||||
| Wind is displayed, with arrow indicating direction (a tooltip can be displayed with the direction that the wind is coming **from**) (*new in 0.5.5*).
|
||||
- Segments can be displayed.
|
||||
- Workout gpx file can be downloaded (*new in 0.5.1*)
|
||||
|
@ -28,7 +28,7 @@ Prerequisites
|
||||
- optional
|
||||
- Redis for task queue (if email sending is enabled) and API rate limits
|
||||
- SMTP provider (if email sending is enabled)
|
||||
- API key from `Dark Sky <https://darksky.net/dev>`__ (deprecated, DarkSky will stop on March 31st, 2023)
|
||||
- API key from a `weather data provider <installation.html#weather-data>`__
|
||||
- `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
|
||||
- `Yarn <https://yarnpkg.com>`__ (for development only)
|
||||
- Docker and Docker Compose (for development or evaluation purposes)
|
||||
@ -172,7 +172,7 @@ deployment method.
|
||||
Number of processes used by **Dramatiq**.
|
||||
|
||||
|
||||
.. envvar:: API_RATE_LIMITS 🆕
|
||||
.. envvar:: API_RATE_LIMITS
|
||||
|
||||
.. versionadded:: 0.7.0
|
||||
|
||||
@ -229,7 +229,14 @@ deployment method.
|
||||
|
||||
.. versionchanged:: 0.4.0 ⚠️ replaces ``WEATHER_API``
|
||||
|
||||
**Dark Sky** API key for weather data (not mandatory).
|
||||
Weather API key (not mandatory), see ``WEATHER_API_PROVIDER``.
|
||||
|
||||
|
||||
.. envvar:: WEATHER_API_PROVIDER 🆕
|
||||
|
||||
.. versionadded:: 0.7.11
|
||||
|
||||
Provider for weather data (not mandatory), see `Weather data <installation.html#weather-data>`__.
|
||||
|
||||
|
||||
.. envvar:: VUE_APP_API_URL
|
||||
@ -302,8 +309,8 @@ For instance, to set OSM France tile server, the expected values are:
|
||||
The subdomain will be chosen randomly.
|
||||
|
||||
|
||||
API rate limits 🆕
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
API rate limits
|
||||
^^^^^^^^^^^^^^^
|
||||
.. versionadded:: 0.7.0
|
||||
|
||||
| API rate limits are managed by `Flask-Limiter <https://flask-limiter.readthedocs.io/en/stable>`_, based on IP with fixed window strategy.
|
||||
@ -338,6 +345,21 @@ API rate limits 🆕
|
||||
limits Enumerate details about all routes with rate limits
|
||||
|
||||
|
||||
Weather data
|
||||
^^^^^^^^^^^^
|
||||
.. versionchanged:: 0.7.11
|
||||
|
||||
The following weather data providers are supported by **FitTrackee**:
|
||||
|
||||
- `Dark Sky <https://darksky.net>`__ (deprecated, will stop on March 31st, 2023)
|
||||
- `Visual Crossing <https://www.visualcrossing.com>`__ (**note**: historical data are provided on hourly period)
|
||||
|
||||
To configure a weather provider, set the following environment variables:
|
||||
|
||||
- ``WEATHER_API_PROVIDER``: ``darksky`` for **Dark Sky** or ``visualcrossing`` for **Visual Crossing**
|
||||
- ``WEATHER_API_KEY``: the key to the corresponding weather provider
|
||||
|
||||
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
|
||||
@ -480,13 +502,13 @@ Production environment
|
||||
.. warning::
|
||||
| Note that FitTrackee is under heavy development, some features may be unstable.
|
||||
|
||||
- Download the last release (for now, it is the release v0.7.10):
|
||||
- Download the last release (for now, it is the release v0.7.11):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
|
||||
$ tar -xzf v0.7.10.tar.gz
|
||||
$ mv FitTrackee-0.7.10 FitTrackee
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
|
||||
$ tar -xzf v0.7.11.tar.gz
|
||||
$ mv FitTrackee-0.7.11 FitTrackee
|
||||
$ cd FitTrackee
|
||||
|
||||
- Create **.env** from example and update it
|
||||
@ -606,13 +628,13 @@ Prod environment
|
||||
|
||||
- Change to the directory where FitTrackee directory is located
|
||||
|
||||
- Download the last release (for now, it is the release v0.7.10) and overwrite existing files:
|
||||
- Download the last release (for now, it is the release v0.7.11) and overwrite existing files:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
|
||||
$ tar -xzf v0.7.10.tar.gz
|
||||
$ cp -R FitTrackee-0.7.10/* FitTrackee/
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
|
||||
$ tar -xzf v0.7.11.tar.gz
|
||||
$ cp -R FitTrackee-0.7.11/* FitTrackee/
|
||||
$ cd FitTrackee
|
||||
|
||||
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
2
docs/_static/documentation_options.js
vendored
@ -1,6 +1,6 @@
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '0.7.10',
|
||||
VERSION: '0.7.11',
|
||||
LANGUAGE: 'en',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Authentication — FitTrackee 0.7.10
|
||||
<title>Authentication — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -1239,7 +1239,7 @@ for other reasons.</p></li>
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Configuration — FitTrackee 0.7.10
|
||||
<title>Configuration — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -154,8 +154,9 @@
|
||||
<span class="w"> </span><span class="nt">"max_single_file_size"</span><span class="p">:</span><span class="w"> </span><span class="mi">1048576</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"max_users"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"max_zip_file_size"</span><span class="p">:</span><span class="w"> </span><span class="mi">10485760</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"map_attribution"</span><span class="p">:</span><span class="w"> </span><span class="nt">"&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.7.10"</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"map_attribution"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.7.11"</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"weather_provider"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="p">},</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"></span>
|
||||
<span class="p">}</span><span class="w"></span>
|
||||
@ -195,8 +196,9 @@
|
||||
<span class="w"> </span><span class="nt">"max_single_file_size"</span><span class="p">:</span><span class="w"> </span><span class="mi">1048576</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"max_users"</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"max_zip_file_size"</span><span class="p">:</span><span class="w"> </span><span class="mi">10485760</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"map_attribution"</span><span class="p">:</span><span class="w"> </span><span class="nt">"&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.7.10"</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"map_attribution"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.7.11"</span><span class="p">,</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"weather_provider"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="p">},</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="nt">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"></span>
|
||||
<span class="p">}</span><span class="w"></span>
|
||||
@ -279,7 +281,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>API documentation — FitTrackee 0.7.10
|
||||
<title>API documentation — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -160,7 +160,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>OAuth2 — FitTrackee 0.7.10
|
||||
<title>OAuth2 — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -694,7 +694,7 @@ are supported by FitTrackee)</p></li>
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Records — FitTrackee 0.7.10
|
||||
<title>Records — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -262,7 +262,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Sports — FitTrackee 0.7.10
|
||||
<title>Sports — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -492,7 +492,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Statistics — FitTrackee 0.7.10
|
||||
<title>Statistics — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -419,7 +419,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Users — FitTrackee 0.7.10
|
||||
<title>Users — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -663,7 +663,7 @@ one admin.</p>
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Workouts — FitTrackee 0.7.10
|
||||
<title>Workouts — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -1187,7 +1187,7 @@ must be provided with ascent)</p></li>
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Third-party applications — FitTrackee 0.7.10
|
||||
<title>Third-party applications — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -259,7 +259,7 @@ It is recommended to use PKCE to provide a better security.</p>
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Command line interface — FitTrackee 0.7.10
|
||||
<title>Command line interface — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -288,7 +288,7 @@ Commands:
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Features — FitTrackee 0.7.10
|
||||
<title>Features — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -206,7 +206,7 @@
|
||||
</div>
|
||||
</li>
|
||||
<li><div class="line-block">
|
||||
<div class="line">If DarkSky API key is provided, weather is displayed in workout detail.</div>
|
||||
<div class="line">If <strong>DarkSky API</strong> or <strong>Visual Crossing</strong> (<em>new in 0.7.11</em>) API key is provided, weather is displayed in workout detail. Data source is displayed in About page.</div>
|
||||
<div class="line">Wind is displayed, with arrow indicating direction (a tooltip can be displayed with the direction that the wind is coming <strong>from</strong>) (<em>new in 0.5.5</em>).</div>
|
||||
</div>
|
||||
</li>
|
||||
@ -400,7 +400,7 @@ A user with an inactive account cannot log in. (<em>new in 0.6.0</em>)</p></li>
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Index — FitTrackee 0.7.10
|
||||
<title>Index — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
|
||||
@ -40,7 +40,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -126,7 +126,7 @@
|
||||
environment variable
|
||||
|
||||
<ul>
|
||||
<li><a href="installation.html#envvar-API_RATE_LIMITS">API_RATE_LIMITS 🆕</a>
|
||||
<li><a href="installation.html#envvar-API_RATE_LIMITS">API_RATE_LIMITS</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-APP_LOG">APP_LOG</a>
|
||||
</li>
|
||||
@ -167,6 +167,8 @@
|
||||
<li><a href="installation.html#envvar-VUE_APP_API_URL">VUE_APP_API_URL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-WEATHER_API_KEY">WEATHER_API_KEY</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-WEATHER_API_PROVIDER">WEATHER_API_PROVIDER 🆕</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-WORKERS_PROCESSES">WORKERS_PROCESSES</a>
|
||||
</li>
|
||||
@ -188,7 +190,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>HTTP Routing Table — FitTrackee 0.7.10
|
||||
<title>HTTP Routing Table — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
|
||||
@ -47,7 +47,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -410,7 +410,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>FitTrackee — FitTrackee 0.7.10
|
||||
<title>FitTrackee — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
|
||||
@ -42,7 +42,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -180,7 +180,7 @@ Map</a>.</div>
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Installation — FitTrackee 0.7.10
|
||||
<title>Installation — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -87,7 +87,8 @@
|
||||
<li><a class="reference internal" href="#environment-variables">Environment variables</a><ul>
|
||||
<li><a class="reference internal" href="#emails">Emails</a></li>
|
||||
<li><a class="reference internal" href="#map-tile-server">Map tile server</a></li>
|
||||
<li><a class="reference internal" href="#api-rate-limits">API rate limits 🆕</a></li>
|
||||
<li><a class="reference internal" href="#api-rate-limits">API rate limits</a></li>
|
||||
<li><a class="reference internal" href="#weather-data">Weather data</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#id2">Installation</a><ul>
|
||||
@ -209,7 +210,7 @@
|
||||
<dt>optional</dt><dd><ul>
|
||||
<li><p>Redis for task queue (if email sending is enabled) and API rate limits</p></li>
|
||||
<li><p>SMTP provider (if email sending is enabled)</p></li>
|
||||
<li><p>API key from <a class="reference external" href="https://darksky.net/dev">Dark Sky</a> (deprecated, DarkSky will stop on March 31st, 2023)</p></li>
|
||||
<li><p>API key from a <a class="reference external" href="installation.html#weather-data">weather data provider</a></p></li>
|
||||
<li><p><a class="reference external" href="https://poetry.eustace.io">Poetry</a> (for installation from sources only)</p></li>
|
||||
<li><p><a class="reference external" href="https://yarnpkg.com">Yarn</a> (for development only)</p></li>
|
||||
<li><p>Docker and Docker Compose (for development or evaluation purposes)</p></li>
|
||||
@ -428,7 +429,7 @@ see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/p
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt class="sig sig-object std" id="envvar-API_RATE_LIMITS">
|
||||
<span class="sig-name descname"><span class="pre">API_RATE_LIMITS</span> <span class="pre">🆕</span></span><a class="headerlink" href="#envvar-API_RATE_LIMITS" title="Permalink to this definition">¶</a></dt>
|
||||
<span class="sig-name descname"><span class="pre">API_RATE_LIMITS</span></span><a class="headerlink" href="#envvar-API_RATE_LIMITS" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.7.0.</span></p>
|
||||
</div>
|
||||
@ -518,7 +519,16 @@ see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/p
|
||||
<dd><div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 0.4.0: </span>⚠️ replaces <code class="docutils literal notranslate"><span class="pre">WEATHER_API</span></code></p>
|
||||
</div>
|
||||
<p><strong>Dark Sky</strong> API key for weather data (not mandatory).</p>
|
||||
<p>Weather API key (not mandatory), see <code class="docutils literal notranslate"><span class="pre">WEATHER_API_PROVIDER</span></code>.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt class="sig sig-object std" id="envvar-WEATHER_API_PROVIDER">
|
||||
<span class="sig-name descname"><span class="pre">WEATHER_API_PROVIDER</span> <span class="pre">🆕</span></span><a class="headerlink" href="#envvar-WEATHER_API_PROVIDER" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.7.11.</span></p>
|
||||
</div>
|
||||
<p>Provider for weather data (not mandatory), see <a class="reference external" href="installation.html#weather-data">Weather data</a>.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
@ -604,7 +614,7 @@ The tile server can be changed by updating <code class="docutils literal notrans
|
||||
<p>The subdomain will be chosen randomly.</p>
|
||||
</section>
|
||||
<section id="api-rate-limits">
|
||||
<h3>API rate limits 🆕<a class="headerlink" href="#api-rate-limits" title="Permalink to this heading">¶</a></h3>
|
||||
<h3>API rate limits<a class="headerlink" href="#api-rate-limits" title="Permalink to this heading">¶</a></h3>
|
||||
<div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.7.0.</span></p>
|
||||
</div>
|
||||
@ -642,6 +652,22 @@ Commands:
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="weather-data">
|
||||
<h3>Weather data<a class="headerlink" href="#weather-data" title="Permalink to this heading">¶</a></h3>
|
||||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 0.7.11.</span></p>
|
||||
</div>
|
||||
<p>The following weather data providers are supported by <strong>FitTrackee</strong>:</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference external" href="https://darksky.net">Dark Sky</a> (deprecated, will stop on March 31st, 2023)</p></li>
|
||||
<li><p><a class="reference external" href="https://www.visualcrossing.com">Visual Crossing</a> (<strong>note</strong>: historical data are provided on hourly period)</p></li>
|
||||
</ul>
|
||||
<p>To configure a weather provider, set the following environment variables:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">WEATHER_API_PROVIDER</span></code>: <code class="docutils literal notranslate"><span class="pre">darksky</span></code> for <strong>Dark Sky</strong> or <code class="docutils literal notranslate"><span class="pre">visualcrossing</span></code> for <strong>Visual Crossing</strong></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">WEATHER_API_KEY</span></code>: the key to the corresponding weather provider</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
<section id="id2">
|
||||
<h2>Installation<a class="headerlink" href="#id2" title="Permalink to this heading">¶</a></h2>
|
||||
@ -795,11 +821,11 @@ $ make install-db
|
||||
</div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Download the last release (for now, it is the release v0.7.10):</p></li>
|
||||
<li><p>Download the last release (for now, it is the release v0.7.11):</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
|
||||
$ tar -xzf v0.7.10.tar.gz
|
||||
$ mv FitTrackee-0.7.10 FitTrackee
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
|
||||
$ tar -xzf v0.7.11.tar.gz
|
||||
$ mv FitTrackee-0.7.11 FitTrackee
|
||||
$ <span class="nb">cd</span> FitTrackee
|
||||
</pre></div>
|
||||
</div>
|
||||
@ -919,11 +945,11 @@ $ <span class="nb">source</span> .env
|
||||
<ul class="simple">
|
||||
<li><p>Stop the application</p></li>
|
||||
<li><p>Change to the directory where FitTrackee directory is located</p></li>
|
||||
<li><p>Download the last release (for now, it is the release v0.7.10) and overwrite existing files:</p></li>
|
||||
<li><p>Download the last release (for now, it is the release v0.7.11) and overwrite existing files:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
|
||||
$ tar -xzf v0.7.10.tar.gz
|
||||
$ cp -R FitTrackee-0.7.10/* FitTrackee/
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
|
||||
$ tar -xzf v0.7.11.tar.gz
|
||||
$ cp -R FitTrackee-0.7.11/* FitTrackee/
|
||||
$ <span class="nb">cd</span> FitTrackee
|
||||
</pre></div>
|
||||
</div>
|
||||
@ -1182,7 +1208,7 @@ $ make docker-test-python <span class="c1"># run unit tests on API</span>
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
BIN
docs/objects.inv
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Search — FitTrackee 0.7.10
|
||||
<title>Search — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
|
||||
@ -47,7 +47,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -154,7 +154,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Administrator — FitTrackee 0.7.10
|
||||
<title>Administrator — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -174,7 +174,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>Troubleshooting — FitTrackee 0.7.10
|
||||
<title>Troubleshooting — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -157,7 +157,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
|
||||
<title>User — FitTrackee 0.7.10
|
||||
<title>User — FitTrackee 0.7.11
|
||||
documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.10
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.7.11
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
@ -148,7 +148,7 @@
|
||||
</p>
|
||||
<p>
|
||||
© Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
|
||||
Last updated on Dec 21, 2022.<br/>
|
||||
Last updated on Dec 31, 2022.<br/>
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
Before Width: | Height: | Size: 567 KiB After Width: | Height: | Size: 567 KiB |
Before Width: | Height: | Size: 378 KiB After Width: | Height: | Size: 378 KiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 83 KiB |
@ -43,7 +43,7 @@ Workouts
|
||||
| Ascent and descent can also be provided (*new in 0.7.10*).
|
||||
- | A workout with a gpx file can be displayed with map and charts (speed and elevation).
|
||||
| Controls allow full screen view and position reset (*new in 0.5.5*).
|
||||
- | If DarkSky API key is provided, weather is displayed in workout detail.
|
||||
- | If **DarkSky API** or **Visual Crossing** (*new in 0.7.11*) API key is provided, weather is displayed in workout detail. Data source is displayed in About page.
|
||||
| Wind is displayed, with arrow indicating direction (a tooltip can be displayed with the direction that the wind is coming **from**) (*new in 0.5.5*).
|
||||
- Segments can be displayed.
|
||||
- Workout gpx file can be downloaded (*new in 0.5.1*)
|
||||
|
@ -28,7 +28,7 @@ Prerequisites
|
||||
- optional
|
||||
- Redis for task queue (if email sending is enabled) and API rate limits
|
||||
- SMTP provider (if email sending is enabled)
|
||||
- API key from `Dark Sky <https://darksky.net/dev>`__ (deprecated, DarkSky will stop on March 31st, 2023)
|
||||
- API key from a `weather data provider <installation.html#weather-data>`__
|
||||
- `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
|
||||
- `Yarn <https://yarnpkg.com>`__ (for development only)
|
||||
- Docker and Docker Compose (for development or evaluation purposes)
|
||||
@ -172,7 +172,7 @@ deployment method.
|
||||
Number of processes used by **Dramatiq**.
|
||||
|
||||
|
||||
.. envvar:: API_RATE_LIMITS 🆕
|
||||
.. envvar:: API_RATE_LIMITS
|
||||
|
||||
.. versionadded:: 0.7.0
|
||||
|
||||
@ -229,7 +229,14 @@ deployment method.
|
||||
|
||||
.. versionchanged:: 0.4.0 ⚠️ replaces ``WEATHER_API``
|
||||
|
||||
**Dark Sky** API key for weather data (not mandatory).
|
||||
Weather API key (not mandatory), see ``WEATHER_API_PROVIDER``.
|
||||
|
||||
|
||||
.. envvar:: WEATHER_API_PROVIDER 🆕
|
||||
|
||||
.. versionadded:: 0.7.11
|
||||
|
||||
Provider for weather data (not mandatory), see `Weather data <installation.html#weather-data>`__.
|
||||
|
||||
|
||||
.. envvar:: VUE_APP_API_URL
|
||||
@ -302,8 +309,8 @@ For instance, to set OSM France tile server, the expected values are:
|
||||
The subdomain will be chosen randomly.
|
||||
|
||||
|
||||
API rate limits 🆕
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
API rate limits
|
||||
^^^^^^^^^^^^^^^
|
||||
.. versionadded:: 0.7.0
|
||||
|
||||
| API rate limits are managed by `Flask-Limiter <https://flask-limiter.readthedocs.io/en/stable>`_, based on IP with fixed window strategy.
|
||||
@ -338,6 +345,21 @@ API rate limits 🆕
|
||||
limits Enumerate details about all routes with rate limits
|
||||
|
||||
|
||||
Weather data
|
||||
^^^^^^^^^^^^
|
||||
.. versionchanged:: 0.7.11
|
||||
|
||||
The following weather data providers are supported by **FitTrackee**:
|
||||
|
||||
- `Dark Sky <https://darksky.net>`__ (deprecated, will stop on March 31st, 2023)
|
||||
- `Visual Crossing <https://www.visualcrossing.com>`__ (**note**: historical data are provided on hourly period)
|
||||
|
||||
To configure a weather provider, set the following environment variables:
|
||||
|
||||
- ``WEATHER_API_PROVIDER``: ``darksky`` for **Dark Sky** or ``visualcrossing`` for **Visual Crossing**
|
||||
- ``WEATHER_API_KEY``: the key to the corresponding weather provider
|
||||
|
||||
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
|
||||
@ -480,13 +502,13 @@ Production environment
|
||||
.. warning::
|
||||
| Note that FitTrackee is under heavy development, some features may be unstable.
|
||||
|
||||
- Download the last release (for now, it is the release v0.7.10):
|
||||
- Download the last release (for now, it is the release v0.7.11):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
|
||||
$ tar -xzf v0.7.10.tar.gz
|
||||
$ mv FitTrackee-0.7.10 FitTrackee
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
|
||||
$ tar -xzf v0.7.11.tar.gz
|
||||
$ mv FitTrackee-0.7.11 FitTrackee
|
||||
$ cd FitTrackee
|
||||
|
||||
- Create **.env** from example and update it
|
||||
@ -606,13 +628,13 @@ Prod environment
|
||||
|
||||
- Change to the directory where FitTrackee directory is located
|
||||
|
||||
- Download the last release (for now, it is the release v0.7.10) and overwrite existing files:
|
||||
- Download the last release (for now, it is the release v0.7.11) and overwrite existing files:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
|
||||
$ tar -xzf v0.7.10.tar.gz
|
||||
$ cp -R FitTrackee-0.7.10/* FitTrackee/
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
|
||||
$ tar -xzf v0.7.11.tar.gz
|
||||
$ cp -R FitTrackee-0.7.11/* FitTrackee/
|
||||
$ cd FitTrackee
|
||||
|
||||
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
@ -25,7 +25,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
from fittrackee.emails.email import EmailService
|
||||
from fittrackee.request import CustomRequest
|
||||
|
||||
VERSION = __version__ = '0.7.10'
|
||||
VERSION = __version__ = '0.7.11'
|
||||
REDIS_URL = os.getenv('REDIS_URL', 'redis://')
|
||||
API_RATE_LIMITS = os.environ.get('API_RATE_LIMITS', '300 per 5 minutes').split(
|
||||
','
|
||||
|
@ -47,8 +47,9 @@ def get_application_config() -> Union[Dict, HttpResponse]:
|
||||
"max_single_file_size": 1048576,
|
||||
"max_users": 0,
|
||||
"max_zip_file_size": 10485760,
|
||||
"map_attribution": "© <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
|
||||
"version": "0.7.10"
|
||||
"map_attribution": "© <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors",
|
||||
"version": "0.7.11",
|
||||
"weather_provider": null
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
@ -99,8 +100,9 @@ def update_application_config(auth_user: User) -> Union[Dict, HttpResponse]:
|
||||
"max_single_file_size": 1048576,
|
||||
"max_users": 10,
|
||||
"max_zip_file_size": 10485760,
|
||||
"map_attribution": "© <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
|
||||
"version": "0.7.10"
|
||||
"map_attribution": "© <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors",
|
||||
"version": "0.7.11",
|
||||
"weather_provider": null
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import os
|
||||
from typing import Dict
|
||||
|
||||
from flask import current_app
|
||||
@ -43,6 +44,7 @@ class AppConfig(BaseModel):
|
||||
return current_app.config['TILE_SERVER']['ATTRIBUTION']
|
||||
|
||||
def serialize(self) -> Dict:
|
||||
weather_provider = os.getenv('WEATHER_API_PROVIDER', '').lower()
|
||||
return {
|
||||
'admin_contact': self.admin_contact,
|
||||
'gpx_limit_import': self.gpx_limit_import,
|
||||
@ -53,6 +55,11 @@ class AppConfig(BaseModel):
|
||||
'max_users': self.max_users,
|
||||
'map_attribution': self.map_attribution,
|
||||
'version': VERSION,
|
||||
'weather_provider': (
|
||||
weather_provider
|
||||
if weather_provider in ['darksky', 'visualcrossing']
|
||||
else None
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
2
fittrackee/dist/index.html
vendored
@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"/><link rel="stylesheet" href="/static/css/leaflet.css"/><title>FitTrackee</title><script defer="defer" src="/static/js/chunk-vendors.a82f8875.js"></script><script defer="defer" src="/static/js/app.c4c614bd.js"></script><link href="/static/css/app.2461bfc8.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"/><link rel="stylesheet" href="/static/css/leaflet.css"/><title>FitTrackee</title><script defer="defer" src="/static/js/chunk-vendors.5bcd2175.js"></script><script defer="defer" src="/static/js/app.02c11a8c.js"></script><link href="/static/css/app.92a77a8d.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
2
fittrackee/dist/service-worker.js
vendored
2
fittrackee/dist/service-worker.js.map
vendored
2
fittrackee/dist/static/js/app.02c11a8c.js
vendored
Normal file
1
fittrackee/dist/static/js/app.02c11a8c.js.map
vendored
Normal file
2
fittrackee/dist/static/js/app.c4c614bd.js
vendored
@ -1,2 +1,2 @@
|
||||
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[193],{7885:function(e,s,t){t.r(s),t.d(s,{default:function(){return A}});var a=t(6252),r=t(2262),l=t(3577),o=(t(7658),t(9150)),n=t(436);const c={class:"chart-menu"},i={class:"chart-arrow"},u={class:"time-frames custom-checkboxes-group"},d={class:"time-frames-checkboxes custom-checkboxes"},p=["id","name","checked","onInput"],m={class:"chart-arrow"};var v=(0,a.aZ)({__name:"StatsMenu",emits:["arrowClick","timeFrameUpdate"],setup(e,{emit:s}){const t=(0,r.iH)("month"),o=["week","month","year"];function n(e){t.value=e,s("timeFrameUpdate",e)}return(e,r)=>((0,a.wg)(),(0,a.iD)("div",c,[(0,a._)("div",i,[(0,a._)("i",{class:"fa fa-chevron-left","aria-hidden":"true",onClick:r[0]||(r[0]=e=>s("arrowClick",!0))})]),(0,a._)("div",u,[(0,a._)("div",d,[((0,a.wg)(),(0,a.iD)(a.HY,null,(0,a.Ko)(o,(s=>(0,a._)("div",{class:"time-frame custom-checkbox",key:s},[(0,a._)("label",null,[(0,a._)("input",{type:"radio",id:s,name:s,checked:t.value===s,onInput:e=>n(s)},null,40,p),(0,a._)("span",null,(0,l.zw)(e.$t(`statistics.TIME_FRAMES.${s}`)),1)])]))),64))])]),(0,a._)("div",m,[(0,a._)("i",{class:"fa fa-chevron-right","aria-hidden":"true",onClick:r[1]||(r[1]=e=>s("arrowClick",!1))})])]))}}),k=t(3744);const _=(0,k.Z)(v,[["__scopeId","data-v-22d55de2"]]);var S=_,w=t(631);const f={class:"sports-menu"},h=["id","name","checked","onInput"],U={class:"sport-label"};var b=(0,a.aZ)({__name:"StatsSportsMenu",props:{userSports:null,selectedSportIds:{default:()=>[]}},emits:["selectedSportIdsUpdate"],setup(e,{emit:s}){const t=e,{t:n}=(0,o.QT)(),c=(0,a.f3)("sportColors"),{selectedSportIds:i}=(0,r.BK)(t),u=(0,a.Fl)((()=>(0,w.xH)(t.userSports,n)));function d(e){s("selectedSportIdsUpdate",e)}return(e,s)=>{const t=(0,a.up)("SportImage");return(0,a.wg)(),(0,a.iD)("div",f,[((0,a.wg)(!0),(0,a.iD)(a.HY,null,(0,a.Ko)((0,r.SU)(u),(e=>((0,a.wg)(),(0,a.iD)("label",{type:"checkbox",key:e.id,style:(0,l.j5)({color:e.color?e.color:(0,r.SU)(c)[e.label]})},[(0,a._)("input",{type:"checkbox",id:e.id,name:e.label,checked:(0,r.SU)(i).includes(e.id),onInput:s=>d(e.id)},null,40,h),(0,a.Wm)(t,{"sport-label":e.label,color:e.color},null,8,["sport-label","color"]),(0,a._)("span",U,(0,l.zw)(e.translatedLabel),1)],4)))),128))])}}});const I=b;var g=I,T=t(9318);const y={key:0,id:"user-statistics"};var C=(0,a.aZ)({__name:"index",props:{sports:null,user:null},setup(e){const s=e,{t:t}=(0,o.QT)(),{sports:l,user:c}=(0,r.BK)(s),i=(0,r.iH)("month"),u=(0,r.iH)(v(i.value)),d=(0,a.Fl)((()=>(0,w.xH)(s.sports,t))),p=(0,r.iH)(_(s.sports));function m(e){i.value=e,u.value=v(i.value)}function v(e){return(0,T.aZ)(new Date,e,s.user.weekm)}function k(e){u.value=(0,T.FN)(u.value,e,s.user.weekm)}function _(e){return e.map((e=>e.id))}function f(e){p.value.includes(e)?p.value=p.value.filter((s=>s!==e)):p.value.push(e)}return(0,a.YP)((()=>s.sports),(e=>{p.value=_(e)})),(e,s)=>(0,r.SU)(d)?((0,a.wg)(),(0,a.iD)("div",y,[(0,a.Wm)(S,{onTimeFrameUpdate:m,onArrowClick:k}),(0,a.Wm)(n.Z,{sports:(0,r.SU)(l),user:(0,r.SU)(c),chartParams:u.value,"displayed-sport-ids":p.value,fullStats:!0},null,8,["sports","user","chartParams","displayed-sport-ids"]),(0,a.Wm)(g,{"selected-sport-ids":p.value,"user-sports":(0,r.SU)(l),onSelectedSportIdsUpdate:f},null,8,["selected-sport-ids","user-sports"])])):(0,a.kq)("",!0)}});const F=(0,k.Z)(C,[["__scopeId","data-v-30799d13"]]);var Z=F,x=t(5630),D=t(5801),H=t(9917);const E={id:"statistics",class:"view"},R={key:0,class:"container"};var W=(0,a.aZ)({__name:"StatisticsView",setup(e){const s=(0,H.o)(),t=(0,a.Fl)((()=>s.getters[D.YN.GETTERS.AUTH_USER_PROFILE])),o=(0,a.Fl)((()=>s.getters[D.O8.GETTERS.SPORTS].filter((e=>t.value.sports_list.includes(e.id)))));return(e,s)=>{const n=(0,a.up)("Card");return(0,a.wg)(),(0,a.iD)("div",E,[(0,r.SU)(t).username?((0,a.wg)(),(0,a.iD)("div",R,[(0,a.Wm)(n,null,{title:(0,a.w5)((()=>[(0,a.Uk)((0,l.zw)(e.$t("statistics.STATISTICS")),1)])),content:(0,a.w5)((()=>[(0,a.Wm)(Z,{class:(0,l.C_)({"stats-disabled":0===(0,r.SU)(t).nb_workouts}),user:(0,r.SU)(t),sports:(0,r.SU)(o)},null,8,["class","user","sports"])])),_:1}),0===(0,r.SU)(t).nb_workouts?((0,a.wg)(),(0,a.j4)(x.Z,{key:0})):(0,a.kq)("",!0)])):(0,a.kq)("",!0)])}}});const P=(0,k.Z)(W,[["__scopeId","data-v-2e341d4e"]]);var A=P}}]);
|
||||
//# sourceMappingURL=statistics.31ee4368.js.map
|
||||
//# sourceMappingURL=statistics.99fc9524.js.map
|
1
fittrackee/dist/static/js/workouts.143c4328.js.map
vendored
Normal file
@ -1,3 +1,4 @@
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from fittrackee import VERSION
|
||||
@ -6,7 +7,10 @@ from fittrackee.users.models import User
|
||||
|
||||
|
||||
class TestConfigModel:
|
||||
def test_application_config(self, app: Flask) -> None:
|
||||
def test_application_config(
|
||||
self, app: Flask, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
monkeypatch.setenv('WEATHER_API_PROVIDER', 'darksky')
|
||||
app_config = AppConfig.query.first()
|
||||
app_config.admin_contact = 'admin@example.com'
|
||||
|
||||
@ -40,6 +44,7 @@ class TestConfigModel:
|
||||
== app_config.map_attribution
|
||||
)
|
||||
assert serialized_app_config['version'] == VERSION
|
||||
assert serialized_app_config['weather_provider'] == 'darksky'
|
||||
|
||||
def test_it_returns_registration_disabled_when_users_count_exceeds_limit(
|
||||
self, app: Flask, user_1: User, user_2: User
|
||||
@ -58,3 +63,28 @@ class TestConfigModel:
|
||||
serialized_app_config = app_config.serialize()
|
||||
|
||||
assert serialized_app_config['is_email_sending_enabled'] is False
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'input_weather_api_provider, expected_weather_provider',
|
||||
[
|
||||
('darksky', 'darksky'),
|
||||
('Visualcrossing', 'visualcrossing'),
|
||||
('invalid_provider', None),
|
||||
('', None),
|
||||
],
|
||||
)
|
||||
def test_it_returns_weather_provider(
|
||||
self,
|
||||
app: Flask,
|
||||
input_weather_api_provider: str,
|
||||
expected_weather_provider: str,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.setenv('WEATHER_API_PROVIDER', input_weather_api_provider)
|
||||
app_config = AppConfig.query.first()
|
||||
serialized_app_config = app_config.serialize()
|
||||
|
||||
assert (
|
||||
serialized_app_config['weather_provider']
|
||||
== expected_weather_provider
|
||||
)
|
||||
|
11
fittrackee/tests/fixtures/fixtures_app.py
vendored
@ -1,6 +1,7 @@
|
||||
import os
|
||||
import shutil
|
||||
from typing import Generator, Optional, Union
|
||||
from typing import Generator, Iterator, Optional, Union
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from flask import current_app
|
||||
@ -8,6 +9,13 @@ from flask import current_app
|
||||
from fittrackee import create_app, db, limiter
|
||||
from fittrackee.application.models import AppConfig
|
||||
from fittrackee.application.utils import update_app_config_from_database
|
||||
from fittrackee.workouts.utils.gpx import weather_service
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def default_weather_service(monkeypatch: pytest.MonkeyPatch) -> Iterator[None]:
|
||||
with patch.object(weather_service, 'get_weather', return_value=None):
|
||||
yield
|
||||
|
||||
|
||||
def get_app_config(
|
||||
@ -82,7 +90,6 @@ def get_app(
|
||||
@pytest.fixture
|
||||
def app(monkeypatch: pytest.MonkeyPatch) -> Generator:
|
||||
monkeypatch.setenv('EMAIL_URL', 'smtp://none:none@0.0.0.0:1025')
|
||||
monkeypatch.setenv('WEATHER_API_KEY', '')
|
||||
if os.getenv('TILE_SERVER_URL'):
|
||||
monkeypatch.delenv('TILE_SERVER_URL')
|
||||
if os.getenv('STATICMAP_SUBDOMAINS'):
|
||||
|
344
fittrackee/tests/workouts/test_utils/test_weather_service.py
Normal file
@ -0,0 +1,344 @@
|
||||
from datetime import datetime
|
||||
from typing import Dict, Optional
|
||||
from unittest.mock import Mock, patch, sentinel
|
||||
|
||||
import pytest
|
||||
import pytz
|
||||
import requests
|
||||
from gpxpy.gpx import GPXTrackPoint
|
||||
|
||||
from fittrackee.tests.mixins import CallArgsMixin
|
||||
from fittrackee.tests.utils import random_string
|
||||
from fittrackee.workouts.utils.weather.dark_sky import DarkSky
|
||||
from fittrackee.workouts.utils.weather.visual_crossing import VisualCrossing
|
||||
from fittrackee.workouts.utils.weather.weather_service import WeatherService
|
||||
|
||||
VISUAL_CROSSING_RESPONSE = {
|
||||
"queryCost": 1,
|
||||
"latitude": 48.866667,
|
||||
"longitude": 2.333333,
|
||||
"resolvedAddress": "48.866667,2.333333",
|
||||
"address": "48.866667,2.333333",
|
||||
"timezone": "Europe/Paris",
|
||||
"tzoffset": 1.0,
|
||||
"days": [
|
||||
{
|
||||
"datetime": "2022-11-15",
|
||||
"datetimeEpoch": 1668466800,
|
||||
"temp": 10.4,
|
||||
"humidity": 93.3,
|
||||
"windspeed": 18.9,
|
||||
"winddir": 179.4,
|
||||
"conditions": "Rain, Partially cloudy",
|
||||
"description": "Partly cloudy throughout the day with rain.",
|
||||
"icon": "rain",
|
||||
}
|
||||
],
|
||||
"currentConditions": {
|
||||
"datetime": "13:00:00",
|
||||
"datetimeEpoch": 1668513600,
|
||||
"temp": 11.3,
|
||||
"humidity": 93.1,
|
||||
"windspeed": 14.0,
|
||||
"winddir": 161.9,
|
||||
"conditions": "Rain, Overcast",
|
||||
"icon": "rain",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class WeatherTestCase:
|
||||
api_key = random_string()
|
||||
|
||||
@staticmethod
|
||||
def get_gpx_point(time: Optional[datetime] = None) -> GPXTrackPoint:
|
||||
return GPXTrackPoint(latitude=48.866667, longitude=2.333333, time=time)
|
||||
|
||||
|
||||
class TestDarksky(WeatherTestCase):
|
||||
def test_it_calls_forecast_io_with_datetime_in_utc_when_naive_datetime_is_provided( # noqa
|
||||
self,
|
||||
) -> None:
|
||||
naive_point_time = datetime(
|
||||
year=2022, month=6, day=11, hour=10, minute=23, second=00
|
||||
)
|
||||
point = self.get_gpx_point(naive_point_time)
|
||||
darksky = DarkSky(api_key=self.api_key)
|
||||
with patch(
|
||||
'fittrackee.workouts.utils.weather.dark_sky.forecastio'
|
||||
) as forecast_io_mock:
|
||||
|
||||
darksky.get_weather(point)
|
||||
|
||||
forecast_io_mock.load_forecast.assert_called_with(
|
||||
self.api_key,
|
||||
point.latitude,
|
||||
point.longitude,
|
||||
time=datetime(
|
||||
year=2022,
|
||||
month=6,
|
||||
day=11,
|
||||
hour=10,
|
||||
minute=23,
|
||||
second=00,
|
||||
tzinfo=pytz.utc,
|
||||
),
|
||||
units='si',
|
||||
)
|
||||
|
||||
def test_it_calls_forecast_io_with_provided_datetime_when_with_timezone(
|
||||
self,
|
||||
) -> None:
|
||||
paris_point_time = datetime(
|
||||
year=2022,
|
||||
month=6,
|
||||
day=11,
|
||||
hour=10,
|
||||
minute=23,
|
||||
second=00,
|
||||
).astimezone(pytz.timezone('Europe/Paris'))
|
||||
point = self.get_gpx_point(paris_point_time)
|
||||
darksky = DarkSky(api_key=self.api_key)
|
||||
with patch(
|
||||
'fittrackee.workouts.utils.weather.dark_sky.forecastio'
|
||||
) as forecast_io_mock:
|
||||
|
||||
darksky.get_weather(point)
|
||||
|
||||
forecast_io_mock.load_forecast.assert_called_with(
|
||||
self.api_key,
|
||||
point.latitude,
|
||||
point.longitude,
|
||||
time=paris_point_time,
|
||||
units='si',
|
||||
)
|
||||
|
||||
def test_it_returns_forecast_currently_data(self) -> None:
|
||||
darksky = DarkSky(api_key=self.api_key)
|
||||
with patch(
|
||||
'fittrackee.workouts.utils.weather.dark_sky.forecastio'
|
||||
) as forecast_io_mock:
|
||||
forecast_io_mock.load_forecast().currently.return_value = sentinel
|
||||
|
||||
weather_data = darksky.get_weather(
|
||||
self.get_gpx_point(datetime.utcnow())
|
||||
)
|
||||
|
||||
assert weather_data == {
|
||||
'icon': sentinel.icon,
|
||||
'temperature': sentinel.temperature,
|
||||
'humidity': sentinel.humidity,
|
||||
'wind': sentinel.windSpeed,
|
||||
'windBearing': sentinel.windBearing,
|
||||
}
|
||||
|
||||
|
||||
class TestVisualCrossingGetTimestamp(WeatherTestCase):
|
||||
def test_it_returns_expected_timestamp_as_integer(self) -> None:
|
||||
time = datetime.utcnow()
|
||||
visual_crossing = VisualCrossing(api_key=self.api_key)
|
||||
|
||||
timestamp = visual_crossing._get_timestamp(time)
|
||||
|
||||
assert isinstance(timestamp, int)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'input_datetime,expected_datetime',
|
||||
[
|
||||
('2020-12-15T13:00:00', '2020-12-15T13:00:00'),
|
||||
('2020-12-15T13:29:59', '2020-12-15T13:00:00'),
|
||||
('2020-12-15T13:30:00', '2020-12-15T14:00:00'),
|
||||
('2020-12-15T13:59:59', '2020-12-15T14:00:00'),
|
||||
],
|
||||
)
|
||||
def test_it_returns_rounded_time(
|
||||
self, input_datetime: str, expected_datetime: str
|
||||
) -> None:
|
||||
time = datetime.strptime(input_datetime, '%Y-%m-%dT%H:%M:%S')
|
||||
visual_crossing = VisualCrossing(api_key=self.api_key)
|
||||
|
||||
timestamp = visual_crossing._get_timestamp(time)
|
||||
|
||||
assert (
|
||||
timestamp
|
||||
== datetime.strptime(
|
||||
expected_datetime, '%Y-%m-%dT%H:%M:%S'
|
||||
).timestamp()
|
||||
)
|
||||
|
||||
|
||||
class TestVisualCrossingGetWeather(WeatherTestCase, CallArgsMixin):
|
||||
@staticmethod
|
||||
def get_response() -> Mock:
|
||||
response_mock = Mock()
|
||||
response_mock.raise_for_status = Mock()
|
||||
response_mock.json = Mock()
|
||||
response_mock.json.return_value = VISUAL_CROSSING_RESPONSE
|
||||
return response_mock
|
||||
|
||||
def test_it_calls_api_with_time_and_point_location(self) -> None:
|
||||
time = datetime(
|
||||
year=2022,
|
||||
month=11,
|
||||
day=15,
|
||||
hour=12,
|
||||
minute=00,
|
||||
second=00,
|
||||
tzinfo=pytz.utc,
|
||||
)
|
||||
point = self.get_gpx_point(time)
|
||||
visual_crossing = VisualCrossing(api_key=self.api_key)
|
||||
with patch.object(requests, 'get') as get_mock:
|
||||
|
||||
visual_crossing.get_weather(point)
|
||||
|
||||
args = self.get_args(get_mock.call_args)
|
||||
assert args[0] == (
|
||||
'https://weather.visualcrossing.com/VisualCrossingWebServices/'
|
||||
f'rest/services/timeline/{point.latitude},{point.longitude}/'
|
||||
f'{int(point.time.timestamp())}' # type: ignore
|
||||
)
|
||||
|
||||
def test_it_calls_api_with_expected_params(self) -> None:
|
||||
visual_crossing = VisualCrossing(api_key=self.api_key)
|
||||
with patch.object(requests, 'get') as get_mock:
|
||||
|
||||
visual_crossing.get_weather(self.get_gpx_point(datetime.utcnow()))
|
||||
|
||||
kwargs = self.get_kwargs(get_mock.call_args)
|
||||
assert kwargs.get('params') == {
|
||||
'key': self.api_key,
|
||||
'iconSet': 'icons1',
|
||||
'unitGroup': 'metric',
|
||||
'contentType': 'json',
|
||||
'elements': (
|
||||
'datetime,datetimeEpoch,temp,humidity,windspeed,'
|
||||
'winddir,conditions,description,icon'
|
||||
),
|
||||
'include': 'current',
|
||||
}
|
||||
|
||||
def test_it_returns_data_from_current_conditions(self) -> None:
|
||||
point = self.get_gpx_point(
|
||||
datetime(
|
||||
year=2022,
|
||||
month=11,
|
||||
day=15,
|
||||
hour=13,
|
||||
minute=00,
|
||||
second=00,
|
||||
tzinfo=pytz.utc,
|
||||
).astimezone(pytz.timezone('Europe/Paris'))
|
||||
)
|
||||
visual_crossing = VisualCrossing(api_key=self.api_key)
|
||||
with patch.object(requests, 'get', return_value=self.get_response()):
|
||||
|
||||
weather_data = visual_crossing.get_weather(point)
|
||||
|
||||
current_conditions: Dict = VISUAL_CROSSING_RESPONSE[ # type: ignore
|
||||
'currentConditions'
|
||||
]
|
||||
assert weather_data == {
|
||||
'icon': current_conditions['icon'],
|
||||
'temperature': current_conditions['temp'],
|
||||
'humidity': current_conditions['humidity'] / 100,
|
||||
'wind': (current_conditions['windspeed'] * 1000) / 3600,
|
||||
'windBearing': current_conditions['winddir'],
|
||||
}
|
||||
|
||||
|
||||
class TestWeatherService(WeatherTestCase):
|
||||
@pytest.mark.parametrize(
|
||||
'input_api_key,input_provider',
|
||||
[
|
||||
('', 'darksky'),
|
||||
('valid_api_key', ''),
|
||||
('valid_api_key', 'invalid_provider'),
|
||||
],
|
||||
)
|
||||
def test_weather_api_is_none_when_configuration_is_invalid(
|
||||
self,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
input_api_key: str,
|
||||
input_provider: str,
|
||||
) -> None:
|
||||
monkeypatch.setenv('WEATHER_API_KEY', input_api_key)
|
||||
monkeypatch.setenv('WEATHER_API_PROVIDER', input_provider)
|
||||
|
||||
weather_service = WeatherService()
|
||||
|
||||
assert weather_service.weather_api is None
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'input_provider',
|
||||
['darksky', 'DARKSKY'],
|
||||
)
|
||||
def test_weather_api_is_darksky_when_configured(
|
||||
self,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
input_provider: str,
|
||||
) -> None:
|
||||
monkeypatch.setenv('WEATHER_API_KEY', 'valid_api_key')
|
||||
monkeypatch.setenv('WEATHER_API_PROVIDER', input_provider)
|
||||
|
||||
weather_service = WeatherService()
|
||||
|
||||
assert isinstance(weather_service.weather_api, DarkSky)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'input_provider',
|
||||
['visualcrossing', 'VisualCrossing'],
|
||||
)
|
||||
def test_weather_api_is_visualcrossing_when_configured(
|
||||
self,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
input_provider: str,
|
||||
) -> None:
|
||||
monkeypatch.setenv('WEATHER_API_KEY', 'valid_api_key')
|
||||
monkeypatch.setenv('WEATHER_API_PROVIDER', input_provider)
|
||||
|
||||
weather_service = WeatherService()
|
||||
|
||||
assert isinstance(weather_service.weather_api, VisualCrossing)
|
||||
|
||||
def test_it_returns_none_when_no_weather_api(self) -> None:
|
||||
weather_service = WeatherService()
|
||||
weather_service.weather_api = None
|
||||
point = self.get_gpx_point(datetime.utcnow())
|
||||
|
||||
weather_data = weather_service.get_weather(point)
|
||||
|
||||
assert weather_data is None
|
||||
|
||||
def test_it_returns_none_when_point_time_is_none(self) -> None:
|
||||
weather_service = WeatherService()
|
||||
weather_service.weather_api = DarkSky('api_key')
|
||||
point = self.get_gpx_point(None)
|
||||
|
||||
weather_data = weather_service.get_weather(point)
|
||||
|
||||
assert weather_data is None
|
||||
|
||||
def test_it_returns_none_when_weather_api_raises_exception(self) -> None:
|
||||
weather_api = Mock()
|
||||
weather_api.get_weather = Mock()
|
||||
weather_api.get_weather.side_effect = Exception()
|
||||
weather_service = WeatherService()
|
||||
weather_service.weather_api = weather_api
|
||||
point = self.get_gpx_point(datetime.utcnow())
|
||||
|
||||
weather_data = weather_service.get_weather(point)
|
||||
|
||||
assert weather_data is None
|
||||
|
||||
def test_it_returns_weather_data(self) -> None:
|
||||
weather_api = Mock()
|
||||
weather_api.get_weather = Mock()
|
||||
weather_api.get_weather.return_value = sentinel
|
||||
weather_service = WeatherService()
|
||||
weather_service.weather_api = weather_api
|
||||
point = self.get_gpx_point(datetime.utcnow())
|
||||
|
||||
weather_data = weather_service.get_weather(point)
|
||||
|
||||
assert weather_data == sentinel
|
@ -4,7 +4,9 @@ from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
import gpxpy.gpx
|
||||
|
||||
from ..exceptions import WorkoutGPXException
|
||||
from .weather import get_weather
|
||||
from .weather import WeatherService
|
||||
|
||||
weather_service = WeatherService()
|
||||
|
||||
|
||||
def open_gpx_file(gpx_file: str) -> Optional[gpxpy.gpx.GPX]:
|
||||
@ -99,7 +101,7 @@ def get_gpx_info(
|
||||
if start is None:
|
||||
start = point.time
|
||||
if point.time and update_weather_data:
|
||||
weather_data.append(get_weather(point))
|
||||
weather_data.append(weather_service.get_weather(point))
|
||||
|
||||
# if a previous segment exists, calculate stopped time between
|
||||
# the two segments
|
||||
@ -114,7 +116,7 @@ def get_gpx_info(
|
||||
|
||||
# last gpx point => get weather
|
||||
if segment_idx == (segments_nb - 1) and update_weather_data:
|
||||
weather_data.append(get_weather(point))
|
||||
weather_data.append(weather_service.get_weather(point))
|
||||
|
||||
if update_map_data:
|
||||
map_data.append([point.longitude, point.latitude])
|
||||
|
@ -1,40 +0,0 @@
|
||||
import os
|
||||
from typing import Dict, Optional
|
||||
|
||||
import forecastio
|
||||
import pytz
|
||||
from gpxpy.gpx import GPXTrackPoint
|
||||
|
||||
from fittrackee import appLog
|
||||
|
||||
API_KEY = os.getenv('WEATHER_API_KEY')
|
||||
|
||||
|
||||
def get_weather(point: GPXTrackPoint) -> Optional[Dict]:
|
||||
if not API_KEY or not point.time:
|
||||
return None
|
||||
try:
|
||||
point_time = (
|
||||
pytz.utc.localize(point.time)
|
||||
if point.time.tzinfo is None
|
||||
else point.time.astimezone(pytz.utc)
|
||||
)
|
||||
forecast = forecastio.load_forecast(
|
||||
API_KEY,
|
||||
point.latitude,
|
||||
point.longitude,
|
||||
time=point_time,
|
||||
units='si',
|
||||
)
|
||||
weather = forecast.currently()
|
||||
return {
|
||||
'summary': weather.summary,
|
||||
'icon': weather.icon,
|
||||
'temperature': weather.temperature,
|
||||
'humidity': weather.humidity,
|
||||
'wind': weather.windSpeed,
|
||||
'windBearing': weather.windBearing,
|
||||
}
|
||||
except Exception as e:
|
||||
appLog.error(e)
|
||||
return None
|
5
fittrackee/workouts/utils/weather/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
from .weather_service import WeatherService
|
||||
|
||||
__all__ = [
|
||||
'WeatherService',
|
||||
]
|
50
fittrackee/workouts/utils/weather/base_weather.py
Normal file
@ -0,0 +1,50 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from datetime import datetime
|
||||
from typing import Dict, Optional
|
||||
|
||||
from gpxpy.gpx import GPXTrackPoint
|
||||
|
||||
|
||||
class BaseWeather(ABC):
|
||||
def __init__(self, api_key: str) -> None:
|
||||
self.api_key: str = api_key
|
||||
|
||||
@abstractmethod
|
||||
def _get_data(
|
||||
self, latitude: float, longitude: float, time: datetime
|
||||
) -> Optional[Dict]:
|
||||
# Expected dict:
|
||||
# {
|
||||
# "humidity": 0.69,
|
||||
# "icon": "partly-cloudy-day",
|
||||
# "temperature": 12.26,
|
||||
# "wind": 3.49,
|
||||
# "windBearing": 315
|
||||
# }
|
||||
#
|
||||
# FitTrackee expects the following units:
|
||||
# temperature: Celsius,
|
||||
# humidity: in fraction (rather than percent)
|
||||
# windSpeed: m/s
|
||||
# windBearing: direction wind is from in degrees (0 is north)
|
||||
#
|
||||
# Expected icon values (for UI):
|
||||
# - "clear-day",
|
||||
# - "clear-night",
|
||||
# - "cloudy",
|
||||
# - "fog",
|
||||
# - "partly-cloudy-day",
|
||||
# - "partly-cloudy-night",
|
||||
# - "rain",
|
||||
# - "sleet",
|
||||
# - "snow",
|
||||
# - "wind"
|
||||
pass
|
||||
|
||||
def get_weather(self, point: GPXTrackPoint) -> Optional[Dict]:
|
||||
if not point.time:
|
||||
# if there's no time associated with the point,
|
||||
# we cannot get weather
|
||||
return None
|
||||
|
||||
return self._get_data(point.latitude, point.longitude, point.time)
|
37
fittrackee/workouts/utils/weather/dark_sky.py
Normal file
@ -0,0 +1,37 @@
|
||||
from datetime import datetime
|
||||
from typing import Dict, Optional
|
||||
|
||||
import forecastio
|
||||
import pytz
|
||||
|
||||
from .base_weather import BaseWeather
|
||||
|
||||
|
||||
class DarkSky(BaseWeather):
|
||||
# Deprecated (API will end on March 31st, 2023)
|
||||
|
||||
def _get_data(
|
||||
self, latitude: float, longitude: float, time: datetime
|
||||
) -> Optional[Dict]:
|
||||
# get point time in UTC
|
||||
point_time = (
|
||||
pytz.utc.localize(time)
|
||||
if time.tzinfo is None # naive datetime
|
||||
else time
|
||||
)
|
||||
|
||||
forecast = forecastio.load_forecast(
|
||||
self.api_key,
|
||||
latitude,
|
||||
longitude,
|
||||
time=point_time,
|
||||
units='si',
|
||||
)
|
||||
weather = forecast.currently()
|
||||
return {
|
||||
'humidity': weather.humidity,
|
||||
'icon': weather.icon,
|
||||
'temperature': weather.temperature,
|
||||
'wind': weather.windSpeed,
|
||||
'windBearing': weather.windBearing,
|
||||
}
|
84
fittrackee/workouts/utils/weather/visual_crossing.py
Normal file
@ -0,0 +1,84 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, Optional
|
||||
|
||||
import requests
|
||||
|
||||
from fittrackee import appLog
|
||||
|
||||
from .base_weather import BaseWeather
|
||||
|
||||
|
||||
class VisualCrossing(BaseWeather):
|
||||
def __init__(self, api_key: str):
|
||||
super().__init__(api_key)
|
||||
self.base_url = (
|
||||
'https://weather.visualcrossing.com/'
|
||||
'VisualCrossingWebServices/rest/services'
|
||||
)
|
||||
self.params = {
|
||||
"key": self.api_key,
|
||||
"iconSet": "icons1", # default value, same as Darksky
|
||||
"unitGroup": "metric",
|
||||
"contentType": "json",
|
||||
"elements": (
|
||||
"datetime,datetimeEpoch,temp,humidity,windspeed,"
|
||||
"winddir,conditions,description,icon"
|
||||
),
|
||||
"include": "current", # to get only specific time data
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _get_timestamp(time: datetime) -> int:
|
||||
# The results are returned in the ‘currentConditions’ field and are
|
||||
# truncated to the hour requested (i.e. 2020-10-19T13:59:00 will return
|
||||
# data at 2020-10-19T13:00:00).
|
||||
|
||||
# first, round datetime to nearest hour by truncating, and then adding
|
||||
# an hour if the "real" time's number of minutes is 30 or more (we do
|
||||
# this since the API only truncates)
|
||||
trunc_time = time.replace(
|
||||
second=0, microsecond=0, minute=0, hour=time.hour
|
||||
) + timedelta(hours=time.minute // 30)
|
||||
appLog.debug(
|
||||
f'VC_weather: truncated time {time} ({time.timestamp()})'
|
||||
f' to {trunc_time} ({trunc_time.timestamp()})'
|
||||
)
|
||||
return int(trunc_time.timestamp())
|
||||
|
||||
def _get_data(
|
||||
self, latitude: float, longitude: float, time: datetime
|
||||
) -> Optional[Dict]:
|
||||
# All requests to the Timeline Weather API use the following the form:
|
||||
|
||||
# https://weather.visualcrossing.com/VisualCrossingWebServices/rest
|
||||
# /services/timeline/[location]/[date1]/[date2]?key=YOUR_API_KEY
|
||||
|
||||
# location (required) – is the address, partial address or
|
||||
# latitude,longitude location for
|
||||
# which to retrieve weather data. You can also use US ZIP Codes.
|
||||
|
||||
# date1 (optional) – is the start date for which to retrieve weather
|
||||
# data. All dates and times are in local time of the **location**
|
||||
# specified.
|
||||
url = (
|
||||
f"{self.base_url}/timeline/{latitude},{longitude}"
|
||||
f"/{self._get_timestamp(time)}"
|
||||
)
|
||||
appLog.debug(
|
||||
f'VC_weather: getting weather from {url}'.replace(
|
||||
self.api_key, '*****'
|
||||
)
|
||||
)
|
||||
r = requests.get(url, params=self.params)
|
||||
r.raise_for_status()
|
||||
res = r.json()
|
||||
weather = res['currentConditions']
|
||||
|
||||
data = {
|
||||
'icon': weather['icon'],
|
||||
'temperature': weather['temp'],
|
||||
'humidity': weather['humidity'] / 100,
|
||||
'wind': weather['windspeed'] * 1000 / (60 * 60), # km/h to m/s
|
||||
'windBearing': weather['winddir'],
|
||||
}
|
||||
return data
|
44
fittrackee/workouts/utils/weather/weather_service.py
Normal file
@ -0,0 +1,44 @@
|
||||
import os
|
||||
from typing import Dict, Optional, Union
|
||||
|
||||
from gpxpy.gpx import GPXTrackPoint
|
||||
|
||||
from fittrackee import appLog
|
||||
|
||||
from .dark_sky import DarkSky
|
||||
from .visual_crossing import VisualCrossing
|
||||
|
||||
|
||||
class WeatherService:
|
||||
"""
|
||||
Available API:
|
||||
- DarkSky (deprecated, will end on March 31st, 2023)
|
||||
- VisualCrossing
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.weather_api = self._get_weather_api()
|
||||
|
||||
@staticmethod
|
||||
def _get_weather_api() -> Union[DarkSky, VisualCrossing, None]:
|
||||
weather_api_key: str = os.getenv('WEATHER_API_KEY', '')
|
||||
weather_api_provider: str = os.getenv(
|
||||
'WEATHER_API_PROVIDER', ''
|
||||
).lower()
|
||||
|
||||
if not weather_api_key:
|
||||
return None
|
||||
if weather_api_provider == 'darksky': # deprecated
|
||||
return DarkSky(weather_api_key)
|
||||
if weather_api_provider == 'visualcrossing':
|
||||
return VisualCrossing(weather_api_key)
|
||||
return None
|
||||
|
||||
def get_weather(self, point: GPXTrackPoint) -> Optional[Dict]:
|
||||
if not self.weather_api:
|
||||
return None
|
||||
try:
|
||||
return self.weather_api.get_weather(point)
|
||||
except Exception as e:
|
||||
appLog.error(e)
|
||||
return None
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fittrackee_client",
|
||||
"version": "0.7.10",
|
||||
"version": "0.7.11",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
@ -11,7 +11,7 @@
|
||||
"i18n:report": "vue-cli-service i18n:report --src \"./src/**/*.?(js|vue)\" --locales \"./src/locales/**/*.json\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@tmcw/togeojson": "^5.5.0",
|
||||
"@tmcw/togeojson": "^5.6.0",
|
||||
"@vue-leaflet/vue-leaflet": "^0.7.0",
|
||||
"@zxcvbn-ts/core": "^2.0.5",
|
||||
"@zxcvbn-ts/language-common": "^2.0.1",
|
||||
@ -22,14 +22,14 @@
|
||||
"axios": "^1.2.1",
|
||||
"chart.js": "^4.1.1",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"core-js": "^3.26.1",
|
||||
"core-js": "^3.27.1",
|
||||
"date-fns": "^2.29.3",
|
||||
"date-fns-tz": "^1.3.7",
|
||||
"leaflet": "^1.9.3",
|
||||
"linkify-html": "^4.0.2",
|
||||
"linkifyjs": "^4.0.2",
|
||||
"register-service-worker": "^1.7.1",
|
||||
"sanitize-html": "^2.8.0",
|
||||
"sanitize-html": "^2.8.1",
|
||||
"vue": "^3.2.45",
|
||||
"vue-chart-3": "3.1.1",
|
||||
"vue-fullscreen": "^3.1.1",
|
||||
@ -42,8 +42,8 @@
|
||||
"@types/chai": "^4.3.4",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/sanitize-html": "^2.8.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
||||
"@typescript-eslint/parser": "^5.47.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.47.1",
|
||||
"@typescript-eslint/parser": "^5.47.1",
|
||||
"@vue/cli-plugin-babel": "~5.0.8",
|
||||
"@vue/cli-plugin-eslint": "~5.0.8",
|
||||
"@vue/cli-plugin-pwa": "~5.0.8",
|
||||
@ -55,7 +55,7 @@
|
||||
"@vue/eslint-config-typescript": "^11.0.2",
|
||||
"@vue/test-utils": "^2.2.6",
|
||||
"chai": "^4.3.7",
|
||||
"eslint": "8.30.0",
|
||||
"eslint": "8.31.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.2",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
|
@ -40,6 +40,12 @@
|
||||
{{ $t('about.CONTACT_ADMIN') }}
|
||||
</a>
|
||||
</div>
|
||||
<div v-if="weather_provider && weather_provider.name">
|
||||
{{ $t('about.WEATHER_DATA_FROM') }}
|
||||
<a :href="weather_provider.url" target="_blank" rel="nofollow noopener">
|
||||
{{ weather_provider.name }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -55,6 +61,22 @@
|
||||
const appConfig: ComputedRef<TAppConfig> = computed(
|
||||
() => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
|
||||
)
|
||||
const weather_provider: ComputedRef<Record<string, string>> = computed(() =>
|
||||
get_weather_provider()
|
||||
)
|
||||
|
||||
function get_weather_provider() {
|
||||
const weather_provider: Record<string, string> = {}
|
||||
if (appConfig.value.weather_provider === 'darksky') {
|
||||
weather_provider['name'] = 'Dark Sky'
|
||||
weather_provider['url'] = 'https://darksky.net'
|
||||
}
|
||||
if (appConfig.value.weather_provider === 'visualcrossing') {
|
||||
weather_provider['name'] = 'Visual Crossing'
|
||||
weather_provider['url'] = 'https://www.visualcrossing.com'
|
||||
}
|
||||
return weather_provider
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -1,13 +1,6 @@
|
||||
<template>
|
||||
<div class="wind">
|
||||
<Distance
|
||||
:distance="weather.wind"
|
||||
unitFrom="m"
|
||||
:digits="1"
|
||||
:displayUnit="false"
|
||||
:useImperialUnits="useImperialUnits"
|
||||
/>
|
||||
{{ useImperialUnits ? 'ft' : 'm' }}/s
|
||||
{{ getWindSpeed(weather.wind, useImperialUnits) }}
|
||||
<div class="wind-bearing">
|
||||
<i
|
||||
v-if="weather.windBearing"
|
||||
@ -27,6 +20,7 @@
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { IWeather } from '@/types/workouts'
|
||||
import { getWindSpeed } from '@/utils/units'
|
||||
import { convertDegreeToDirection } from '@/utils/weather'
|
||||
|
||||
interface Props {
|
||||
|
@ -58,10 +58,20 @@
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
{{ Number(workoutObject.weatherStart.temperature).toFixed(1) }}°C
|
||||
{{
|
||||
getTemperature(
|
||||
workoutObject.weatherStart.temperature,
|
||||
useImperialUnits
|
||||
)
|
||||
}}
|
||||
</td>
|
||||
<td>
|
||||
{{ Number(workoutObject.weatherEnd.temperature).toFixed(1) }}°C
|
||||
{{
|
||||
getTemperature(
|
||||
workoutObject.weatherEnd.temperature,
|
||||
useImperialUnits
|
||||
)
|
||||
}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -112,6 +122,7 @@
|
||||
|
||||
import WeatherWind from '@/components/Workout/WorkoutDetail/WeatherWind.vue'
|
||||
import { IWorkoutObject } from '@/types/workouts'
|
||||
import { getTemperature } from '@/utils/units'
|
||||
|
||||
interface Props {
|
||||
workoutObject: IWorkoutObject
|
||||
|
@ -94,9 +94,9 @@
|
||||
},
|
||||
"TIMEZONE": "Zeitzone",
|
||||
"UNITS": {
|
||||
"IMPERIAL": "Imperiales System (ft, mi)",
|
||||
"IMPERIAL": "Imperiales System (ft, mi, mph, °F)",
|
||||
"LABEL": "Einheiten für die Distanz",
|
||||
"METRIC": "Metrisches System (m, km)"
|
||||
"METRIC": "Metrisches System (m, km, m/s, °C)"
|
||||
}
|
||||
},
|
||||
"REGISTER": "Registrieren",
|
||||
|
@ -16,6 +16,7 @@
|
||||
"FROM": "Von",
|
||||
"GPX_FILE": ".gpx Datei",
|
||||
"HIDE_FILTERS": "verberge Filter",
|
||||
"INVALID_ASCENT_OR_DESCENT": "Beide Höhenwerte müssen angegeben werden und größer oder gleich 0 sein.",
|
||||
"INVALID_DISTANCE": "Die Distanz muss größer als 0 sein",
|
||||
"INVALID_DURATION": "Die Dauer muss größer als 0 Sekunden sein",
|
||||
"LATEST_WORKOUTS": "Letzte Trainings",
|
||||
|
@ -2,5 +2,6 @@
|
||||
"CONTACT_ADMIN": "Contact the administrator",
|
||||
"FITTRACKEE_DESCRIPTION": "<strong>FitTrackee</strong> is a self-hosted outdoor activity tracker.",
|
||||
"FITTRACKEE_LICENSE": "under {0} license ",
|
||||
"SOURCE_CODE": "Source code"
|
||||
"SOURCE_CODE": "Source code",
|
||||
"WEATHER_DATA_FROM": "Weather data from:"
|
||||
}
|
@ -94,9 +94,9 @@
|
||||
},
|
||||
"TIMEZONE": "Timezone",
|
||||
"UNITS": {
|
||||
"IMPERIAL": "Imperial system (ft, mi)",
|
||||
"IMPERIAL": "Imperial system (ft, mi, mph, °F)",
|
||||
"LABEL": "Units for distance",
|
||||
"METRIC": "Metric system (m, km)"
|
||||
"METRIC": "Metric system (m, km, m/s, °C)"
|
||||
}
|
||||
},
|
||||
"REGISTER": "Register",
|
||||
@ -108,4 +108,4 @@
|
||||
"USERNAME": "Username",
|
||||
"USERNAME_INFO": "3 to 30 characters required, only alphanumeric characters and the underscore character \"_\" allowed.",
|
||||
"USER_PICTURE": "user picture"
|
||||
}
|
||||
}
|
@ -2,5 +2,6 @@
|
||||
"CONTACT_ADMIN": "Contacter l'administrateur",
|
||||
"FITTRACKEE_DESCRIPTION": "<strong>FitTrackee</strong> est un <em>tracker</em> d'activités sportives (en extérieur).",
|
||||
"FITTRACKEE_LICENSE": "sous licence {0} (en) ",
|
||||
"SOURCE_CODE": "Code source (en)"
|
||||
"SOURCE_CODE": "Code source (en)",
|
||||
"WEATHER_DATA_FROM": "Source des données météo :"
|
||||
}
|
||||
|
@ -94,9 +94,9 @@
|
||||
},
|
||||
"TIMEZONE": "Fuseau horaire",
|
||||
"UNITS": {
|
||||
"IMPERIAL": "Système impérial (ft, mi)",
|
||||
"IMPERIAL": "Système impérial (ft, mi, mph, °F)",
|
||||
"LABEL": "Unités pour les distances",
|
||||
"METRIC": "Système métrique (m, km)"
|
||||
"METRIC": "Système métrique (m, km, m/s, °C)"
|
||||
}
|
||||
},
|
||||
"REGISTER": "S'inscrire",
|
||||
@ -108,4 +108,4 @@
|
||||
"USERNAME": "Nom d'utilisateur",
|
||||
"USERNAME_INFO": "3 à 30 caractères requis, seuls les caractères alphanumériques et le caractère _ sont autorisés.",
|
||||
"USER_PICTURE": "photo de l'utilisateur"
|
||||
}
|
||||
}
|
@ -94,9 +94,9 @@
|
||||
},
|
||||
"TIMEZONE": "Timezone",
|
||||
"UNITS": {
|
||||
"IMPERIAL": "Sistema imperiale (ft, mi)",
|
||||
"IMPERIAL": "Sistema imperiale (ft, mi, mph, °F)",
|
||||
"LABEL": "Unità per la distanza",
|
||||
"METRIC": "Sistema metrico (m, km)"
|
||||
"METRIC": "Sistema metrico (m, km, m/s, °C)"
|
||||
}
|
||||
},
|
||||
"REGISTER": "Registra",
|
||||
|
@ -13,6 +13,6 @@
|
||||
"NO": "Nee",
|
||||
"REGISTER": "Registreer",
|
||||
"RESET": "Reset",
|
||||
"SUBMIT": "Aanpassen",
|
||||
"SUBMIT": "Uploaden",
|
||||
"YES": "Ja"
|
||||
}
|
||||
|
@ -94,9 +94,9 @@
|
||||
},
|
||||
"TIMEZONE": "Tijdzone",
|
||||
"UNITS": {
|
||||
"IMPERIAL": "Imperialistisch systeem (ft, mi)",
|
||||
"IMPERIAL": "Imperialistisch systeem (ft, mi, mph, °F)",
|
||||
"LABEL": "Eenheid voor afstand",
|
||||
"METRIC": "Metrisch systeem (m, km)"
|
||||
"METRIC": "Metrisch systeem (m, km, m/s, °C)"
|
||||
}
|
||||
},
|
||||
"REGISTER": "Registreren",
|
||||
|
@ -16,6 +16,7 @@
|
||||
"FROM": "van",
|
||||
"GPX_FILE": ".gpx bestand",
|
||||
"HIDE_FILTERS": "verberg filters",
|
||||
"INVALID_ASCENT_OR_DESCENT": "Beide waarden moeten opgegeven worden en dienen groter dan of gelijk aan 0 te zijn.",
|
||||
"INVALID_DISTANCE": "De afstand moet groter zijn dan 0",
|
||||
"INVALID_DURATION": "De duur moet langer zijn dan 0 seconden",
|
||||
"LATEST_WORKOUTS": "Laatste trainingen",
|
||||
|
@ -6,7 +6,7 @@ export interface IAppStatistics {
|
||||
}
|
||||
|
||||
export type TAppConfig = {
|
||||
[key: string]: number | boolean | string
|
||||
[key: string]: number | boolean | string | null
|
||||
admin_contact: string
|
||||
gpx_limit_import: number
|
||||
is_email_sending_enabled: boolean
|
||||
@ -16,6 +16,7 @@ export type TAppConfig = {
|
||||
max_users: number
|
||||
max_zip_file_size: number
|
||||
version: string
|
||||
weather_provider: string | null
|
||||
}
|
||||
|
||||
export interface IApplication {
|
||||
|
@ -63,3 +63,23 @@ export const convertStatsDistance = (
|
||||
const unitTo = useImperialUnits ? units[unitFrom].defaultTarget : unitFrom
|
||||
return useImperialUnits ? convertDistance(value, unitFrom, unitTo, 2) : value
|
||||
}
|
||||
|
||||
export const getTemperature = (
|
||||
temperatureInCelsius: number,
|
||||
useImperialUnits: boolean
|
||||
): string => {
|
||||
const temperature = useImperialUnits
|
||||
? temperatureInCelsius * 1.8 + 32
|
||||
: temperatureInCelsius
|
||||
const unit = useImperialUnits ? ' °F' : '°C'
|
||||
return `${temperature === 0 ? 0 : Number(temperature).toFixed(1)}${unit}`
|
||||
}
|
||||
|
||||
export const getWindSpeed = (
|
||||
windSpeedInMS: number,
|
||||
useImperialUnits: boolean
|
||||
): string => {
|
||||
const windSpeed = useImperialUnits ? windSpeedInMS * 2.2369363 : windSpeedInMS
|
||||
const unit = useImperialUnits ? ' mph' : 'm/s'
|
||||
return `${windSpeed === 0 ? 0 : Number(windSpeed).toFixed(1)}${unit}`
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { TUnit } from '@/types/units'
|
||||
import { convertDistance } from '@/utils/units'
|
||||
import { convertDistance, getTemperature, getWindSpeed } from '@/utils/units'
|
||||
|
||||
describe('convertDistance', () => {
|
||||
const testsParams: [number, TUnit, TUnit, number][] = [
|
||||
@ -56,3 +56,35 @@ describe('convertDistance w/ digits', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getTemperature', () => {
|
||||
const testsParams: [number, boolean, string][] = [
|
||||
[0, false, '0°C'],
|
||||
[10.0, false, '10.0°C'],
|
||||
[10.3, false, '10.3°C'],
|
||||
[0, true, '32.0 °F'],
|
||||
[13.0, true, '55.4 °F'],
|
||||
]
|
||||
|
||||
testsParams.map((testParams) => {
|
||||
it(`get temperature for input: ${testParams[0]} and imperialUnits: ${testParams[1]}`, () => {
|
||||
assert.equal(getTemperature(testParams[0], testParams[1]), testParams[2])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getWindSpeed', () => {
|
||||
const testsParams: [number, boolean, string][] = [
|
||||
[0, false, '0m/s'],
|
||||
[6.0, false, '6.0m/s'],
|
||||
[6.3, false, '6.3m/s'],
|
||||
[0, true, '0 mph'],
|
||||
[13.2, true, '29.5 mph'],
|
||||
]
|
||||
|
||||
testsParams.map((testParams) => {
|
||||
it(`get wind speed for input: ${testParams[0]} and imperialUnits: ${testParams[1]}`, () => {
|
||||
assert.equal(getWindSpeed(testParams[0], testParams[1]), testParams[2])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -963,10 +963,10 @@
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@eslint/eslintrc@^1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.0.tgz#8ec64e0df3e7a1971ee1ff5158da87389f167a63"
|
||||
integrity sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A==
|
||||
"@eslint/eslintrc@^1.4.1":
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e"
|
||||
integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
@ -1251,10 +1251,10 @@
|
||||
magic-string "^0.25.0"
|
||||
string.prototype.matchall "^4.0.6"
|
||||
|
||||
"@tmcw/togeojson@^5.5.0":
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@tmcw/togeojson/-/togeojson-5.5.0.tgz#874081d1b3df1e51a6c5e878dd8f4cdf06a3ac48"
|
||||
integrity sha512-K/neYsnwGkC1sjI0UInSyuxybPsBPXZF+g18l7XtzW37Jfzzcw4YjMd/rnqP5QRONtjuvGN6nGeCemKfeWkPGg==
|
||||
"@tmcw/togeojson@^5.6.0":
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@tmcw/togeojson/-/togeojson-5.6.0.tgz#a6c96971acdf36eef73a1c398cf19a565eb02831"
|
||||
integrity sha512-p+c0kbSY/tIwd3C0rpmTf3iFAOUYV6bkJbDiq0oQDGROOc7c6uh/X8r/mijY6SIFYIkVuKc8MS2REKhur2e6Jw==
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
@ -1489,7 +1489,7 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.0.0", "@typescript-eslint/eslint-plugin@^5.47.0":
|
||||
"@typescript-eslint/eslint-plugin@^5.0.0":
|
||||
version "5.47.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.0.tgz#dadb79df3b0499699b155839fd6792f16897d910"
|
||||
integrity sha512-AHZtlXAMGkDmyLuLZsRpH3p4G/1iARIwc/T0vIem2YB+xW6pZaXYXzCBnZSF/5fdM97R9QqZWZ+h3iW10XgevQ==
|
||||
@ -1504,7 +1504,22 @@
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.47.0":
|
||||
"@typescript-eslint/eslint-plugin@^5.47.1":
|
||||
version "5.47.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.1.tgz#50cc5085578a7fa22cd46a0806c2e5eae858af02"
|
||||
integrity sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.47.1"
|
||||
"@typescript-eslint/type-utils" "5.47.1"
|
||||
"@typescript-eslint/utils" "5.47.1"
|
||||
debug "^4.3.4"
|
||||
ignore "^5.2.0"
|
||||
natural-compare-lite "^1.4.0"
|
||||
regexpp "^3.2.0"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/parser@^5.0.0":
|
||||
version "5.47.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.0.tgz#62e83de93499bf4b500528f74bf2e0554e3a6c8d"
|
||||
integrity sha512-udPU4ckK+R1JWCGdQC4Qa27NtBg7w020ffHqGyAK8pAgOVuNw7YaKXGChk+udh+iiGIJf6/E/0xhVXyPAbsczw==
|
||||
@ -1514,6 +1529,16 @@
|
||||
"@typescript-eslint/typescript-estree" "5.47.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/parser@^5.47.1":
|
||||
version "5.47.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.1.tgz#c4bf16f8c3c7608ce4bf8ff804b677fc899f173f"
|
||||
integrity sha512-9Vb+KIv29r6GPu4EboWOnQM7T+UjpjXvjCPhNORlgm40a9Ia9bvaPJswvtae1gip2QEeVeGh6YquqAzEgoRAlw==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.47.1"
|
||||
"@typescript-eslint/types" "5.47.1"
|
||||
"@typescript-eslint/typescript-estree" "5.47.1"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.47.0":
|
||||
version "5.47.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.0.tgz#f58144a6b0ff58b996f92172c488813aee9b09df"
|
||||
@ -1522,6 +1547,14 @@
|
||||
"@typescript-eslint/types" "5.47.0"
|
||||
"@typescript-eslint/visitor-keys" "5.47.0"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.47.1":
|
||||
version "5.47.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.1.tgz#0d302b3c2f20ab24e4787bf3f5a0d8c449b823bd"
|
||||
integrity sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.47.1"
|
||||
"@typescript-eslint/visitor-keys" "5.47.1"
|
||||
|
||||
"@typescript-eslint/type-utils@5.47.0":
|
||||
version "5.47.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.0.tgz#2b440979c574e317d3473225ae781f292c99e55d"
|
||||
@ -1532,11 +1565,26 @@
|
||||
debug "^4.3.4"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/type-utils@5.47.1":
|
||||
version "5.47.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.1.tgz#aee13314f840ab336c1adb49a300856fd16d04ce"
|
||||
integrity sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "5.47.1"
|
||||
"@typescript-eslint/utils" "5.47.1"
|
||||
debug "^4.3.4"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/types@5.47.0":
|
||||
version "5.47.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.0.tgz#67490def406eaa023dbbd8da42ee0d0c9b5229d3"
|
||||
integrity sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg==
|
||||
|
||||
"@typescript-eslint/types@5.47.1":
|
||||
version "5.47.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.1.tgz#459f07428aec5a8c4113706293c2ae876741ac8e"
|
||||
integrity sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.47.0":
|
||||
version "5.47.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.0.tgz#ed971a11c5c928646d6ba7fc9dfdd6e997649aca"
|
||||
@ -1550,6 +1598,19 @@
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.47.1":
|
||||
version "5.47.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.1.tgz#b9d8441308aca53df7f69b2c67a887b82c9ed418"
|
||||
integrity sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.47.1"
|
||||
"@typescript-eslint/visitor-keys" "5.47.1"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/utils@5.47.0":
|
||||
version "5.47.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.0.tgz#b5005f7d2696769a1fdc1e00897005a25b3a0ec7"
|
||||
@ -1564,6 +1625,20 @@
|
||||
eslint-utils "^3.0.0"
|
||||
semver "^7.3.7"
|
||||
|
||||
"@typescript-eslint/utils@5.47.1":
|
||||
version "5.47.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.1.tgz#595f25ac06e9ee28c339fd43c709402820b13d7b"
|
||||
integrity sha512-l90SdwqfmkuIVaREZ2ykEfCezepCLxzWMo5gVfcJsJCaT4jHT+QjgSkYhs5BMQmWqE9k3AtIfk4g211z/sTMVw==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.9"
|
||||
"@types/semver" "^7.3.12"
|
||||
"@typescript-eslint/scope-manager" "5.47.1"
|
||||
"@typescript-eslint/types" "5.47.1"
|
||||
"@typescript-eslint/typescript-estree" "5.47.1"
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
semver "^7.3.7"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.47.0":
|
||||
version "5.47.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.0.tgz#4aca4efbdf6209c154df1f7599852d571b80bb45"
|
||||
@ -1572,6 +1647,14 @@
|
||||
"@typescript-eslint/types" "5.47.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.47.1":
|
||||
version "5.47.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz#d35c2da544dbb685db9c5b5b85adac0a1d74d1f2"
|
||||
integrity sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.47.1"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@ungap/promise-all-settled@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
|
||||
@ -3000,7 +3083,12 @@ core-js@^2.6.12:
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
core-js@^3.26.1, core-js@^3.8.3:
|
||||
core-js@^3.27.1:
|
||||
version "3.27.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.27.1.tgz#23cc909b315a6bb4e418bf40a52758af2103ba46"
|
||||
integrity sha512-GutwJLBChfGCpwwhbYoqfv03LAfmiz7e7D/BNxzeMxwQf10GRSzqiOjx7AmtEk+heiD/JWmBuyBPgFtx0Sg1ww==
|
||||
|
||||
core-js@^3.8.3:
|
||||
version "3.26.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e"
|
||||
integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==
|
||||
@ -3788,12 +3876,12 @@ eslint-webpack-plugin@^3.1.0:
|
||||
normalize-path "^3.0.0"
|
||||
schema-utils "^4.0.0"
|
||||
|
||||
eslint@8.30.0:
|
||||
version "8.30.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50"
|
||||
integrity sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ==
|
||||
eslint@8.31.0:
|
||||
version "8.31.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.31.0.tgz#75028e77cbcff102a9feae1d718135931532d524"
|
||||
integrity sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==
|
||||
dependencies:
|
||||
"@eslint/eslintrc" "^1.4.0"
|
||||
"@eslint/eslintrc" "^1.4.1"
|
||||
"@humanwhocodes/config-array" "^0.11.8"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
"@nodelib/fs.walk" "^1.2.8"
|
||||
@ -6723,10 +6811,10 @@ safe-regex-test@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
sanitize-html@^2.8.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.8.0.tgz#651d1d0e5b2d61b4ec6147cc46f6d6680eef98ce"
|
||||
integrity sha512-ZsGyc6avnqgvEm3eMKrcy8xa7WM1MrGrfkGsUgQee2CU+vg3PCfNCexXwBDF/6dEPvaQ4k/QqRjnYKHL8xgNjg==
|
||||
sanitize-html@^2.8.1:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.8.1.tgz#319c4fdba67e1edf35b1fd6d9362210044826d47"
|
||||
integrity sha512-qK5neD0SaMxGwVv5txOYv05huC3o6ZAA4h5+7nJJgWMNFUNRjcjLO6FpwAtKzfKCZ0jrG6xTk6eVFskbvOGblg==
|
||||
dependencies:
|
||||
deepmerge "^4.2.2"
|
||||
escape-string-regexp "^4.0.0"
|
||||
|
210
poetry.lock
generated
@ -14,14 +14,14 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "alembic"
|
||||
version = "1.9.0"
|
||||
version = "1.9.1"
|
||||
description = "A database migration tool for SQLAlchemy."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "alembic-1.9.0-py3-none-any.whl", hash = "sha256:e8ce855f731d92cfdbf9a71d148401fcc420399927817c6e2c0b6a5f31db745d"},
|
||||
{file = "alembic-1.9.0.tar.gz", hash = "sha256:6af6792fe699730b27480382701b16028ebbaac6bc5cd4f06daf5fa3e4690364"},
|
||||
{file = "alembic-1.9.1-py3-none-any.whl", hash = "sha256:a9781ed0979a20341c2cbb56bd22bd8db4fc1913f955e705444bd3a97c59fa32"},
|
||||
{file = "alembic-1.9.1.tar.gz", hash = "sha256:f9f76e41061f5ebe27d4fe92600df9dd612521a7683f904dab328ba02cffa5a2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -62,21 +62,22 @@ typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""}
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "22.1.0"
|
||||
version = "22.2.0"
|
||||
description = "Classes Without Boilerplate"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"},
|
||||
{file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"},
|
||||
{file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"},
|
||||
{file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
|
||||
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
|
||||
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
|
||||
tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
|
||||
cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"]
|
||||
dev = ["attrs[docs,tests]"]
|
||||
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"]
|
||||
tests = ["attrs[tests-no-zope]", "zope.interface"]
|
||||
tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"]
|
||||
|
||||
[[package]]
|
||||
name = "authlib"
|
||||
@ -352,63 +353,63 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "7.0.0"
|
||||
version = "7.0.1"
|
||||
description = "Code coverage measurement for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "coverage-7.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f2569682d6ea9628da8d6ba38579a48b1e53081226ec7a6c82b5024b3ce5009f"},
|
||||
{file = "coverage-7.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ec256a592b497f26054195f7d7148892aca8c4cdcc064a7cc66ef7a0455b811"},
|
||||
{file = "coverage-7.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5885a4ceb6dde34271bb0adafa4a248a7f589c89821e9da3110c39f92f41e21b"},
|
||||
{file = "coverage-7.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d43d406a4d73aa7f855fa44fa77ff47e739b565b2af3844600cdc016d01e46b9"},
|
||||
{file = "coverage-7.0.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18df11efa615b79b9ecc13035a712957ff6283f7b244e57684e1c092869f541"},
|
||||
{file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f6a4bf5bdee93f6817797beba7086292c2ebde6df0d5822e0c33f8b05415c339"},
|
||||
{file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:33efe89cd0efef016db19d8d05aa46631f76793de90a61b6717acb202b36fe60"},
|
||||
{file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96b5b1f1079e48f56bfccf103bcf44d48b9eb5163f1ea523fad580f15d3fe5e0"},
|
||||
{file = "coverage-7.0.0-cp310-cp310-win32.whl", hash = "sha256:fb85b7a7a4b204bd59d6d0b0c8d87d9ffa820da225e691dfaffc3137dc05b5f6"},
|
||||
{file = "coverage-7.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:793dcd9d42035746fc7637df4336f7581df19d33c5c5253cf988c99d8e93a8ba"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d564142a03d3bc8913499a458e931b52ddfe952f69b6cd4b24d810fd2959044a"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0a8b0e86bede874bf5da566b02194fbb12dd14ce3585cabd58452007f272ba81"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e645c73cbfc4577d93747d3f793115acf6f907a7eb9208fa807fdcf2da1964a4"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de06e7585abe88c6d38c1b73ce4c3cb4c1a79fbb0da0d0f8e8689ef5729ec60d"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a30b646fbdd5bc52f506e149fa4fbdef82432baf6b81774e61ec4e3b43b9cbde"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:db8141856dc9be0917413df7200f53accf1d84c8b156868e6af058a1ea8e903a"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:59e71912c7fc78d08a567ee65656123878f49ca1b5672e660ea70bf8dfbebf8f"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b8f7cd942dda3795fc9eadf303cc53a422ac057e3b70c2ad6d4276ec6a83a541"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-win32.whl", hash = "sha256:bf437a04b9790d3c9cd5b48e9ce9aa84229040e3ae7d6c670a55118906113c5a"},
|
||||
{file = "coverage-7.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:a7e1bb36b4e57a2d304322021b35d4e4a25fa0d501ba56e8e51efaebf4480556"},
|
||||
{file = "coverage-7.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:215f40ef86f1958a1151fa7fad2b4f2f99534c4e10a34a1e065eba3f19ef8868"},
|
||||
{file = "coverage-7.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae088eb1cbdad8206931b1bf3f11dee644e038a9300be84d3e705e29356e5b1d"},
|
||||
{file = "coverage-7.0.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9071e197faa24837b967bc9aa0b9ef961f805a75f1ee3ea1f3367f55cd46c3c"},
|
||||
{file = "coverage-7.0.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f1e6d9c70d45a960d3f3d781ea62b167fdf2e0e1f6bb282b96feea653adb923"},
|
||||
{file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9fadd15f9fcfd7b16d9cccce9f5e6ec6f9b8df860633ad9aa62c2b14c259560f"},
|
||||
{file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:10b6246cae61896ab4c7568e498e492cbb73a2dfa4c3af79141c43cf806f929a"},
|
||||
{file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a8785791c2120af114ea7a06137f7778632e568a5aa2bbfc3b46c573b702af74"},
|
||||
{file = "coverage-7.0.0-cp37-cp37m-win32.whl", hash = "sha256:30220518dd89c4878908d73f5f3d1269f86e9e045354436534587a18c7b9da85"},
|
||||
{file = "coverage-7.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bc904aa96105d73357de03de76336b1e3db28e2b12067d36625fd9646ab043fd"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2331b7bd84a1be79bd17ca8e103ce38db8cbf7cb354dc56e651ba489cf849212"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e907db8bdd0ad1253a33c20fdc5f0f6209d271114a9c6f1fcdf96617343f7ca0"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0deee68e0dae1d6e3fe6943c76d7e66fbeb6519bd08e4e5366bcc28a8a9aca"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fff0f08bc5ffd0d78db821971472b4adc2ee876b86f743e46d634fb8e3c22f"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a290b7921c1c05787b953e5854d394e887df40696f21381cc33c4e2179bf50ac"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:100546219af59d2ad82d4575de03a303eb27b75ea36ffbd1677371924d50bcbc"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c1ba6e63b831112b9484ff5905370d89e43d4316bac76d403031f60d61597466"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c685fc17d6f4f1a3833e9dac27d0b931f7ccb52be6c30d269374203c7d0204a2"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-win32.whl", hash = "sha256:8938f3a10f45019b502020ba9567b97b6ecc8c76b664b421705c5406d4f92fe8"},
|
||||
{file = "coverage-7.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:c4b63888bef2928d0eca12cbce0760cfb696acb4fe226eb55178b6a2a039328a"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cda63459eb20652b22e038729a8f5063862c189a3963cb042a764b753172f75e"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e06abac1a4aec1ff989131e43ca917fc7bd296f34bf0cfe86cbf74343b21566d"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b94ad926e933976627f040f96dd1d9b0ac91f8d27e868c30a28253b9b6ac2d"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6b4af31fb49a2ae8de1cd505fa66c403bfcc5066e845ac19d8904dcfc9d40da"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36b62f0220459e528ad5806cc7dede71aa716e067d2cb10cb4a09686b8791fba"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:43ec1935c6d6caab4f3bc126d20bd709c0002a175d62208ebe745be37a826a41"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8593c9baf1f0f273afa22f5b45508b76adc7b8e94e17e7d98fbe1e3cd5812af2"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fee283cd36c3f14422d9c1b51da24ddbb5e1eed89ad2480f6a9f115df38b5df8"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-win32.whl", hash = "sha256:97c0b001ff15b8e8882995fc07ac0a08c8baf8b13c1145f3f12e0587bbb0e335"},
|
||||
{file = "coverage-7.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:8dbf83a4611c591b5de65069b6fd4dd3889200ed270cd2f7f5ac765d3842889f"},
|
||||
{file = "coverage-7.0.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:bcaf18e46668057051a312c714a4548b81f7e8fb3454116ad97be7562d2a99e4"},
|
||||
{file = "coverage-7.0.0.tar.gz", hash = "sha256:9a175da2a7320e18fc3ee1d147639a2b3a8f037e508c96aa2da160294eb50e17"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b3695c4f4750bca943b3e1f74ad4be8d29e4aeab927d50772c41359107bd5d5c"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fa6a5a224b7f4cfb226f4fc55a57e8537fcc096f42219128c2c74c0e7d0953e1"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74f70cd92669394eaf8d7756d1b195c8032cf7bbbdfce3bc489d4e15b3b8cf73"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b66bb21a23680dee0be66557dc6b02a3152ddb55edf9f6723fa4a93368f7158d"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d87717959d4d0ee9db08a0f1d80d21eb585aafe30f9b0a54ecf779a69cb015f6"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:854f22fa361d1ff914c7efa347398374cc7d567bdafa48ac3aa22334650dfba2"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1e414dc32ee5c3f36544ea466b6f52f28a7af788653744b8570d0bf12ff34bc0"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6c5ad996c6fa4d8ed669cfa1e8551348729d008a2caf81489ab9ea67cfbc7498"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-win32.whl", hash = "sha256:691571f31ace1837838b7e421d3a09a8c00b4aac32efacb4fc9bd0a5c647d25a"},
|
||||
{file = "coverage-7.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:89caf4425fe88889e2973a8e9a3f6f5f9bbe5dd411d7d521e86428c08a873a4a"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:63d56165a7c76265468d7e0c5548215a5ba515fc2cba5232d17df97bffa10f6c"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f943a3b2bc520102dd3e0bb465e1286e12c9a54f58accd71b9e65324d9c7c01"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:830525361249dc4cd013652b0efad645a385707a5ae49350c894b67d23fbb07c"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd1b9c5adc066db699ccf7fa839189a649afcdd9e02cb5dc9d24e67e7922737d"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00c14720b8b3b6c23b487e70bd406abafc976ddc50490f645166f111c419c39"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6d55d840e1b8c0002fce66443e124e8581f30f9ead2e54fbf6709fb593181f2c"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:66b18c3cf8bbab0cce0d7b9e4262dc830e93588986865a8c78ab2ae324b3ed56"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:12a5aa77783d49e05439fbe6e6b427484f8a0f9f456b46a51d8aac022cfd024d"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-win32.whl", hash = "sha256:b77015d1cb8fe941be1222a5a8b4e3fbca88180cfa7e2d4a4e58aeabadef0ab7"},
|
||||
{file = "coverage-7.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb992c47cb1e5bd6a01e97182400bcc2ba2077080a17fcd7be23aaa6e572e390"},
|
||||
{file = "coverage-7.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e78e9dcbf4f3853d3ae18a8f9272111242531535ec9e1009fa8ec4a2b74557dc"},
|
||||
{file = "coverage-7.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60bef2e2416f15fdc05772bf87db06c6a6f9870d1db08fdd019fbec98ae24a9"},
|
||||
{file = "coverage-7.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9823e4789ab70f3ec88724bba1a203f2856331986cd893dedbe3e23a6cfc1e4e"},
|
||||
{file = "coverage-7.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9158f8fb06747ac17bd237930c4372336edc85b6e13bdc778e60f9d685c3ca37"},
|
||||
{file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:486ee81fa694b4b796fc5617e376326a088f7b9729c74d9defa211813f3861e4"},
|
||||
{file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1285648428a6101b5f41a18991c84f1c3959cee359e51b8375c5882fc364a13f"},
|
||||
{file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2c44fcfb3781b41409d0f060a4ed748537557de9362a8a9282182fafb7a76ab4"},
|
||||
{file = "coverage-7.0.1-cp37-cp37m-win32.whl", hash = "sha256:d6814854c02cbcd9c873c0f3286a02e3ac1250625cca822ca6bc1018c5b19f1c"},
|
||||
{file = "coverage-7.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f66460f17c9319ea4f91c165d46840314f0a7c004720b20be58594d162a441d8"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b373c9345c584bb4b5f5b8840df7f4ab48c4cbb7934b58d52c57020d911b856"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d3022c3007d3267a880b5adcf18c2a9bf1fc64469b394a804886b401959b8742"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92651580bd46519067e36493acb394ea0607b55b45bd81dd4e26379ed1871f55"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cfc595d2af13856505631be072835c59f1acf30028d1c860b435c5fc9c15b69"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b4b3a4d9915b2be879aff6299c0a6129f3d08a775d5a061f503cf79571f73e4"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b6f22bb64cc39bcb883e5910f99a27b200fdc14cdd79df8696fa96b0005c9444"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72d1507f152abacea81f65fee38e4ef3ac3c02ff8bc16f21d935fd3a8a4ad910"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a79137fc99815fff6a852c233628e735ec15903cfd16da0f229d9c4d45926ab"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-win32.whl", hash = "sha256:b3763e7fcade2ff6c8e62340af9277f54336920489ceb6a8cd6cc96da52fcc62"},
|
||||
{file = "coverage-7.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:09f6b5a8415b6b3e136d5fec62b552972187265cb705097bf030eb9d4ffb9b60"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:978258fec36c154b5e250d356c59af7d4c3ba02bef4b99cda90b6029441d797d"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:19ec666533f0f70a0993f88b8273057b96c07b9d26457b41863ccd021a043b9a"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfded268092a84605f1cc19e5c737f9ce630a8900a3589e9289622db161967e9"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07bcfb1d8ac94af886b54e18a88b393f6a73d5959bb31e46644a02453c36e475"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:397b4a923cc7566bbc7ae2dfd0ba5a039b61d19c740f1373791f2ebd11caea59"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aec2d1515d9d39ff270059fd3afbb3b44e6ec5758af73caf18991807138c7118"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c20cfebcc149a4c212f6491a5f9ff56f41829cd4f607b5be71bb2d530ef243b1"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fd556ff16a57a070ce4f31c635953cc44e25244f91a0378c6e9bdfd40fdb249f"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-win32.whl", hash = "sha256:b9ea158775c7c2d3e54530a92da79496fb3fb577c876eec761c23e028f1e216c"},
|
||||
{file = "coverage-7.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:d1991f1dd95eba69d2cd7708ff6c2bbd2426160ffc73c2b81f617a053ebcb1a8"},
|
||||
{file = "coverage-7.0.1-pp37.pp38.pp39-none-any.whl", hash = "sha256:3dd4ee135e08037f458425b8842d24a95a0961831a33f89685ff86b77d378f89"},
|
||||
{file = "coverage-7.0.1.tar.gz", hash = "sha256:a4a574a19eeb67575a5328a5760bbbb737faa685616586a9f9da4281f940109c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -521,14 +522,14 @@ watch = ["watchdog", "watchdog-gevent"]
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.0.4"
|
||||
version = "1.1.0"
|
||||
description = "Backport of PEP 654 (exception groups)"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"},
|
||||
{file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"},
|
||||
{file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"},
|
||||
{file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@ -623,22 +624,23 @@ dramatiq = ">=1.5,<2.0"
|
||||
|
||||
[[package]]
|
||||
name = "flask-limiter"
|
||||
version = "2.8.1"
|
||||
version = "2.9.2"
|
||||
description = "Rate limiting for flask applications"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "Flask-Limiter-2.8.1.tar.gz", hash = "sha256:d37d0a39ce1fe36f661a765132557d3213040c51d9355379fe2f336bfea7e308"},
|
||||
{file = "Flask_Limiter-2.8.1-py3-none-any.whl", hash = "sha256:621f1f26fbde4768c60df510e31569e72ae91eee659633e35fd78d90073a0d56"},
|
||||
{file = "Flask-Limiter-2.9.2.tar.gz", hash = "sha256:041bf0d72c8c62d2cb54c772de1ad842c82bdefeddfadc1c9171739f296484e2"},
|
||||
{file = "Flask_Limiter-2.9.2-py3-none-any.whl", hash = "sha256:64c6456204d88006324127071598a04cdd77be1576e00e8f5b74fad80925ea37"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
Flask = ">=2"
|
||||
limits = [
|
||||
{version = ">=2.3"},
|
||||
{version = ">=2.8"},
|
||||
{version = "*", extras = ["redis"], optional = true, markers = "extra == \"redis\""},
|
||||
]
|
||||
ordered-set = ">4,<5"
|
||||
rich = ">=12,<13"
|
||||
typing-extensions = ">=4"
|
||||
|
||||
@ -712,14 +714,14 @@ smmap = ">=3.0.1,<6"
|
||||
|
||||
[[package]]
|
||||
name = "gitpython"
|
||||
version = "3.1.29"
|
||||
version = "3.1.30"
|
||||
description = "GitPython is a python library used to interact with Git repositories"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "GitPython-3.1.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"},
|
||||
{file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"},
|
||||
{file = "GitPython-3.1.30-py3-none-any.whl", hash = "sha256:cd455b0000615c60e286208ba540271af9fe531fa6a87cc590a7298785ab2882"},
|
||||
{file = "GitPython-3.1.30.tar.gz", hash = "sha256:769c2d83e13f5d938b7688479da374c4e3d49f71549aaf462b646db9602ea6f8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -909,21 +911,21 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag
|
||||
|
||||
[[package]]
|
||||
name = "importlib-resources"
|
||||
version = "5.10.1"
|
||||
version = "5.10.2"
|
||||
description = "Read resources from Python packages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "importlib_resources-5.10.1-py3-none-any.whl", hash = "sha256:c09b067d82e72c66f4f8eb12332f5efbebc9b007c0b6c40818108c9870adc363"},
|
||||
{file = "importlib_resources-5.10.1.tar.gz", hash = "sha256:32bb095bda29741f6ef0e5278c42df98d135391bee5f932841efc0041f748dc3"},
|
||||
{file = "importlib_resources-5.10.2-py3-none-any.whl", hash = "sha256:7d543798b0beca10b6a01ac7cafda9f822c54db9e8376a6bf57e0cbd74d486b6"},
|
||||
{file = "importlib_resources-5.10.2.tar.gz", hash = "sha256:e4a96c8cc0339647ff9a5e0550d9f276fc5a01ffa276012b58ec108cfd7b8484"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""}
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
|
||||
|
||||
[[package]]
|
||||
@ -940,14 +942,14 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "isort"
|
||||
version = "5.11.3"
|
||||
version = "5.11.4"
|
||||
description = "A Python utility / library to sort Python imports."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "isort-5.11.3-py3-none-any.whl", hash = "sha256:83155ffa936239d986b0f190347a3f2285f42a9b9e1725c89d865b27dd0627e5"},
|
||||
{file = "isort-5.11.3.tar.gz", hash = "sha256:a8ca25fbfad0f7d5d8447a4314837298d9f6b23aed8618584c894574f626b64b"},
|
||||
{file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"},
|
||||
{file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@ -988,14 +990,14 @@ i18n = ["Babel (>=2.7)"]
|
||||
|
||||
[[package]]
|
||||
name = "limits"
|
||||
version = "2.7.2"
|
||||
version = "2.8.0"
|
||||
description = "Rate limiting utilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "limits-2.7.2-py3-none-any.whl", hash = "sha256:503a22d3b292fccf1a25f26654fefb44f97d83cb6af37b8996c0e2499df5363b"},
|
||||
{file = "limits-2.7.2.tar.gz", hash = "sha256:159b3c1514af0529854b640f43299aa4a9961b3298e352f4197d9736b8309106"},
|
||||
{file = "limits-2.8.0-py3-none-any.whl", hash = "sha256:ee19e9a98dd392d52dd62cfc28d93710eb29a22cf9834c21c16ee19367c4d596"},
|
||||
{file = "limits-2.8.0.tar.gz", hash = "sha256:b47e01c48b3b677c7230cb51775ebe7c30a574e9711dc68499dab810ed883bb9"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -1162,6 +1164,21 @@ files = [
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-set"
|
||||
version = "4.1.0"
|
||||
description = "An OrderedSet is a custom MutableSet that remembers its order, so that every"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"},
|
||||
{file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["black", "mypy", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "outcome"
|
||||
version = "1.2.0"
|
||||
@ -1288,19 +1305,22 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "2.6.0"
|
||||
version = "2.6.2"
|
||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "platformdirs-2.6.0-py3-none-any.whl", hash = "sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca"},
|
||||
{file = "platformdirs-2.6.0.tar.gz", hash = "sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e"},
|
||||
{file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"},
|
||||
{file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing-extensions = {version = ">=4.4", markers = "python_version < \"3.8\""}
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"]
|
||||
test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
|
||||
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"]
|
||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
@ -2484,26 +2504,26 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "types-redis"
|
||||
version = "4.3.21.6"
|
||||
version = "4.3.21.7"
|
||||
description = "Typing stubs for redis"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "types-redis-4.3.21.6.tar.gz", hash = "sha256:f7969f73a0f79e9e7895f053a06d8b429fb7b5d4fe1269b8ee40463388f653ad"},
|
||||
{file = "types_redis-4.3.21.6-py3-none-any.whl", hash = "sha256:615e5a9142993789ffc22ee54435769b600da3e528bb51cf38430e5cd82af306"},
|
||||
{file = "types-redis-4.3.21.7.tar.gz", hash = "sha256:f9baac41fcafb0b8ec655893feebc5d8bd189da05062d03b4566a16c092fc08c"},
|
||||
{file = "types_redis-4.3.21.7-py3-none-any.whl", hash = "sha256:834e816a84fc570aa96551a9252b0df164ac671bc09e4708e2f8e2b129449ef1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-requests"
|
||||
version = "2.28.11.6"
|
||||
version = "2.28.11.7"
|
||||
description = "Typing stubs for requests"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "types-requests-2.28.11.6.tar.gz", hash = "sha256:8c1b1e6a0b19522b4738063e772dcee82cee1c3646536ccc4eb96f655af2b6c6"},
|
||||
{file = "types_requests-2.28.11.6-py3-none-any.whl", hash = "sha256:48b7c06e3dffc1b6359e1888084a2b97f41b6b63f208c571ddb02ddbc6a892e4"},
|
||||
{file = "types-requests-2.28.11.7.tar.gz", hash = "sha256:0ae38633734990d019b80f5463dfa164ebd3581998ac8435f526da6fe4d598c3"},
|
||||
{file = "types_requests-2.28.11.7-py3-none-any.whl", hash = "sha256:b6a2fca8109f4fdba33052f11ed86102bddb2338519e1827387137fefc66a98b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -2703,4 +2723,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.7"
|
||||
content-hash = "44659aa26f07c74af8d04ca7a5d426cf439e65ad5301386d0f6713d676ab9cd9"
|
||||
content-hash = "a8eb55d8966ea55b1f38a96b410e85bab447cb436efcb208b514bf6cc20a9ef4"
|
||||
|