Merge branch 'release-v0.7.11'

This commit is contained in:
Sam 2022-12-31 18:39:31 +01:00
commit 22631f61e0
101 changed files with 1635 additions and 718 deletions

View File

@ -19,7 +19,7 @@ export DATABASE_TEST_URL=postgresql://fittrackee:fittrackee@fittrackee-db:5432/f
export REDIS_URL=redis://redis:6379 export REDIS_URL=redis://redis:6379
# API rate limits # API rate limits
# export API_RATE_LIMITS=300 per 5 minutes # export API_RATE_LIMITS="300 per 5 minutes"
# Emails # Emails
export UI_URL=http://0.0.0.0:5000 export UI_URL=http://0.0.0.0:5000
@ -31,6 +31,11 @@ export WORKERS_PROCESSES=2
# Workouts # Workouts
# export TILE_SERVER_URL= # export TILE_SERVER_URL=
# export STATICMAP_SUBDOMAINS=
# export MAP_ATTRIBUTION= # export MAP_ATTRIBUTION=
# export DEFAULT_STATICMAP=False # export DEFAULT_STATICMAP=False
# Weather
# available weather API providers: darksky, visualcrossing
# export WEATHER_API_PROVIDER=
# export WEATHER_API_KEY= # export WEATHER_API_KEY=

View File

@ -20,7 +20,7 @@ export UPLOAD_FOLDER=
# export REDIS_URL= # export REDIS_URL=
# API rate limits # API rate limits
# export API_RATE_LIMITS=300 per 5 minutes # export API_RATE_LIMITS="300 per 5 minutes"
# Emails # Emails
export UI_URL= export UI_URL=
@ -33,4 +33,8 @@ export SENDER_EMAIL=
# export STATICMAP_SUBDOMAINS= # export STATICMAP_SUBDOMAINS=
# export MAP_ATTRIBUTION= # export MAP_ATTRIBUTION=
# export DEFAULT_STATICMAP=False # export DEFAULT_STATICMAP=False
# Weather
# available weather API providers: darksky, visualcrossing
# export WEATHER_API_PROVIDER=
# export WEATHER_API_KEY= # export WEATHER_API_KEY=

View File

@ -1,7 +1,28 @@
# Change log # 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) ## Version 0.7.10 (2022/12/21)
FitTrackee is now available in Italian (thanks to @dperruso).
### Features and enhancements ### Features and enhancements
* [#92](https://github.com/SamR1/FitTrackee/issues/92) - Add ascent and descent parameters in workout import without GPX file * [#92](https://github.com/SamR1/FitTrackee/issues/92) - Add ascent and descent parameters in workout import without GPX file

View File

@ -1 +1 @@
0.7.10 0.7.11

View File

@ -1,4 +1,4 @@
# Sphinx build info version 1 # 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. # 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 tags: 645f666f9bcd5a90fca523b33c5a78b7

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 KiB

After

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 KiB

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -1,7 +1,28 @@
# Change log # 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) ## Version 0.7.10 (2022/12/21)
FitTrackee is now available in Italian (thanks to @dperruso).
### Features and enhancements ### Features and enhancements
* [#92](https://github.com/SamR1/FitTrackee/issues/92) - Add ascent and descent parameters in workout import without GPX file * [#92](https://github.com/SamR1/FitTrackee/issues/92) - Add ascent and descent parameters in workout import without GPX file

View File

@ -43,7 +43,7 @@ Workouts
| Ascent and descent can also be provided (*new in 0.7.10*). | 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). - | 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*). | 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*). | 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. - Segments can be displayed.
- Workout gpx file can be downloaded (*new in 0.5.1*) - Workout gpx file can be downloaded (*new in 0.5.1*)

View File

@ -28,7 +28,7 @@ Prerequisites
- optional - optional
- Redis for task queue (if email sending is enabled) and API rate limits - Redis for task queue (if email sending is enabled) and API rate limits
- SMTP provider (if email sending is enabled) - 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) - `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
- `Yarn <https://yarnpkg.com>`__ (for development only) - `Yarn <https://yarnpkg.com>`__ (for development only)
- Docker and Docker Compose (for development or evaluation purposes) - Docker and Docker Compose (for development or evaluation purposes)
@ -172,7 +172,7 @@ deployment method.
Number of processes used by **Dramatiq**. Number of processes used by **Dramatiq**.
.. envvar:: API_RATE_LIMITS 🆕 .. envvar:: API_RATE_LIMITS
.. versionadded:: 0.7.0 .. versionadded:: 0.7.0
@ -229,7 +229,14 @@ deployment method.
.. versionchanged:: 0.4.0 ⚠️ replaces ``WEATHER_API`` .. 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 .. 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. The subdomain will be chosen randomly.
API rate limits 🆕 API rate limits
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
.. versionadded:: 0.7.0 .. 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. | 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 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 Installation
~~~~~~~~~~~~ ~~~~~~~~~~~~
@ -480,13 +502,13 @@ Production environment
.. warning:: .. warning::
| Note that FitTrackee is under heavy development, some features may be unstable. | 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 .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
$ tar -xzf v0.7.10.tar.gz $ tar -xzf v0.7.11.tar.gz
$ mv FitTrackee-0.7.10 FitTrackee $ mv FitTrackee-0.7.11 FitTrackee
$ cd FitTrackee $ cd FitTrackee
- Create **.env** from example and update it - Create **.env** from example and update it
@ -606,13 +628,13 @@ Prod environment
- Change to the directory where FitTrackee directory is located - 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 .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
$ tar -xzf v0.7.10.tar.gz $ tar -xzf v0.7.11.tar.gz
$ cp -R FitTrackee-0.7.10/* FitTrackee/ $ cp -R FitTrackee-0.7.11/* FitTrackee/
$ cd FitTrackee $ cd FitTrackee
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__). - Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).

View File

@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = { var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '0.7.10', VERSION: '0.7.11',
LANGUAGE: 'en', LANGUAGE: 'en',
COLLAPSE_INDEX: false, COLLAPSE_INDEX: false,
BUILDER: 'html', BUILDER: 'html',

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Authentication &#8212; FitTrackee 0.7.10 <title>Authentication &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -1239,7 +1239,7 @@ for other reasons.</p></li>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Configuration &#8212; FitTrackee 0.7.10 <title>Configuration &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -154,8 +154,9 @@
<span class="w"> </span><span class="nt">&quot;max_single_file_size&quot;</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">&quot;max_single_file_size&quot;</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">&quot;max_users&quot;</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">&quot;max_users&quot;</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">&quot;max_zip_file_size&quot;</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">&quot;max_zip_file_size&quot;</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">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="nt">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.7.10&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.7.11&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;weather_provider&quot;</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="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span> <span class="p">}</span><span class="w"></span>
@ -195,8 +196,9 @@
<span class="w"> </span><span class="nt">&quot;max_single_file_size&quot;</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">&quot;max_single_file_size&quot;</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">&quot;max_users&quot;</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">&quot;max_users&quot;</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">&quot;max_zip_file_size&quot;</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">&quot;max_zip_file_size&quot;</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">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="nt">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.7.10&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.7.11&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;weather_provider&quot;</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="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span> <span class="p">}</span><span class="w"></span>
@ -279,7 +281,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <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 &#8212; FitTrackee 0.7.10 <title>API documentation &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -160,7 +160,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>OAuth2 &#8212; FitTrackee 0.7.10 <title>OAuth2 &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -694,7 +694,7 @@ are supported by FitTrackee)</p></li>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Records &#8212; FitTrackee 0.7.10 <title>Records &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -262,7 +262,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Sports &#8212; FitTrackee 0.7.10 <title>Sports &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -492,7 +492,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Statistics &#8212; FitTrackee 0.7.10 <title>Statistics &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -419,7 +419,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Users &#8212; FitTrackee 0.7.10 <title>Users &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -663,7 +663,7 @@ one admin.</p>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Workouts &#8212; FitTrackee 0.7.10 <title>Workouts &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -1187,7 +1187,7 @@ must be provided with ascent)</p></li>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <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 &#8212; FitTrackee 0.7.10 <title>Third-party applications &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -259,7 +259,7 @@ It is recommended to use PKCE to provide a better security.</p>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <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 &#8212; FitTrackee 0.7.10 <title>Command line interface &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -288,7 +288,7 @@ Commands:
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Features &#8212; FitTrackee 0.7.10 <title>Features &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -206,7 +206,7 @@
</div> </div>
</li> </li>
<li><div class="line-block"> <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 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> </div>
</li> </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>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -4,7 +4,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Index &#8212; FitTrackee 0.7.10 <title>Index &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -126,7 +126,7 @@
environment variable environment variable
<ul> <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>
<li><a href="installation.html#envvar-APP_LOG">APP_LOG</a> <li><a href="installation.html#envvar-APP_LOG">APP_LOG</a>
</li> </li>
@ -167,6 +167,8 @@
<li><a href="installation.html#envvar-VUE_APP_API_URL">VUE_APP_API_URL</a> <li><a href="installation.html#envvar-VUE_APP_API_URL">VUE_APP_API_URL</a>
</li> </li>
<li><a href="installation.html#envvar-WEATHER_API_KEY">WEATHER_API_KEY</a> <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>
<li><a href="installation.html#envvar-WORKERS_PROCESSES">WORKERS_PROCESSES</a> <li><a href="installation.html#envvar-WORKERS_PROCESSES">WORKERS_PROCESSES</a>
</li> </li>
@ -188,7 +190,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -4,7 +4,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HTTP Routing Table &#8212; FitTrackee 0.7.10 <title>HTTP Routing Table &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -47,7 +47,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -410,7 +410,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>FitTrackee &#8212; FitTrackee 0.7.10 <title>FitTrackee &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -42,7 +42,7 @@
</button> </button>
<a class="navbar-brand" href="#"> <a class="navbar-brand" href="#">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -180,7 +180,7 @@ Map</a>.</div>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Installation &#8212; FitTrackee 0.7.10 <title>Installation &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -87,7 +87,8 @@
<li><a class="reference internal" href="#environment-variables">Environment variables</a><ul> <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="#emails">Emails</a></li>
<li><a class="reference internal" href="#map-tile-server">Map tile server</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> </ul>
</li> </li>
<li><a class="reference internal" href="#id2">Installation</a><ul> <li><a class="reference internal" href="#id2">Installation</a><ul>
@ -209,7 +210,7 @@
<dt>optional</dt><dd><ul> <dt>optional</dt><dd><ul>
<li><p>Redis for task queue (if email sending is enabled) and API rate limits</p></li> <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>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://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><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> <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"> <dl class="std envvar">
<dt class="sig sig-object std" id="envvar-API_RATE_LIMITS"> <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"> <dd><div class="versionadded">
<p><span class="versionmodified added">New in version 0.7.0.</span></p> <p><span class="versionmodified added">New in version 0.7.0.</span></p>
</div> </div>
@ -518,7 +519,16 @@ see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/p
<dd><div class="versionchanged"> <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> <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> </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> </dd></dl>
<dl class="std envvar"> <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> <p>The subdomain will be chosen randomly.</p>
</section> </section>
<section id="api-rate-limits"> <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"> <div class="versionadded">
<p><span class="versionmodified added">New in version 0.7.0.</span></p> <p><span class="versionmodified added">New in version 0.7.0.</span></p>
</div> </div>
@ -642,6 +652,22 @@ Commands:
</pre></div> </pre></div>
</div> </div>
</section> </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>
<section id="id2"> <section id="id2">
<h2>Installation<a class="headerlink" href="#id2" title="Permalink to this heading"></a></h2> <h2>Installation<a class="headerlink" href="#id2" title="Permalink to this heading"></a></h2>
@ -795,11 +821,11 @@ $ make install-db
</div> </div>
</div> </div>
<ul class="simple"> <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> </ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz <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.10.tar.gz $ tar -xzf v0.7.11.tar.gz
$ mv FitTrackee-0.7.10 FitTrackee $ mv FitTrackee-0.7.11 FitTrackee
$ <span class="nb">cd</span> FitTrackee $ <span class="nb">cd</span> FitTrackee
</pre></div> </pre></div>
</div> </div>
@ -919,11 +945,11 @@ $ <span class="nb">source</span> .env
<ul class="simple"> <ul class="simple">
<li><p>Stop the application</p></li> <li><p>Stop the application</p></li>
<li><p>Change to the directory where FitTrackee directory is located</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> </ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz <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.10.tar.gz $ tar -xzf v0.7.11.tar.gz
$ cp -R FitTrackee-0.7.10/* FitTrackee/ $ cp -R FitTrackee-0.7.11/* FitTrackee/
$ <span class="nb">cd</span> FitTrackee $ <span class="nb">cd</span> FitTrackee
</pre></div> </pre></div>
</div> </div>
@ -1182,7 +1208,7 @@ $ make docker-test-python <span class="c1"># run unit tests on API</span>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

Binary file not shown.

View File

@ -4,7 +4,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Search &#8212; FitTrackee 0.7.10 <title>Search &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -47,7 +47,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -154,7 +154,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Administrator &#8212; FitTrackee 0.7.10 <title>Administrator &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -174,7 +174,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Troubleshooting &#8212; FitTrackee 0.7.10 <title>Troubleshooting &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -157,7 +157,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <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/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>User &#8212; FitTrackee 0.7.10 <title>User &#8212; FitTrackee 0.7.11
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> 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> </b></span>
</div> </div>
@ -148,7 +148,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; 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/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 KiB

After

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 KiB

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -43,7 +43,7 @@ Workouts
| Ascent and descent can also be provided (*new in 0.7.10*). | 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). - | 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*). | 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*). | 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. - Segments can be displayed.
- Workout gpx file can be downloaded (*new in 0.5.1*) - Workout gpx file can be downloaded (*new in 0.5.1*)

View File

@ -28,7 +28,7 @@ Prerequisites
- optional - optional
- Redis for task queue (if email sending is enabled) and API rate limits - Redis for task queue (if email sending is enabled) and API rate limits
- SMTP provider (if email sending is enabled) - 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) - `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
- `Yarn <https://yarnpkg.com>`__ (for development only) - `Yarn <https://yarnpkg.com>`__ (for development only)
- Docker and Docker Compose (for development or evaluation purposes) - Docker and Docker Compose (for development or evaluation purposes)
@ -172,7 +172,7 @@ deployment method.
Number of processes used by **Dramatiq**. Number of processes used by **Dramatiq**.
.. envvar:: API_RATE_LIMITS 🆕 .. envvar:: API_RATE_LIMITS
.. versionadded:: 0.7.0 .. versionadded:: 0.7.0
@ -229,7 +229,14 @@ deployment method.
.. versionchanged:: 0.4.0 ⚠️ replaces ``WEATHER_API`` .. 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 .. 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. The subdomain will be chosen randomly.
API rate limits 🆕 API rate limits
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
.. versionadded:: 0.7.0 .. 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. | 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 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 Installation
~~~~~~~~~~~~ ~~~~~~~~~~~~
@ -480,13 +502,13 @@ Production environment
.. warning:: .. warning::
| Note that FitTrackee is under heavy development, some features may be unstable. | 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 .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
$ tar -xzf v0.7.10.tar.gz $ tar -xzf v0.7.11.tar.gz
$ mv FitTrackee-0.7.10 FitTrackee $ mv FitTrackee-0.7.11 FitTrackee
$ cd FitTrackee $ cd FitTrackee
- Create **.env** from example and update it - Create **.env** from example and update it
@ -606,13 +628,13 @@ Prod environment
- Change to the directory where FitTrackee directory is located - 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 .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.7.11.tar.gz
$ tar -xzf v0.7.10.tar.gz $ tar -xzf v0.7.11.tar.gz
$ cp -R FitTrackee-0.7.10/* FitTrackee/ $ cp -R FitTrackee-0.7.11/* FitTrackee/
$ cd FitTrackee $ cd FitTrackee
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__). - Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).

View File

@ -25,7 +25,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
from fittrackee.emails.email import EmailService from fittrackee.emails.email import EmailService
from fittrackee.request import CustomRequest from fittrackee.request import CustomRequest
VERSION = __version__ = '0.7.10' VERSION = __version__ = '0.7.11'
REDIS_URL = os.getenv('REDIS_URL', 'redis://') REDIS_URL = os.getenv('REDIS_URL', 'redis://')
API_RATE_LIMITS = os.environ.get('API_RATE_LIMITS', '300 per 5 minutes').split( API_RATE_LIMITS = os.environ.get('API_RATE_LIMITS', '300 per 5 minutes').split(
',' ','

View File

@ -47,8 +47,9 @@ def get_application_config() -> Union[Dict, HttpResponse]:
"max_single_file_size": 1048576, "max_single_file_size": 1048576,
"max_users": 0, "max_users": 0,
"max_zip_file_size": 10485760, "max_zip_file_size": 10485760,
"map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors" "map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors",
"version": "0.7.10" "version": "0.7.11",
"weather_provider": null
}, },
"status": "success" "status": "success"
} }
@ -99,8 +100,9 @@ def update_application_config(auth_user: User) -> Union[Dict, HttpResponse]:
"max_single_file_size": 1048576, "max_single_file_size": 1048576,
"max_users": 10, "max_users": 10,
"max_zip_file_size": 10485760, "max_zip_file_size": 10485760,
"map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors" "map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors",
"version": "0.7.10" "version": "0.7.11",
"weather_provider": null
}, },
"status": "success" "status": "success"
} }

View File

@ -1,3 +1,4 @@
import os
from typing import Dict from typing import Dict
from flask import current_app from flask import current_app
@ -43,6 +44,7 @@ class AppConfig(BaseModel):
return current_app.config['TILE_SERVER']['ATTRIBUTION'] return current_app.config['TILE_SERVER']['ATTRIBUTION']
def serialize(self) -> Dict: def serialize(self) -> Dict:
weather_provider = os.getenv('WEATHER_API_PROVIDER', '').lower()
return { return {
'admin_contact': self.admin_contact, 'admin_contact': self.admin_contact,
'gpx_limit_import': self.gpx_limit_import, 'gpx_limit_import': self.gpx_limit_import,
@ -53,6 +55,11 @@ class AppConfig(BaseModel):
'max_users': self.max_users, 'max_users': self.max_users,
'map_attribution': self.map_attribution, 'map_attribution': self.map_attribution,
'version': VERSION, 'version': VERSION,
'weather_provider': (
weather_provider
if weather_provider in ['darksky', 'visualcrossing']
else None
),
} }

View File

@ -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>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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}}]); "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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,4 @@
import pytest
from flask import Flask from flask import Flask
from fittrackee import VERSION from fittrackee import VERSION
@ -6,7 +7,10 @@ from fittrackee.users.models import User
class TestConfigModel: 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 = AppConfig.query.first()
app_config.admin_contact = 'admin@example.com' app_config.admin_contact = 'admin@example.com'
@ -40,6 +44,7 @@ class TestConfigModel:
== app_config.map_attribution == app_config.map_attribution
) )
assert serialized_app_config['version'] == VERSION assert serialized_app_config['version'] == VERSION
assert serialized_app_config['weather_provider'] == 'darksky'
def test_it_returns_registration_disabled_when_users_count_exceeds_limit( def test_it_returns_registration_disabled_when_users_count_exceeds_limit(
self, app: Flask, user_1: User, user_2: User self, app: Flask, user_1: User, user_2: User
@ -58,3 +63,28 @@ class TestConfigModel:
serialized_app_config = app_config.serialize() serialized_app_config = app_config.serialize()
assert serialized_app_config['is_email_sending_enabled'] is False 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
)

View File

@ -1,6 +1,7 @@
import os import os
import shutil import shutil
from typing import Generator, Optional, Union from typing import Generator, Iterator, Optional, Union
from unittest.mock import patch
import pytest import pytest
from flask import current_app from flask import current_app
@ -8,6 +9,13 @@ from flask import current_app
from fittrackee import create_app, db, limiter from fittrackee import create_app, db, limiter
from fittrackee.application.models import AppConfig from fittrackee.application.models import AppConfig
from fittrackee.application.utils import update_app_config_from_database 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( def get_app_config(
@ -82,7 +90,6 @@ def get_app(
@pytest.fixture @pytest.fixture
def app(monkeypatch: pytest.MonkeyPatch) -> Generator: def app(monkeypatch: pytest.MonkeyPatch) -> Generator:
monkeypatch.setenv('EMAIL_URL', 'smtp://none:none@0.0.0.0:1025') monkeypatch.setenv('EMAIL_URL', 'smtp://none:none@0.0.0.0:1025')
monkeypatch.setenv('WEATHER_API_KEY', '')
if os.getenv('TILE_SERVER_URL'): if os.getenv('TILE_SERVER_URL'):
monkeypatch.delenv('TILE_SERVER_URL') monkeypatch.delenv('TILE_SERVER_URL')
if os.getenv('STATICMAP_SUBDOMAINS'): if os.getenv('STATICMAP_SUBDOMAINS'):

View 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

View File

@ -4,7 +4,9 @@ from typing import Any, Dict, List, Optional, Tuple, Union
import gpxpy.gpx import gpxpy.gpx
from ..exceptions import WorkoutGPXException 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]: def open_gpx_file(gpx_file: str) -> Optional[gpxpy.gpx.GPX]:
@ -99,7 +101,7 @@ def get_gpx_info(
if start is None: if start is None:
start = point.time start = point.time
if point.time and update_weather_data: 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 # if a previous segment exists, calculate stopped time between
# the two segments # the two segments
@ -114,7 +116,7 @@ def get_gpx_info(
# last gpx point => get weather # last gpx point => get weather
if segment_idx == (segments_nb - 1) and update_weather_data: 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: if update_map_data:
map_data.append([point.longitude, point.latitude]) map_data.append([point.longitude, point.latitude])

View File

@ -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

View File

@ -0,0 +1,5 @@
from .weather_service import WeatherService
__all__ = [
'WeatherService',
]

View 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)

View 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,
}

View 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

View 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

View File

@ -1,6 +1,6 @@
{ {
"name": "fittrackee_client", "name": "fittrackee_client",
"version": "0.7.10", "version": "0.7.11",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
@ -11,7 +11,7 @@
"i18n:report": "vue-cli-service i18n:report --src \"./src/**/*.?(js|vue)\" --locales \"./src/locales/**/*.json\"" "i18n:report": "vue-cli-service i18n:report --src \"./src/**/*.?(js|vue)\" --locales \"./src/locales/**/*.json\""
}, },
"dependencies": { "dependencies": {
"@tmcw/togeojson": "^5.5.0", "@tmcw/togeojson": "^5.6.0",
"@vue-leaflet/vue-leaflet": "^0.7.0", "@vue-leaflet/vue-leaflet": "^0.7.0",
"@zxcvbn-ts/core": "^2.0.5", "@zxcvbn-ts/core": "^2.0.5",
"@zxcvbn-ts/language-common": "^2.0.1", "@zxcvbn-ts/language-common": "^2.0.1",
@ -22,14 +22,14 @@
"axios": "^1.2.1", "axios": "^1.2.1",
"chart.js": "^4.1.1", "chart.js": "^4.1.1",
"chartjs-plugin-datalabels": "^2.2.0", "chartjs-plugin-datalabels": "^2.2.0",
"core-js": "^3.26.1", "core-js": "^3.27.1",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"date-fns-tz": "^1.3.7", "date-fns-tz": "^1.3.7",
"leaflet": "^1.9.3", "leaflet": "^1.9.3",
"linkify-html": "^4.0.2", "linkify-html": "^4.0.2",
"linkifyjs": "^4.0.2", "linkifyjs": "^4.0.2",
"register-service-worker": "^1.7.1", "register-service-worker": "^1.7.1",
"sanitize-html": "^2.8.0", "sanitize-html": "^2.8.1",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-chart-3": "3.1.1", "vue-chart-3": "3.1.1",
"vue-fullscreen": "^3.1.1", "vue-fullscreen": "^3.1.1",
@ -42,8 +42,8 @@
"@types/chai": "^4.3.4", "@types/chai": "^4.3.4",
"@types/mocha": "^10.0.1", "@types/mocha": "^10.0.1",
"@types/sanitize-html": "^2.8.0", "@types/sanitize-html": "^2.8.0",
"@typescript-eslint/eslint-plugin": "^5.47.0", "@typescript-eslint/eslint-plugin": "^5.47.1",
"@typescript-eslint/parser": "^5.47.0", "@typescript-eslint/parser": "^5.47.1",
"@vue/cli-plugin-babel": "~5.0.8", "@vue/cli-plugin-babel": "~5.0.8",
"@vue/cli-plugin-eslint": "~5.0.8", "@vue/cli-plugin-eslint": "~5.0.8",
"@vue/cli-plugin-pwa": "~5.0.8", "@vue/cli-plugin-pwa": "~5.0.8",
@ -55,7 +55,7 @@
"@vue/eslint-config-typescript": "^11.0.2", "@vue/eslint-config-typescript": "^11.0.2",
"@vue/test-utils": "^2.2.6", "@vue/test-utils": "^2.2.6",
"chai": "^4.3.7", "chai": "^4.3.7",
"eslint": "8.30.0", "eslint": "8.31.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-typescript": "^3.5.2", "eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",

View File

@ -40,6 +40,12 @@
{{ $t('about.CONTACT_ADMIN') }} {{ $t('about.CONTACT_ADMIN') }}
</a> </a>
</div> </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>
</div> </div>
</template> </template>
@ -55,6 +61,22 @@
const appConfig: ComputedRef<TAppConfig> = computed( const appConfig: ComputedRef<TAppConfig> = computed(
() => store.getters[ROOT_STORE.GETTERS.APP_CONFIG] () => 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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,13 +1,6 @@
<template> <template>
<div class="wind"> <div class="wind">
<Distance {{ getWindSpeed(weather.wind, useImperialUnits) }}
:distance="weather.wind"
unitFrom="m"
:digits="1"
:displayUnit="false"
:useImperialUnits="useImperialUnits"
/>
{{ useImperialUnits ? 'ft' : 'm' }}/s
<div class="wind-bearing"> <div class="wind-bearing">
<i <i
v-if="weather.windBearing" v-if="weather.windBearing"
@ -27,6 +20,7 @@
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { IWeather } from '@/types/workouts' import { IWeather } from '@/types/workouts'
import { getWindSpeed } from '@/utils/units'
import { convertDegreeToDirection } from '@/utils/weather' import { convertDegreeToDirection } from '@/utils/weather'
interface Props { interface Props {

View File

@ -58,10 +58,20 @@
/> />
</td> </td>
<td> <td>
{{ Number(workoutObject.weatherStart.temperature).toFixed(1) }}°C {{
getTemperature(
workoutObject.weatherStart.temperature,
useImperialUnits
)
}}
</td> </td>
<td> <td>
{{ Number(workoutObject.weatherEnd.temperature).toFixed(1) }}°C {{
getTemperature(
workoutObject.weatherEnd.temperature,
useImperialUnits
)
}}
</td> </td>
</tr> </tr>
<tr> <tr>
@ -112,6 +122,7 @@
import WeatherWind from '@/components/Workout/WorkoutDetail/WeatherWind.vue' import WeatherWind from '@/components/Workout/WorkoutDetail/WeatherWind.vue'
import { IWorkoutObject } from '@/types/workouts' import { IWorkoutObject } from '@/types/workouts'
import { getTemperature } from '@/utils/units'
interface Props { interface Props {
workoutObject: IWorkoutObject workoutObject: IWorkoutObject

View File

@ -94,9 +94,9 @@
}, },
"TIMEZONE": "Zeitzone", "TIMEZONE": "Zeitzone",
"UNITS": { "UNITS": {
"IMPERIAL": "Imperiales System (ft, mi)", "IMPERIAL": "Imperiales System (ft, mi, mph, °F)",
"LABEL": "Einheiten für die Distanz", "LABEL": "Einheiten für die Distanz",
"METRIC": "Metrisches System (m, km)" "METRIC": "Metrisches System (m, km, m/s, °C)"
} }
}, },
"REGISTER": "Registrieren", "REGISTER": "Registrieren",

View File

@ -16,6 +16,7 @@
"FROM": "Von", "FROM": "Von",
"GPX_FILE": ".gpx Datei", "GPX_FILE": ".gpx Datei",
"HIDE_FILTERS": "verberge Filter", "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_DISTANCE": "Die Distanz muss größer als 0 sein",
"INVALID_DURATION": "Die Dauer muss größer als 0 Sekunden sein", "INVALID_DURATION": "Die Dauer muss größer als 0 Sekunden sein",
"LATEST_WORKOUTS": "Letzte Trainings", "LATEST_WORKOUTS": "Letzte Trainings",

View File

@ -2,5 +2,6 @@
"CONTACT_ADMIN": "Contact the administrator", "CONTACT_ADMIN": "Contact the administrator",
"FITTRACKEE_DESCRIPTION": "<strong>FitTrackee</strong> is a self-hosted outdoor activity tracker.", "FITTRACKEE_DESCRIPTION": "<strong>FitTrackee</strong> is a self-hosted outdoor activity tracker.",
"FITTRACKEE_LICENSE": "under {0} license ", "FITTRACKEE_LICENSE": "under {0} license ",
"SOURCE_CODE": "Source code" "SOURCE_CODE": "Source code",
"WEATHER_DATA_FROM": "Weather data from:"
} }

View File

@ -94,9 +94,9 @@
}, },
"TIMEZONE": "Timezone", "TIMEZONE": "Timezone",
"UNITS": { "UNITS": {
"IMPERIAL": "Imperial system (ft, mi)", "IMPERIAL": "Imperial system (ft, mi, mph, °F)",
"LABEL": "Units for distance", "LABEL": "Units for distance",
"METRIC": "Metric system (m, km)" "METRIC": "Metric system (m, km, m/s, °C)"
} }
}, },
"REGISTER": "Register", "REGISTER": "Register",
@ -108,4 +108,4 @@
"USERNAME": "Username", "USERNAME": "Username",
"USERNAME_INFO": "3 to 30 characters required, only alphanumeric characters and the underscore character \"_\" allowed.", "USERNAME_INFO": "3 to 30 characters required, only alphanumeric characters and the underscore character \"_\" allowed.",
"USER_PICTURE": "user picture" "USER_PICTURE": "user picture"
} }

View File

@ -2,5 +2,6 @@
"CONTACT_ADMIN": "Contacter l'administrateur", "CONTACT_ADMIN": "Contacter l'administrateur",
"FITTRACKEE_DESCRIPTION": "<strong>FitTrackee</strong> est un <em>tracker</em> d'activités sportives (en extérieur).", "FITTRACKEE_DESCRIPTION": "<strong>FitTrackee</strong> est un <em>tracker</em> d'activités sportives (en extérieur).",
"FITTRACKEE_LICENSE": "sous licence {0} (en) ", "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 :"
} }

View File

@ -94,9 +94,9 @@
}, },
"TIMEZONE": "Fuseau horaire", "TIMEZONE": "Fuseau horaire",
"UNITS": { "UNITS": {
"IMPERIAL": "Système impérial (ft, mi)", "IMPERIAL": "Système impérial (ft, mi, mph, °F)",
"LABEL": "Unités pour les distances", "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", "REGISTER": "S'inscrire",
@ -108,4 +108,4 @@
"USERNAME": "Nom d'utilisateur", "USERNAME": "Nom d'utilisateur",
"USERNAME_INFO": "3 à 30 caractères requis, seuls les caractères alphanumériques et le caractère _ sont autorisés.", "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" "USER_PICTURE": "photo de l'utilisateur"
} }

View File

@ -94,9 +94,9 @@
}, },
"TIMEZONE": "Timezone", "TIMEZONE": "Timezone",
"UNITS": { "UNITS": {
"IMPERIAL": "Sistema imperiale (ft, mi)", "IMPERIAL": "Sistema imperiale (ft, mi, mph, °F)",
"LABEL": "Unità per la distanza", "LABEL": "Unità per la distanza",
"METRIC": "Sistema metrico (m, km)" "METRIC": "Sistema metrico (m, km, m/s, °C)"
} }
}, },
"REGISTER": "Registra", "REGISTER": "Registra",

View File

@ -13,6 +13,6 @@
"NO": "Nee", "NO": "Nee",
"REGISTER": "Registreer", "REGISTER": "Registreer",
"RESET": "Reset", "RESET": "Reset",
"SUBMIT": "Aanpassen", "SUBMIT": "Uploaden",
"YES": "Ja" "YES": "Ja"
} }

View File

@ -94,9 +94,9 @@
}, },
"TIMEZONE": "Tijdzone", "TIMEZONE": "Tijdzone",
"UNITS": { "UNITS": {
"IMPERIAL": "Imperialistisch systeem (ft, mi)", "IMPERIAL": "Imperialistisch systeem (ft, mi, mph, °F)",
"LABEL": "Eenheid voor afstand", "LABEL": "Eenheid voor afstand",
"METRIC": "Metrisch systeem (m, km)" "METRIC": "Metrisch systeem (m, km, m/s, °C)"
} }
}, },
"REGISTER": "Registreren", "REGISTER": "Registreren",

View File

@ -16,6 +16,7 @@
"FROM": "van", "FROM": "van",
"GPX_FILE": ".gpx bestand", "GPX_FILE": ".gpx bestand",
"HIDE_FILTERS": "verberg filters", "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_DISTANCE": "De afstand moet groter zijn dan 0",
"INVALID_DURATION": "De duur moet langer zijn dan 0 seconden", "INVALID_DURATION": "De duur moet langer zijn dan 0 seconden",
"LATEST_WORKOUTS": "Laatste trainingen", "LATEST_WORKOUTS": "Laatste trainingen",

View File

@ -6,7 +6,7 @@ export interface IAppStatistics {
} }
export type TAppConfig = { export type TAppConfig = {
[key: string]: number | boolean | string [key: string]: number | boolean | string | null
admin_contact: string admin_contact: string
gpx_limit_import: number gpx_limit_import: number
is_email_sending_enabled: boolean is_email_sending_enabled: boolean
@ -16,6 +16,7 @@ export type TAppConfig = {
max_users: number max_users: number
max_zip_file_size: number max_zip_file_size: number
version: string version: string
weather_provider: string | null
} }
export interface IApplication { export interface IApplication {

View File

@ -63,3 +63,23 @@ export const convertStatsDistance = (
const unitTo = useImperialUnits ? units[unitFrom].defaultTarget : unitFrom const unitTo = useImperialUnits ? units[unitFrom].defaultTarget : unitFrom
return useImperialUnits ? convertDistance(value, unitFrom, unitTo, 2) : value 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}`
}

View File

@ -1,7 +1,7 @@
import { assert } from 'chai' import { assert } from 'chai'
import { TUnit } from '@/types/units' import { TUnit } from '@/types/units'
import { convertDistance } from '@/utils/units' import { convertDistance, getTemperature, getWindSpeed } from '@/utils/units'
describe('convertDistance', () => { describe('convertDistance', () => {
const testsParams: [number, TUnit, TUnit, number][] = [ 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])
})
})
})

View File

@ -963,10 +963,10 @@
"@babel/helper-validator-identifier" "^7.19.1" "@babel/helper-validator-identifier" "^7.19.1"
to-fast-properties "^2.0.0" to-fast-properties "^2.0.0"
"@eslint/eslintrc@^1.4.0": "@eslint/eslintrc@^1.4.1":
version "1.4.0" version "1.4.1"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.0.tgz#8ec64e0df3e7a1971ee1ff5158da87389f167a63" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e"
integrity sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A== integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==
dependencies: dependencies:
ajv "^6.12.4" ajv "^6.12.4"
debug "^4.3.2" debug "^4.3.2"
@ -1251,10 +1251,10 @@
magic-string "^0.25.0" magic-string "^0.25.0"
string.prototype.matchall "^4.0.6" string.prototype.matchall "^4.0.6"
"@tmcw/togeojson@^5.5.0": "@tmcw/togeojson@^5.6.0":
version "5.5.0" version "5.6.0"
resolved "https://registry.yarnpkg.com/@tmcw/togeojson/-/togeojson-5.5.0.tgz#874081d1b3df1e51a6c5e878dd8f4cdf06a3ac48" resolved "https://registry.yarnpkg.com/@tmcw/togeojson/-/togeojson-5.6.0.tgz#a6c96971acdf36eef73a1c398cf19a565eb02831"
integrity sha512-K/neYsnwGkC1sjI0UInSyuxybPsBPXZF+g18l7XtzW37Jfzzcw4YjMd/rnqP5QRONtjuvGN6nGeCemKfeWkPGg== integrity sha512-p+c0kbSY/tIwd3C0rpmTf3iFAOUYV6bkJbDiq0oQDGROOc7c6uh/X8r/mijY6SIFYIkVuKc8MS2REKhur2e6Jw==
"@tootallnate/once@2": "@tootallnate/once@2":
version "2.0.0" version "2.0.0"
@ -1489,7 +1489,7 @@
dependencies: dependencies:
"@types/node" "*" "@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" version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.0.tgz#dadb79df3b0499699b155839fd6792f16897d910" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.0.tgz#dadb79df3b0499699b155839fd6792f16897d910"
integrity sha512-AHZtlXAMGkDmyLuLZsRpH3p4G/1iARIwc/T0vIem2YB+xW6pZaXYXzCBnZSF/5fdM97R9QqZWZ+h3iW10XgevQ== integrity sha512-AHZtlXAMGkDmyLuLZsRpH3p4G/1iARIwc/T0vIem2YB+xW6pZaXYXzCBnZSF/5fdM97R9QqZWZ+h3iW10XgevQ==
@ -1504,7 +1504,22 @@
semver "^7.3.7" semver "^7.3.7"
tsutils "^3.21.0" 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" version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.0.tgz#62e83de93499bf4b500528f74bf2e0554e3a6c8d" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.0.tgz#62e83de93499bf4b500528f74bf2e0554e3a6c8d"
integrity sha512-udPU4ckK+R1JWCGdQC4Qa27NtBg7w020ffHqGyAK8pAgOVuNw7YaKXGChk+udh+iiGIJf6/E/0xhVXyPAbsczw== integrity sha512-udPU4ckK+R1JWCGdQC4Qa27NtBg7w020ffHqGyAK8pAgOVuNw7YaKXGChk+udh+iiGIJf6/E/0xhVXyPAbsczw==
@ -1514,6 +1529,16 @@
"@typescript-eslint/typescript-estree" "5.47.0" "@typescript-eslint/typescript-estree" "5.47.0"
debug "^4.3.4" 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": "@typescript-eslint/scope-manager@5.47.0":
version "5.47.0" version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.0.tgz#f58144a6b0ff58b996f92172c488813aee9b09df" 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/types" "5.47.0"
"@typescript-eslint/visitor-keys" "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": "@typescript-eslint/type-utils@5.47.0":
version "5.47.0" version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.0.tgz#2b440979c574e317d3473225ae781f292c99e55d" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.0.tgz#2b440979c574e317d3473225ae781f292c99e55d"
@ -1532,11 +1565,26 @@
debug "^4.3.4" debug "^4.3.4"
tsutils "^3.21.0" 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": "@typescript-eslint/types@5.47.0":
version "5.47.0" version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.0.tgz#67490def406eaa023dbbd8da42ee0d0c9b5229d3" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.0.tgz#67490def406eaa023dbbd8da42ee0d0c9b5229d3"
integrity sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg== 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": "@typescript-eslint/typescript-estree@5.47.0":
version "5.47.0" version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.0.tgz#ed971a11c5c928646d6ba7fc9dfdd6e997649aca" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.0.tgz#ed971a11c5c928646d6ba7fc9dfdd6e997649aca"
@ -1550,6 +1598,19 @@
semver "^7.3.7" semver "^7.3.7"
tsutils "^3.21.0" 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": "@typescript-eslint/utils@5.47.0":
version "5.47.0" version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.0.tgz#b5005f7d2696769a1fdc1e00897005a25b3a0ec7" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.0.tgz#b5005f7d2696769a1fdc1e00897005a25b3a0ec7"
@ -1564,6 +1625,20 @@
eslint-utils "^3.0.0" eslint-utils "^3.0.0"
semver "^7.3.7" 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": "@typescript-eslint/visitor-keys@5.47.0":
version "5.47.0" version "5.47.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.0.tgz#4aca4efbdf6209c154df1f7599852d571b80bb45" 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" "@typescript-eslint/types" "5.47.0"
eslint-visitor-keys "^3.3.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": "@ungap/promise-all-settled@1.1.2":
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" 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" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== 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" version "3.26.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e"
integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA== integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==
@ -3788,12 +3876,12 @@ eslint-webpack-plugin@^3.1.0:
normalize-path "^3.0.0" normalize-path "^3.0.0"
schema-utils "^4.0.0" schema-utils "^4.0.0"
eslint@8.30.0: eslint@8.31.0:
version "8.30.0" version "8.31.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.31.0.tgz#75028e77cbcff102a9feae1d718135931532d524"
integrity sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ== integrity sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==
dependencies: dependencies:
"@eslint/eslintrc" "^1.4.0" "@eslint/eslintrc" "^1.4.1"
"@humanwhocodes/config-array" "^0.11.8" "@humanwhocodes/config-array" "^0.11.8"
"@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/module-importer" "^1.0.1"
"@nodelib/fs.walk" "^1.2.8" "@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" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sanitize-html@^2.8.0: sanitize-html@^2.8.1:
version "2.8.0" version "2.8.1"
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.8.0.tgz#651d1d0e5b2d61b4ec6147cc46f6d6680eef98ce" resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.8.1.tgz#319c4fdba67e1edf35b1fd6d9362210044826d47"
integrity sha512-ZsGyc6avnqgvEm3eMKrcy8xa7WM1MrGrfkGsUgQee2CU+vg3PCfNCexXwBDF/6dEPvaQ4k/QqRjnYKHL8xgNjg== integrity sha512-qK5neD0SaMxGwVv5txOYv05huC3o6ZAA4h5+7nJJgWMNFUNRjcjLO6FpwAtKzfKCZ0jrG6xTk6eVFskbvOGblg==
dependencies: dependencies:
deepmerge "^4.2.2" deepmerge "^4.2.2"
escape-string-regexp "^4.0.0" escape-string-regexp "^4.0.0"

210
poetry.lock generated
View File

@ -14,14 +14,14 @@ files = [
[[package]] [[package]]
name = "alembic" name = "alembic"
version = "1.9.0" version = "1.9.1"
description = "A database migration tool for SQLAlchemy." description = "A database migration tool for SQLAlchemy."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "alembic-1.9.0-py3-none-any.whl", hash = "sha256:e8ce855f731d92cfdbf9a71d148401fcc420399927817c6e2c0b6a5f31db745d"}, {file = "alembic-1.9.1-py3-none-any.whl", hash = "sha256:a9781ed0979a20341c2cbb56bd22bd8db4fc1913f955e705444bd3a97c59fa32"},
{file = "alembic-1.9.0.tar.gz", hash = "sha256:6af6792fe699730b27480382701b16028ebbaac6bc5cd4f06daf5fa3e4690364"}, {file = "alembic-1.9.1.tar.gz", hash = "sha256:f9f76e41061f5ebe27d4fe92600df9dd612521a7683f904dab328ba02cffa5a2"},
] ]
[package.dependencies] [package.dependencies]
@ -62,21 +62,22 @@ typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""}
[[package]] [[package]]
name = "attrs" name = "attrs"
version = "22.1.0" version = "22.2.0"
description = "Classes Without Boilerplate" description = "Classes Without Boilerplate"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.5" python-versions = ">=3.6"
files = [ files = [
{file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"},
{file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"},
] ]
[package.extras] [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"] cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"]
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] dev = ["attrs[docs,tests]"]
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "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"] 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]] [[package]]
name = "authlib" name = "authlib"
@ -352,63 +353,63 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
[[package]] [[package]]
name = "coverage" name = "coverage"
version = "7.0.0" version = "7.0.1"
description = "Code coverage measurement for Python" description = "Code coverage measurement for Python"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "coverage-7.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f2569682d6ea9628da8d6ba38579a48b1e53081226ec7a6c82b5024b3ce5009f"}, {file = "coverage-7.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b3695c4f4750bca943b3e1f74ad4be8d29e4aeab927d50772c41359107bd5d5c"},
{file = "coverage-7.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ec256a592b497f26054195f7d7148892aca8c4cdcc064a7cc66ef7a0455b811"}, {file = "coverage-7.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fa6a5a224b7f4cfb226f4fc55a57e8537fcc096f42219128c2c74c0e7d0953e1"},
{file = "coverage-7.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5885a4ceb6dde34271bb0adafa4a248a7f589c89821e9da3110c39f92f41e21b"}, {file = "coverage-7.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74f70cd92669394eaf8d7756d1b195c8032cf7bbbdfce3bc489d4e15b3b8cf73"},
{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.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b66bb21a23680dee0be66557dc6b02a3152ddb55edf9f6723fa4a93368f7158d"},
{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.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.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f6a4bf5bdee93f6817797beba7086292c2ebde6df0d5822e0c33f8b05415c339"}, {file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:854f22fa361d1ff914c7efa347398374cc7d567bdafa48ac3aa22334650dfba2"},
{file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:33efe89cd0efef016db19d8d05aa46631f76793de90a61b6717acb202b36fe60"}, {file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1e414dc32ee5c3f36544ea466b6f52f28a7af788653744b8570d0bf12ff34bc0"},
{file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96b5b1f1079e48f56bfccf103bcf44d48b9eb5163f1ea523fad580f15d3fe5e0"}, {file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6c5ad996c6fa4d8ed669cfa1e8551348729d008a2caf81489ab9ea67cfbc7498"},
{file = "coverage-7.0.0-cp310-cp310-win32.whl", hash = "sha256:fb85b7a7a4b204bd59d6d0b0c8d87d9ffa820da225e691dfaffc3137dc05b5f6"}, {file = "coverage-7.0.1-cp310-cp310-win32.whl", hash = "sha256:691571f31ace1837838b7e421d3a09a8c00b4aac32efacb4fc9bd0a5c647d25a"},
{file = "coverage-7.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:793dcd9d42035746fc7637df4336f7581df19d33c5c5253cf988c99d8e93a8ba"}, {file = "coverage-7.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:89caf4425fe88889e2973a8e9a3f6f5f9bbe5dd411d7d521e86428c08a873a4a"},
{file = "coverage-7.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d564142a03d3bc8913499a458e931b52ddfe952f69b6cd4b24d810fd2959044a"}, {file = "coverage-7.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:63d56165a7c76265468d7e0c5548215a5ba515fc2cba5232d17df97bffa10f6c"},
{file = "coverage-7.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0a8b0e86bede874bf5da566b02194fbb12dd14ce3585cabd58452007f272ba81"}, {file = "coverage-7.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f943a3b2bc520102dd3e0bb465e1286e12c9a54f58accd71b9e65324d9c7c01"},
{file = "coverage-7.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e645c73cbfc4577d93747d3f793115acf6f907a7eb9208fa807fdcf2da1964a4"}, {file = "coverage-7.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:830525361249dc4cd013652b0efad645a385707a5ae49350c894b67d23fbb07c"},
{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.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd1b9c5adc066db699ccf7fa839189a649afcdd9e02cb5dc9d24e67e7922737d"},
{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.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.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:db8141856dc9be0917413df7200f53accf1d84c8b156868e6af058a1ea8e903a"}, {file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6d55d840e1b8c0002fce66443e124e8581f30f9ead2e54fbf6709fb593181f2c"},
{file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:59e71912c7fc78d08a567ee65656123878f49ca1b5672e660ea70bf8dfbebf8f"}, {file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:66b18c3cf8bbab0cce0d7b9e4262dc830e93588986865a8c78ab2ae324b3ed56"},
{file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b8f7cd942dda3795fc9eadf303cc53a422ac057e3b70c2ad6d4276ec6a83a541"}, {file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:12a5aa77783d49e05439fbe6e6b427484f8a0f9f456b46a51d8aac022cfd024d"},
{file = "coverage-7.0.0-cp311-cp311-win32.whl", hash = "sha256:bf437a04b9790d3c9cd5b48e9ce9aa84229040e3ae7d6c670a55118906113c5a"}, {file = "coverage-7.0.1-cp311-cp311-win32.whl", hash = "sha256:b77015d1cb8fe941be1222a5a8b4e3fbca88180cfa7e2d4a4e58aeabadef0ab7"},
{file = "coverage-7.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:a7e1bb36b4e57a2d304322021b35d4e4a25fa0d501ba56e8e51efaebf4480556"}, {file = "coverage-7.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb992c47cb1e5bd6a01e97182400bcc2ba2077080a17fcd7be23aaa6e572e390"},
{file = "coverage-7.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:215f40ef86f1958a1151fa7fad2b4f2f99534c4e10a34a1e065eba3f19ef8868"}, {file = "coverage-7.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e78e9dcbf4f3853d3ae18a8f9272111242531535ec9e1009fa8ec4a2b74557dc"},
{file = "coverage-7.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae088eb1cbdad8206931b1bf3f11dee644e038a9300be84d3e705e29356e5b1d"}, {file = "coverage-7.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60bef2e2416f15fdc05772bf87db06c6a6f9870d1db08fdd019fbec98ae24a9"},
{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.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9823e4789ab70f3ec88724bba1a203f2856331986cd893dedbe3e23a6cfc1e4e"},
{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.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.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9fadd15f9fcfd7b16d9cccce9f5e6ec6f9b8df860633ad9aa62c2b14c259560f"}, {file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:486ee81fa694b4b796fc5617e376326a088f7b9729c74d9defa211813f3861e4"},
{file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:10b6246cae61896ab4c7568e498e492cbb73a2dfa4c3af79141c43cf806f929a"}, {file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1285648428a6101b5f41a18991c84f1c3959cee359e51b8375c5882fc364a13f"},
{file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a8785791c2120af114ea7a06137f7778632e568a5aa2bbfc3b46c573b702af74"}, {file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2c44fcfb3781b41409d0f060a4ed748537557de9362a8a9282182fafb7a76ab4"},
{file = "coverage-7.0.0-cp37-cp37m-win32.whl", hash = "sha256:30220518dd89c4878908d73f5f3d1269f86e9e045354436534587a18c7b9da85"}, {file = "coverage-7.0.1-cp37-cp37m-win32.whl", hash = "sha256:d6814854c02cbcd9c873c0f3286a02e3ac1250625cca822ca6bc1018c5b19f1c"},
{file = "coverage-7.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bc904aa96105d73357de03de76336b1e3db28e2b12067d36625fd9646ab043fd"}, {file = "coverage-7.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f66460f17c9319ea4f91c165d46840314f0a7c004720b20be58594d162a441d8"},
{file = "coverage-7.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2331b7bd84a1be79bd17ca8e103ce38db8cbf7cb354dc56e651ba489cf849212"}, {file = "coverage-7.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b373c9345c584bb4b5f5b8840df7f4ab48c4cbb7934b58d52c57020d911b856"},
{file = "coverage-7.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e907db8bdd0ad1253a33c20fdc5f0f6209d271114a9c6f1fcdf96617343f7ca0"}, {file = "coverage-7.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d3022c3007d3267a880b5adcf18c2a9bf1fc64469b394a804886b401959b8742"},
{file = "coverage-7.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0deee68e0dae1d6e3fe6943c76d7e66fbeb6519bd08e4e5366bcc28a8a9aca"}, {file = "coverage-7.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92651580bd46519067e36493acb394ea0607b55b45bd81dd4e26379ed1871f55"},
{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.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cfc595d2af13856505631be072835c59f1acf30028d1c860b435c5fc9c15b69"},
{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.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.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:100546219af59d2ad82d4575de03a303eb27b75ea36ffbd1677371924d50bcbc"}, {file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b6f22bb64cc39bcb883e5910f99a27b200fdc14cdd79df8696fa96b0005c9444"},
{file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c1ba6e63b831112b9484ff5905370d89e43d4316bac76d403031f60d61597466"}, {file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72d1507f152abacea81f65fee38e4ef3ac3c02ff8bc16f21d935fd3a8a4ad910"},
{file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c685fc17d6f4f1a3833e9dac27d0b931f7ccb52be6c30d269374203c7d0204a2"}, {file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a79137fc99815fff6a852c233628e735ec15903cfd16da0f229d9c4d45926ab"},
{file = "coverage-7.0.0-cp38-cp38-win32.whl", hash = "sha256:8938f3a10f45019b502020ba9567b97b6ecc8c76b664b421705c5406d4f92fe8"}, {file = "coverage-7.0.1-cp38-cp38-win32.whl", hash = "sha256:b3763e7fcade2ff6c8e62340af9277f54336920489ceb6a8cd6cc96da52fcc62"},
{file = "coverage-7.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:c4b63888bef2928d0eca12cbce0760cfb696acb4fe226eb55178b6a2a039328a"}, {file = "coverage-7.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:09f6b5a8415b6b3e136d5fec62b552972187265cb705097bf030eb9d4ffb9b60"},
{file = "coverage-7.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cda63459eb20652b22e038729a8f5063862c189a3963cb042a764b753172f75e"}, {file = "coverage-7.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:978258fec36c154b5e250d356c59af7d4c3ba02bef4b99cda90b6029441d797d"},
{file = "coverage-7.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e06abac1a4aec1ff989131e43ca917fc7bd296f34bf0cfe86cbf74343b21566d"}, {file = "coverage-7.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:19ec666533f0f70a0993f88b8273057b96c07b9d26457b41863ccd021a043b9a"},
{file = "coverage-7.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b94ad926e933976627f040f96dd1d9b0ac91f8d27e868c30a28253b9b6ac2d"}, {file = "coverage-7.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfded268092a84605f1cc19e5c737f9ce630a8900a3589e9289622db161967e9"},
{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.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07bcfb1d8ac94af886b54e18a88b393f6a73d5959bb31e46644a02453c36e475"},
{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.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.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:43ec1935c6d6caab4f3bc126d20bd709c0002a175d62208ebe745be37a826a41"}, {file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aec2d1515d9d39ff270059fd3afbb3b44e6ec5758af73caf18991807138c7118"},
{file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8593c9baf1f0f273afa22f5b45508b76adc7b8e94e17e7d98fbe1e3cd5812af2"}, {file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c20cfebcc149a4c212f6491a5f9ff56f41829cd4f607b5be71bb2d530ef243b1"},
{file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fee283cd36c3f14422d9c1b51da24ddbb5e1eed89ad2480f6a9f115df38b5df8"}, {file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fd556ff16a57a070ce4f31c635953cc44e25244f91a0378c6e9bdfd40fdb249f"},
{file = "coverage-7.0.0-cp39-cp39-win32.whl", hash = "sha256:97c0b001ff15b8e8882995fc07ac0a08c8baf8b13c1145f3f12e0587bbb0e335"}, {file = "coverage-7.0.1-cp39-cp39-win32.whl", hash = "sha256:b9ea158775c7c2d3e54530a92da79496fb3fb577c876eec761c23e028f1e216c"},
{file = "coverage-7.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:8dbf83a4611c591b5de65069b6fd4dd3889200ed270cd2f7f5ac765d3842889f"}, {file = "coverage-7.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:d1991f1dd95eba69d2cd7708ff6c2bbd2426160ffc73c2b81f617a053ebcb1a8"},
{file = "coverage-7.0.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:bcaf18e46668057051a312c714a4548b81f7e8fb3454116ad97be7562d2a99e4"}, {file = "coverage-7.0.1-pp37.pp38.pp39-none-any.whl", hash = "sha256:3dd4ee135e08037f458425b8842d24a95a0961831a33f89685ff86b77d378f89"},
{file = "coverage-7.0.0.tar.gz", hash = "sha256:9a175da2a7320e18fc3ee1d147639a2b3a8f037e508c96aa2da160294eb50e17"}, {file = "coverage-7.0.1.tar.gz", hash = "sha256:a4a574a19eeb67575a5328a5760bbbb737faa685616586a9f9da4281f940109c"},
] ]
[package.dependencies] [package.dependencies]
@ -521,14 +522,14 @@ watch = ["watchdog", "watchdog-gevent"]
[[package]] [[package]]
name = "exceptiongroup" name = "exceptiongroup"
version = "1.0.4" version = "1.1.0"
description = "Backport of PEP 654 (exception groups)" description = "Backport of PEP 654 (exception groups)"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"},
{file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"},
] ]
[package.extras] [package.extras]
@ -623,22 +624,23 @@ dramatiq = ">=1.5,<2.0"
[[package]] [[package]]
name = "flask-limiter" name = "flask-limiter"
version = "2.8.1" version = "2.9.2"
description = "Rate limiting for flask applications" description = "Rate limiting for flask applications"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "Flask-Limiter-2.8.1.tar.gz", hash = "sha256:d37d0a39ce1fe36f661a765132557d3213040c51d9355379fe2f336bfea7e308"}, {file = "Flask-Limiter-2.9.2.tar.gz", hash = "sha256:041bf0d72c8c62d2cb54c772de1ad842c82bdefeddfadc1c9171739f296484e2"},
{file = "Flask_Limiter-2.8.1-py3-none-any.whl", hash = "sha256:621f1f26fbde4768c60df510e31569e72ae91eee659633e35fd78d90073a0d56"}, {file = "Flask_Limiter-2.9.2-py3-none-any.whl", hash = "sha256:64c6456204d88006324127071598a04cdd77be1576e00e8f5b74fad80925ea37"},
] ]
[package.dependencies] [package.dependencies]
Flask = ">=2" Flask = ">=2"
limits = [ limits = [
{version = ">=2.3"}, {version = ">=2.8"},
{version = "*", extras = ["redis"], optional = true, markers = "extra == \"redis\""}, {version = "*", extras = ["redis"], optional = true, markers = "extra == \"redis\""},
] ]
ordered-set = ">4,<5"
rich = ">=12,<13" rich = ">=12,<13"
typing-extensions = ">=4" typing-extensions = ">=4"
@ -712,14 +714,14 @@ smmap = ">=3.0.1,<6"
[[package]] [[package]]
name = "gitpython" name = "gitpython"
version = "3.1.29" version = "3.1.30"
description = "GitPython is a python library used to interact with Git repositories" description = "GitPython is a python library used to interact with Git repositories"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "GitPython-3.1.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"}, {file = "GitPython-3.1.30-py3-none-any.whl", hash = "sha256:cd455b0000615c60e286208ba540271af9fe531fa6a87cc590a7298785ab2882"},
{file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"}, {file = "GitPython-3.1.30.tar.gz", hash = "sha256:769c2d83e13f5d938b7688479da374c4e3d49f71549aaf462b646db9602ea6f8"},
] ]
[package.dependencies] [package.dependencies]
@ -909,21 +911,21 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag
[[package]] [[package]]
name = "importlib-resources" name = "importlib-resources"
version = "5.10.1" version = "5.10.2"
description = "Read resources from Python packages" description = "Read resources from Python packages"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "importlib_resources-5.10.1-py3-none-any.whl", hash = "sha256:c09b067d82e72c66f4f8eb12332f5efbebc9b007c0b6c40818108c9870adc363"}, {file = "importlib_resources-5.10.2-py3-none-any.whl", hash = "sha256:7d543798b0beca10b6a01ac7cafda9f822c54db9e8376a6bf57e0cbd74d486b6"},
{file = "importlib_resources-5.10.1.tar.gz", hash = "sha256:32bb095bda29741f6ef0e5278c42df98d135391bee5f932841efc0041f748dc3"}, {file = "importlib_resources-5.10.2.tar.gz", hash = "sha256:e4a96c8cc0339647ff9a5e0550d9f276fc5a01ffa276012b58ec108cfd7b8484"},
] ]
[package.dependencies] [package.dependencies]
zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""}
[package.extras] [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)"] 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]] [[package]]
@ -940,14 +942,14 @@ files = [
[[package]] [[package]]
name = "isort" name = "isort"
version = "5.11.3" version = "5.11.4"
description = "A Python utility / library to sort Python imports." description = "A Python utility / library to sort Python imports."
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7.0" python-versions = ">=3.7.0"
files = [ files = [
{file = "isort-5.11.3-py3-none-any.whl", hash = "sha256:83155ffa936239d986b0f190347a3f2285f42a9b9e1725c89d865b27dd0627e5"}, {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"},
{file = "isort-5.11.3.tar.gz", hash = "sha256:a8ca25fbfad0f7d5d8447a4314837298d9f6b23aed8618584c894574f626b64b"}, {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"},
] ]
[package.extras] [package.extras]
@ -988,14 +990,14 @@ i18n = ["Babel (>=2.7)"]
[[package]] [[package]]
name = "limits" name = "limits"
version = "2.7.2" version = "2.8.0"
description = "Rate limiting utilities" description = "Rate limiting utilities"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "limits-2.7.2-py3-none-any.whl", hash = "sha256:503a22d3b292fccf1a25f26654fefb44f97d83cb6af37b8996c0e2499df5363b"}, {file = "limits-2.8.0-py3-none-any.whl", hash = "sha256:ee19e9a98dd392d52dd62cfc28d93710eb29a22cf9834c21c16ee19367c4d596"},
{file = "limits-2.7.2.tar.gz", hash = "sha256:159b3c1514af0529854b640f43299aa4a9961b3298e352f4197d9736b8309106"}, {file = "limits-2.8.0.tar.gz", hash = "sha256:b47e01c48b3b677c7230cb51775ebe7c30a574e9711dc68499dab810ed883bb9"},
] ]
[package.dependencies] [package.dependencies]
@ -1162,6 +1164,21 @@ files = [
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, {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]] [[package]]
name = "outcome" name = "outcome"
version = "1.2.0" version = "1.2.0"
@ -1288,19 +1305,22 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa
[[package]] [[package]]
name = "platformdirs" 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\"." description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "platformdirs-2.6.0-py3-none-any.whl", hash = "sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca"}, {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"},
{file = "platformdirs-2.6.0.tar.gz", hash = "sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e"}, {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"},
] ]
[package.dependencies]
typing-extensions = {version = ">=4.4", markers = "python_version < \"3.8\""}
[package.extras] [package.extras]
docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"]
test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]] [[package]]
name = "pluggy" name = "pluggy"
@ -2484,26 +2504,26 @@ files = [
[[package]] [[package]]
name = "types-redis" name = "types-redis"
version = "4.3.21.6" version = "4.3.21.7"
description = "Typing stubs for redis" description = "Typing stubs for redis"
category = "dev" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
{file = "types-redis-4.3.21.6.tar.gz", hash = "sha256:f7969f73a0f79e9e7895f053a06d8b429fb7b5d4fe1269b8ee40463388f653ad"}, {file = "types-redis-4.3.21.7.tar.gz", hash = "sha256:f9baac41fcafb0b8ec655893feebc5d8bd189da05062d03b4566a16c092fc08c"},
{file = "types_redis-4.3.21.6-py3-none-any.whl", hash = "sha256:615e5a9142993789ffc22ee54435769b600da3e528bb51cf38430e5cd82af306"}, {file = "types_redis-4.3.21.7-py3-none-any.whl", hash = "sha256:834e816a84fc570aa96551a9252b0df164ac671bc09e4708e2f8e2b129449ef1"},
] ]
[[package]] [[package]]
name = "types-requests" name = "types-requests"
version = "2.28.11.6" version = "2.28.11.7"
description = "Typing stubs for requests" description = "Typing stubs for requests"
category = "dev" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
{file = "types-requests-2.28.11.6.tar.gz", hash = "sha256:8c1b1e6a0b19522b4738063e772dcee82cee1c3646536ccc4eb96f655af2b6c6"}, {file = "types-requests-2.28.11.7.tar.gz", hash = "sha256:0ae38633734990d019b80f5463dfa164ebd3581998ac8435f526da6fe4d598c3"},
{file = "types_requests-2.28.11.6-py3-none-any.whl", hash = "sha256:48b7c06e3dffc1b6359e1888084a2b97f41b6b63f208c571ddb02ddbc6a892e4"}, {file = "types_requests-2.28.11.7-py3-none-any.whl", hash = "sha256:b6a2fca8109f4fdba33052f11ed86102bddb2338519e1827387137fefc66a98b"},
] ]
[package.dependencies] [package.dependencies]
@ -2703,4 +2723,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.7" python-versions = "^3.7"
content-hash = "44659aa26f07c74af8d04ca7a5d426cf439e65ad5301386d0f6713d676ab9cd9" content-hash = "a8eb55d8966ea55b1f38a96b410e85bab447cb436efcb208b514bf6cc20a9ef4"

Some files were not shown because too many files have changed in this diff Show More