diff --git a/README.md b/README.md index f0f3f24..e86e3ee 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,17 @@ Easy to use Google Maps in your Flask application - Jinja - Flask -- A google api key [get here](https://developers.google.com/maps/documentation/javascript/get-api-key) +- A Google api key [get here](https://developers.google.com/maps/documentation/javascript/get-api-key) ## Contribute -To contribute with the project, clone it, create a virtualenv and install all of you need to dev, see below: +To contribute with the project, clone it, create a virtualenv and +install all of you need to dev, see below: ```bash git clone https://github.com/flask-extensions/Flask-GoogleMaps.git cd Flask-GoogleMaps -poetry use env 3.8 # just to create virtualenv at the first time +poetry use env 3.12 # just to create virtualenv at the first time poetry shell # activate virtualenv poetry install # to install all for dev pre-commit install # to install pre-commit hooks @@ -33,7 +34,8 @@ pre-commit install # to install pre-commit hooks ## Installation -To use in your project just use your dependency manager to install it, with pip is like this: +To use in your project just use your dependency manager +to install it, with pip is like this: ```bash pip install flask-googlemaps @@ -41,15 +43,18 @@ pip install flask-googlemaps ## How it works -Flask-GoogleMaps includes some global functions and template filters in your Jinja environment, also it allows you to use the Map in views if needed. +Flask-GoogleMaps includes some global functions and template filters +in your Jinja environment, also it allows you +to use the Map in views if needed. -### registering +### Registering in your app ```python from flask import Flask + from flask_googlemaps import GoogleMaps app = Flask(__name__) @@ -72,7 +77,8 @@ In template -0.45345), ...])}} ``` -That's it! now you have some template filters and functions to use, more details in examples and screenshot below. +That's it! now you have some template filters and functions to use, +more details in examples and screenshot below. ### Usage @@ -84,12 +90,14 @@ That's it! now you have some template filters and functions to use, more details ```python from flask import Flask, render_template + from flask_googlemaps import GoogleMaps from flask_googlemaps import Map app = Flask(__name__, template_folder=".") GoogleMaps(app) + @app.route("/") def mapview(): # creating a map in the view @@ -97,29 +105,36 @@ def mapview(): identifier="view-side", lat=37.4419, lng=-122.1419, - markers=[(37.4419, -122.1419)] + markers=[{'latitude': 37.4419, 'longitude': -122.1419}] ) sndmap = Map( identifier="sndmap", lat=37.4419, lng=-122.1419, markers=[ - { - 'icon': 'http://maps.google.com/mapfiles/ms/icons/green-dot.png', - 'lat': 37.4419, - 'lng': -122.1419, - 'infobox': "Hello World" - }, - { - 'icon': 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png', - 'lat': 37.4300, - 'lng': -122.1400, - 'infobox': "Hello World from other place" - } + { + 'content': { + "icon_url": "https://img.shields.io/badge/PayPal-Donante-red.svg"}, + 'latitude': 37.4419, + 'longitude': -122.1419, + 'infobox': "Hello World" + }, + { + 'content': { + "border_color": "", + "glyph_color": "", + "background": "", + "glyph": "1", + "scale": 1.0, }, + 'latitude': 37.4300, + 'longitude': -122.1400, + 'infobox': "Hello World from other place" + } ] ) return render_template('example.html', mymap=mymap, sndmap=sndmap) + if __name__ == "__main__": app.run(debug=True) @@ -131,9 +146,7 @@ if __name__ == "__main__": - **lng**: The longitude coordinate for centering the map. - **zoom**: The zoom level. Defaults to `13`. - **maptype**: The map type - `ROADMAP`, `SATELLITE`, `HYBRID`, `TERRAIN`. Defaults to `ROADMAP`. -- **markers**: Markers array of tuples having (**lat**, **lng**, infobox, icon, label). Defaults to `None`. -- or **markers**: a list of dicts containing **lat**, **lng**, infobox, icon, label. -- or **markers**: Markers dictionary with icon urls as keys and markers array as values. +- **markers**: A list of dictionaries representing the markers. More details [below](#Markers). - **varname**: The instance variable name. - **style**: A string containing CSS styles. Defaults to `"height:300px;width:300px;margin:0;"`. - **identifier**: The CSS ID selector name. @@ -155,6 +168,30 @@ Also controls True or False: - mapdisplay (show a collapsible map by default or not) - center_on_user_location (using HTML5 Geolocation) +##### `Markers` + +Markers is a list of dictionaries. +Each list element (i.e. a dictionary) represents a marker. +A marker has the following elements: + +- **latitude**: float. The latitude coordinate of a marker +- **longitude**: float. The longitude coordinate of a marker +- *label*: Optional[str]. A label that can appear within the marker. It's best to keep the label short (max 3 chars). More than 3 is fine, but it's not visually appealing +- *infobox*: Optional[str]. The infobox appears on the map when the marker is clicked +- *content*: Optional[dict]. There are two potential structures: + - Pin: A pin can have the following elements: Colour fields can have literal values (e.g. `red`, `green`, etc.) or colour hex representations (`#FF0000`, `#008000`, etc.) + - *border_color*: the `border` field in image below. Default is red + - *glyph_color*: the `glyph` field in image below. Default is dark red + - *background*: the `background` field in image below. Default is red + - *glyph*: the `text`/`label` that a pin could have. Check [Glyph](#Glyph) section below. + - *scale*: How big the marker should be. It takes float values. Default is 1.0 + - Image: An image can have a single element: + - *icon_url*: The url of an icon which will be used as a marker. + +![The elements of a Pin](marker_parts.png "The elements of a Pin. Credits: https://developers.google.com/maps/documentation/javascript/advanced-markers/basic-customization#javascript_1") + +*The elements of a Pin. Credits: https://developers.google.com/maps/documentation/javascript/advanced-markers/basic-customization#javascript_1* + #### 2. Template ```html @@ -194,38 +231,38 @@ Here's an example snippet of code: ```python - Map( - identifier="catsmap", - lat=37.4419, - lng=-122.1419, - markers=[ - { - 'icon': 'http://maps.google.com/mapfiles/ms/icons/green-dot.png', - 'lat': 37.4419, - 'lng': -122.1419, - 'infobox': "" - }, - { - 'icon': 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png', - 'lat': 37.4300, - 'lng': -122.1400, - 'infobox': "" - }, - { - 'icon': 'http://maps.google.com/mapfiles/ms/icons/yellow-dot.png', - 'lat': 37.4500, - 'lng': -122.1350, - 'infobox': "" - } - ] - ) +Map( + identifier="catsmap", + lat=37.4419, + lng=-122.1419, + markers=[ + { + 'content': {"background": "green"}, + 'latitude': 37.4419, + 'longitude': -122.1419, + 'infobox': "" + }, + { + 'content': {"background": "blue"}, + 'latitude': 37.4300, + 'longitude': -122.1400, + 'infobox': "" + }, + { + 'content': {"background": "yellow"}, + 'latitude': 37.4500, + 'longitude': -122.1350, + 'infobox': "" + } + ] +) ``` Which results in something like the following map: screen shot 2015-07-29 at 2 41 52 pm -### Label +### Glyph Here's an example snippet of code: ```python @@ -236,19 +273,19 @@ Map( lng=-122.1419, markers=[ { - 'lat': 37.4500, - 'lng': -122.1350, - 'label': "X" + 'latitude': 37.4500, + 'longitude': -122.1350, + 'content': {"glyph": "X"}, }, { - 'lat': 37.4419, - 'lng': -122.1419, - 'label': "Y" + 'latitude': 37.4419, + 'longitude': -122.1419, + 'content': {"glyph": "Y"}, }, { - 'lat': 37.4300, - 'lng': -122.1400, - 'label': "Z" + 'latitude': 37.4300, + 'longitude': -122.1400, + 'content': {"glyph": "Z"}, } ] ) diff --git a/docs/docs/how_it_works.md b/docs/docs/how_it_works.md index 824e03a..eaa03fb 100644 --- a/docs/docs/how_it_works.md +++ b/docs/docs/how_it_works.md @@ -43,12 +43,14 @@ That's it! now you have some template filters and functions to use, more details ```python from flask import Flask, render_template + from flask_googlemaps import GoogleMaps from flask_googlemaps import Map -app = Flask(__name__, template_folder=".") +app = Flask(__name__) GoogleMaps(app) + @app.route("/") def mapview(): # creating a map in the view @@ -56,29 +58,32 @@ def mapview(): identifier="view-side", lat=37.4419, lng=-122.1419, - markers=[(37.4419, -122.1419)] + markers=[{"latitude": 37.4419, "longitude": -122.1419}] ) sndmap = Map( identifier="sndmap", lat=37.4419, lng=-122.1419, markers=[ - { - 'icon': 'http://maps.google.com/mapfiles/ms/icons/green-dot.png', - 'lat': 37.4419, - 'lng': -122.1419, - 'infobox': "Hello World" - }, - { - 'icon': 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png', - 'lat': 37.4300, - 'lng': -122.1400, - 'infobox': "Hello World from other place" - } + { + 'content': { + + }, + 'latitude': 37.4419, + 'longitude': -122.1419, + 'infobox': "Hello World" + }, + { + 'icon': 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png', + 'latitude': 37.4300, + 'longitude': -122.1400, + 'infobox': "Hello World from other place" + } ] ) return render_template('example.html', mymap=mymap, sndmap=sndmap) + if __name__ == "__main__": app.run(debug=True) diff --git a/examples/example.py b/examples/example.py index ff6e560..59df167 100644 --- a/examples/example.py +++ b/examples/example.py @@ -1,14 +1,11 @@ # coding: utf-8 from flask import Flask, render_template, request -from flask_googlemaps import GoogleMaps -from flask_googlemaps import Map, icons -# from dynaconf import FlaskDynaconf +from flask_googlemaps import GoogleMaps +from flask_googlemaps import Map app = Flask(__name__, template_folder="templates") -# FlaskDynaconf(app) # will read GOOGLEMAPS_KEY from .secrets.toml - # you can set key as config # app.config['GOOGLEMAPS_KEY'] = "AIzaSyDP0GX-Wsui9TSDxtFNj2XuKrh7JBTPCnU" @@ -22,6 +19,26 @@ # NOTE: this example is using a form to get the apikey +markers = [ + { + "latitude": 37.4419, + "longitude": -122.1419, + "content": {"background": "green"}, + }, + { + "latitude": 37.4500, + "longitude": -122.1350, + "content": {"background": "green"}, + }, + { + "latitude": 37.4300, + "longitude": -122.1400, + "content": {"background": "blue"}, + "infobox": "Hello World", + }, +] + + @app.route("/") def mapview(): mymap = Map( @@ -36,10 +53,7 @@ def mapview(): varname="sndmap", lat=37.4419, lng=-122.1419, - markers={ - icons.dots.green: [(37.4419, -122.1419), (37.4500, -122.1350)], - icons.dots.blue: [(37.4300, -122.1400, "Hello World")], - }, + markers=markers, ) trdmap = Map( @@ -49,21 +63,21 @@ def mapview(): lng=-122.1419, markers=[ { - "icon": icons.alpha.B, - "lat": 37.4419, - "lng": -122.1419, + "content": {"background": "green"}, + "latitude": 37.4419, + "longitude": -122.1419, "infobox": "Hello I am GREEN!", }, { - "icon": icons.dots.blue, - "lat": 37.4300, - "lng": -122.1400, + "content": {"background": "blue"}, + "latitude": 37.4300, + "longitude": -122.1400, "infobox": "Hello I am BLUE!", }, { - "icon": "//maps.google.com/mapfiles/ms/icons/yellow-dot.png", - "lat": 37.4500, - "lng": -122.1350, + "content": {"background": "yellow"}, + "latitude": 37.4500, + "longitude": -122.1350, "infobox": ( "Hello I am YELLOW!" "

It is HTML title

" @@ -80,11 +94,11 @@ def mapview(): lat=37.4419, lng=-122.1419, markers=[ - {"lat": 37.4500, "lng": -122.1350}, - {"lat": 37.4400, "lng": -122.1350}, - {"lat": 37.4300, "lng": -122.1350}, - {"lat": 36.4200, "lng": -122.1350}, - {"lat": 36.4100, "lng": -121.1350}, + {"latitude": 37.4500, "longitude": -122.1350}, + {"latitude": 37.4400, "longitude": -122.1350}, + {"latitude": 37.4300, "longitude": -122.1350}, + {"latitude": 36.4200, "longitude": -122.1350}, + {"latitude": 36.4100, "longitude": -121.1350}, ], zoom=12, cluster=True, @@ -95,15 +109,15 @@ def mapview(): varname="movingmap", lat=37.4419, lng=-122.1419, - markers=[{"lat": 37.4500, "lng": -122.1350}], + markers=[{"latitude": 37.4500, "longitude": -122.1350}], zoom=12, ) movingmarkers = [ - {"lat": 37.4400, "lng": -122.1350}, - {"lat": 37.4430, "lng": -122.1350}, - {"lat": 37.4450, "lng": -122.1350}, - {"lat": 37.4490, "lng": -122.1350}, + {"latitude": 37.4400, "longitude": -122.1350}, + {"latitude": 37.4430, "longitude": -122.1350}, + {"latitude": 37.4450, "longitude": -122.1350}, + {"latitude": 37.4490, "longitude": -122.1350}, ] rectangle = { @@ -242,7 +256,13 @@ def mapview(): zoom=12, lat=59.939012, lng=30.315707, - markers=[{"lat": 59.939, "lng": 30.315, "infobox": "This is a marker"}], + markers=[ + { + "latitude": 59.939, + "longitude": 30.315, + "infobox": "This is a marker", + } + ], circles=[ { "stroke_color": "#FF00FF", @@ -347,22 +367,22 @@ def fullmap(): lng=-122.1419, markers=[ { - "icon": "//maps.google.com/mapfiles/ms/icons/green-dot.png", - "lat": 37.4419, - "lng": -122.1419, + "content": {"background": "green"}, + "latitude": 37.4419, + "longitude": -122.1419, "infobox": "Hello I am GREEN!", }, { - "icon": "//maps.google.com/mapfiles/ms/icons/blue-dot.png", - "lat": 37.4300, - "lng": -122.1400, + "content": {"background": "blue"}, + "latitude": 37.4300, + "longitude": -122.1400, "infobox": "Hello I am BLUE!", }, { - "icon": icons.dots.yellow, + "content": {"background": "yellow"}, "title": "Click Here", - "lat": 37.4500, - "lng": -122.1350, + "latitude": 37.4500, + "longitude": -122.1350, "infobox": ( "Hello I am YELLOW!" "

It is HTML title

" diff --git a/examples/example_2.py b/examples/example_2.py index 6ac5e1c..8788cdd 100644 --- a/examples/example_2.py +++ b/examples/example_2.py @@ -1,31 +1,43 @@ +import json + from flask import Flask, render_template -from flask_googlemaps import GoogleMaps, Map, icons -# from dynaconf import FlaskDynaconf -# enter the api key below +from flask_googlemaps import GoogleMaps, Map + api = "" app = Flask(__name__) GoogleMaps(app, key=api) -# FlaskDynaconf(app) - -import json @app.route("/") def map_created_in_view(): - with open("dark_mode.json") as d: dark_data = json.load(d) + markers = [ + { + "latitude": 37.4419, + "longitude": -122.1419, + "content": {"background": "green"}, + }, + { + "latitude": 37.4500, + "longitude": -122.1350, + "content": {"background": "green"}, + }, + { + "latitude": 37.4300, + "longitude": -122.1400, + "content": {"background": "blue"}, + "infobox": "Hello World", + }, + ] wmap = Map( identifier="wmap", varname="wmap", lat=41.881832, lng=-87.623177, - markers={ - icons.dots.green: [(37.4419, -122.1419), (37.4500, -122.1350)], - icons.dots.blue: [(37.4300, -122.1400, "Hello World")], - }, + markers=markers, style="height:400px;width:600px;margin:0;color:#242f3e;", bicycle_layer=True, ) @@ -35,10 +47,24 @@ def map_created_in_view(): varname="gmap", lat=1.351616, lng=103.808053, - markers={ - icons.alpha.A: [(1.351616, 103.808053), (37.4500, -122.1350)], - icons.dots.blue: [(37.4300, -122.1400, "Hello World")], - }, + markers=[ + { + "latitude": 1.351616, + "longitude": 103.808053, + "content": {"background": "green"}, + }, + { + "latitude": 37.4500, + "longitude": -122.1350, + "content": {"background": "green"}, + }, + { + "latitude": 37.4300, + "longitude": -122.1400, + "content": {"background": "blue"}, + "infobox": "Hello World", + }, + ], style="height:400px;width:600px;margin:0;color:#242f3e;", layer="https://geo.data.gov.sg/dengue-cluster/2020/09/02/kml/dengue-cluster.kml", ) @@ -48,10 +74,7 @@ def map_created_in_view(): varname="dmap", lat=1.351616, lng=103.808053, - markers={ - icons.dots.green: [(37.4419, -122.1419), (37.4500, -122.1350)], - icons.dots.blue: [(37.4300, -122.1400, "Hello World")], - }, + markers=markers, style="height:400px;width:600px;margin:0;color:#242f3e;", styles=dark_data, ) diff --git a/examples/example_of_a.secrets.toml b/examples/example_of_a.secrets.toml deleted file mode 100644 index f5d9479..0000000 --- a/examples/example_of_a.secrets.toml +++ /dev/null @@ -1,2 +0,0 @@ -[default] -GOOGLEMAPS_KEY = "AIzaSyASoiiR2llCxCroz6Mj060q18e_893475348957" diff --git a/examples/examples_requirements.txt b/examples/examples_requirements.txt deleted file mode 100644 index 5878a1c..0000000 Binary files a/examples/examples_requirements.txt and /dev/null differ diff --git a/examples/jsonify_examples.py b/examples/jsonify_examples.py index d1bb1e3..e23c052 100644 --- a/examples/jsonify_examples.py +++ b/examples/jsonify_examples.py @@ -1,9 +1,9 @@ -from flask import Flask, jsonify -from flask_googlemaps import Map, GoogleMaps, icons +from flask import Flask, jsonify, render_template + +from flask_googlemaps import Map, GoogleMaps app = Flask(__name__, template_folder="templates") -app.config["GOOGLEMAPS_KEY"] = "AIzaSyAZzeHhs-8JZ7i18MjFuM35dJHq70n3Hx4" -GoogleMaps(app, key="AIzaSyAZzeHhs-8JZ7i18MjFuM35dJHq70n3Hx4") +GoogleMaps(app) @app.route("/") @@ -15,7 +15,6 @@ def tst_jsonify(): lng=-122.1419, markers=[(37.4419, -122.1419)], ) - return jsonify(mymap.as_json()) @@ -38,10 +37,7 @@ def simple_view_two(): varname="sndmap", lat=37.4419, lng=-122.1419, - markers={ - icons.dots.green: [(37.4419, -122.1419), (37.4500, -122.1350)], - icons.dots.blue: [(37.4300, -122.1400, "Hello World")], - }, + markers=[(37.4419, -122.1419), (37.4500, -122.1350)], ) return jsonify(sndmap.as_json()) @@ -55,21 +51,21 @@ def simple_view_three(): lng=-122.1419, markers=[ { - "icon": icons.alpha.B, - "lat": 37.4419, - "lng": -122.1419, + "content": {"background": "green"}, + "latitude": 37.4419, + "longitude": -122.1419, "infobox": "Hello I am GREEN!", }, { - "icon": icons.dots.blue, - "lat": 37.4300, - "lng": -122.1400, + "content": {"background": "blue"}, + "latitude": 37.4300, + "longitude": -122.1400, "infobox": "Hello I am BLUE!", }, { - "icon": "//maps.google.com/mapfiles/ms/icons/yellow-dot.png", - "lat": 37.4500, - "lng": -122.1350, + "content": {"background": "yellow"}, + "latitude": 37.4500, + "longitude": -122.1350, "infobox": ( "Hello I am YELLOW!" "

It is HTML title

" @@ -91,11 +87,11 @@ def cluster_view(): lat=37.4419, lng=-122.1419, markers=[ - {"lat": 37.4500, "lng": -122.1350}, - {"lat": 37.4400, "lng": -122.1350}, - {"lat": 37.4300, "lng": -122.1350}, - {"lat": 36.4200, "lng": -122.1350}, - {"lat": 36.4100, "lng": -121.1350}, + {"latitude": 37.4500, "longitude": -122.1350}, + {"latitude": 37.4400, "longitude": -122.1350}, + {"latitude": 37.4300, "longitude": -122.1350}, + {"latitude": 36.4200, "longitude": -122.1350}, + {"latitude": 36.4100, "longitude": -121.1350}, ], zoom=12, cluster=True, diff --git a/examples/simple.py b/examples/simple.py index 34d9ad2..4cfeff9 100644 --- a/examples/simple.py +++ b/examples/simple.py @@ -1,5 +1,6 @@ from flask import Flask, render_template -from flask_googlemaps import GoogleMaps, Map, icons + +from flask_googlemaps import GoogleMaps, Map app = Flask(__name__) GoogleMaps(app) @@ -7,16 +8,33 @@ @app.route("/") def map_created_in_view(): - gmap = Map( identifier="gmap", varname="gmap", lat=37.4419, lng=-122.1419, - markers={ - icons.dots.green: [(37.4419, -122.1419), (37.4500, -122.1350)], - icons.dots.blue: [(37.4300, -122.1400, "Hello World")], - }, + markers=[ + { + "latitude": 37.4419, + "longitude": -122.1419, + "infobox": "Hello world!", + "content": { + "border_color": "rgb(218, 247, 166)", + "glyph_color": "white", + "background": "#F88379", + "scale": 1.0, + }, + }, + { + "latitude": 37.4519, + "longitude": -122.1519, + "content": { + "icon_url": "https://img.shields.io/badge/PayPal-Donante-red.svg" + }, + }, + (37.4500, -122.1350), + (37.4800, -122.1550), + ], style="height:400px;width:600px;margin:0;", ) diff --git a/examples/templates/example.html b/examples/templates/example.html index 6d17403..4c31bb8 100644 --- a/examples/templates/example.html +++ b/examples/templates/example.html @@ -151,7 +151,8 @@

You can move markers dynamically and add new markers, refresh its position e
- +const { AdvancedMarkerElement } = await google.maps.importLibrary("marker"); +
@@ -161,7 +162,7 @@ 

You can move markers dynamically and add new markers, refresh its position e <button onclick='movingmap_markers.map(function(mk){mk.setPosition({lat: 37.449, lng:-122.135})})'>Go to position 4 </button> <button onclick='movingmap_markers.map(function(mk){mk.setMap(null)})'>Remove marker</button> <button onclick='movingmap_markers.map(function(mk){mk.setMap(movingmap)})'>Restore marker</button> -<button onclick='onclick='new google.maps.Marker({title: "New Marker", position: {lat: 37.4640, lng: -122.1350}}).setMap(movingmap)''>Add new marker above</button> +<button onclick='onclick='AdvancedMarkerElement({title: "New Marker", position: {lat: 37.4640, lng: -122.1350}}).setMap(movingmap)''>Add new marker above</button>

diff --git a/flask_googlemaps/__init__.py b/flask_googlemaps/__init__.py index c22231e..9e3dfdc 100644 --- a/flask_googlemaps/__init__.py +++ b/flask_googlemaps/__init__.py @@ -1,16 +1,16 @@ """FlaskGoogleMaps - Google Maps Extension for Flask""" -__version__ = "0.4.1" +__version__ = "0.5.0" from json import dumps from typing import Optional, Dict, Any, List, Union, Tuple, Text # noqa: F401 import requests -from flask import Blueprint, Markup, g, render_template +from flask import Blueprint, g, render_template +from markupsafe import Markup -from flask_googlemaps.icons import dots, Icon # noqa: F401 +from flask_googlemaps.marker import Marker -DEFAULT_ICON = dots.red DEFAULT_CLUSTER_IMAGE_PATH = "static/images/m" @@ -66,12 +66,11 @@ def __init__( self.language = language self.region = region self.varname = varname - self.center = self.verify_lat_lng_coordinates(lat, lng) + self.center = Marker.verify_latitude(lat), Marker.verify_longitude(lng) self.zoom = zoom self.maptype = maptype - self.markers = [] # type: List[Any] + self.markers = Marker.from_list(markers) # type: List[Marker] self.map_ids = map_ids - self.build_markers(markers) self.rectangles = [] # type: List[Any] self.build_rectangles(rectangles) self.circles = [] # type: List[Any] @@ -108,50 +107,6 @@ def __init__( self.heatmap_data = [] self.build_heatmap(heatmap_data, heatmap_layer) - def build_markers(self, markers): - # type: (Optional[Union[Dict, List, Tuple]]) -> None - if not markers: - return - if not isinstance(markers, (dict, list, tuple)): - raise AttributeError("markers accepts only dict, list and tuple") - - if isinstance(markers, dict): - for icon, marker_list in markers.items(): - for marker in marker_list: - marker_dict = self.build_marker_dict(marker, icon=icon) - self.add_marker(**marker_dict) - else: - for marker in markers: - if isinstance(marker, dict): - self.add_marker(**marker) - elif isinstance(marker, (tuple, list)): - marker_dict = self.build_marker_dict(marker) - self.add_marker(**marker_dict) - - def build_marker_dict(self, marker, icon=None): - # type: (Union[List, Tuple], Optional[Icon]) -> Dict - marker_dict = { - "lat": marker[0], - "lng": marker[1], - "icon": icon or DEFAULT_ICON, - } - if len(marker) > 2: - marker_dict["infobox"] = marker[2] - if len(marker) > 3: - marker_dict["icon"] = marker[3] - return marker_dict - - def add_marker(self, lat=None, lng=None, **kwargs): - # type: (Optional[float], Optional[float], **Any) -> None - if lat is not None: - kwargs["lat"] = lat - if lng is not None: - kwargs["lng"] = lng - if "lat" not in kwargs or "lng" not in kwargs: - raise AttributeError("lat and lng required") - - self.markers.append(kwargs) - def build_rectangles(self, rectangles): # type: (Optional[List[Union[List, Tuple, Tuple[Tuple], Dict]]]) -> None """Process data to construct rectangles @@ -271,7 +226,7 @@ def build_rectangle_dict( def add_rectangle( self, north=None, west=None, south=None, east=None, **kwargs ): - # type: (Optional[float], Optional[float], Optional[float], Optional[float], **Any) -> None # noqa: E501 + # type: (Optional[float], Optional[float], Optional[float], Optional[float], **Any) -> None # noqa E501 """Adds a rectangle dict to the Map.rectangles attribute The Google Maps API describes a rectangle using the LatLngBounds @@ -823,25 +778,11 @@ def as_json(self): return json_dict - def verify_lat_lng_coordinates(self, lat, lng): - if not (90 >= lat >= -90): - raise AttributeError( - "Latitude must be between -90 and 90 degrees inclusive." - ) - if not (180 >= lng >= -180): - raise AttributeError( - "Longitude must be between -180 and 180 degrees inclusive." - ) - - return (lat, lng) - @property def js(self): # type: () -> Markup return Markup( - self.render( - "googlemaps/gmapjs.html", gmap=self, DEFAULT_ICON=DEFAULT_ICON - ) + self.render("googlemaps/gmapjs.html", gmap=self, DEFAULT_PIN="") ) @property diff --git a/flask_googlemaps/icons.py b/flask_googlemaps/icons.py deleted file mode 100644 index c542eea..0000000 --- a/flask_googlemaps/icons.py +++ /dev/null @@ -1,316 +0,0 @@ -""" -The idea is to implement all icons from here: -http://kml4earth.appspot.com/icons.html#mapfiles -and -http://jg.org/mapping/icons.html -and -http://mabp.kiev.ua/2010/01/12/google-map-markers/ -""" - -__all__ = ["dots", "alpha", "shapes", "pushpin", "paddle"] - -from typing import Optional, List # noqa: F401 - - -class Icon(object): - """Dynamically return dot icon url""" - - def __init__(self, base_url, options=None): - # type: (str, Optional[List[str]]) -> None - self.base_url = base_url - self.options = options - - def __getattr__(self, item): - return self.base_url.format(item) - - -dots = Icon( - base_url="//maps.google.com/mapfiles/ms/icons/{0}-dot.png", - options=["blue", "yellow", "green", "red", "pink", "purple", "orange"], -) # type: Icon - -alpha = Icon( - base_url="//www.google.com/mapfiles/marker{0}.png", - options=[ - "A", - "B", - "C", - "D", - "E", - "F", - "G", - "H", - "I", - "J", - "K", - "L", - "M", - "N", - "O", - "P", - "Q", - "R", - "S", - "T", - "U", - "V", - "X", - "Z", - "W", - "Y", - ], -) # type: Icon - -shapes = Icon( - base_url="//maps.google.com/mapfiles/kml/shapes/{0}.png", - options=[ - "airports", - "arrow", - "arrow-reverse", - "arts", - "bars", - "broken_link", - "bus", - "cabs", - "camera", - "campfire", - "campground", - "capital_big", - "capital_big_highlight", - "capital_small", - "capital_small_highlight", - "caution", - "church", - "coffee", - "convenience", - "cross-hairs", - "cross-hairs_highlight", - "cycling", - "dining", - "dollar", - "donut", - "earthquake", - "electronics", - "euro", - "falling_rocks", - "ferry", - "firedept", - "fishing", - "flag", - "forbidden", - "gas_stations", - "golf", - "grocery", - "heliport", - "highway", - "hiker", - "homegardenbusiness", - "horsebackriding", - "hospitals", - "info", - "info-i", - "info_circle", - "lodging", - "man", - "marina", - "mechanic", - "motorcycling", - "mountains", - "movies", - "open-diamond", - "parking_lot", - "parks", - "partly_cloudy", - "pharmacy_rx", - "phone", - "picnic", - "placemark_circle", - "placemark_circle_highlight", - "placemark_square", - "placemark_square_highlight", - "play", - "poi", - "police", - "polygon", - "post_office", - "rail", - "rainy", - "ranger_station", - "realestate", - "road_shield1", - "road_shield2", - "road_shield3", - "ruler", - "sailing", - "salon", - "schools", - "shaded_dot", - "shopping", - "ski", - "snack_bar", - "snowflake_simple", - "square", - "star", - "subway", - "sunny", - "swimming", - "target", - "terrain", - "thunderstorm", - "toilets", - "trail", - "tram", - "triangle", - "truck", - "volcano", - "water", - "webcam", - "wheel_chair_accessible", - "woman", - "yen", - ], -) # type: Icon -pushpin = Icon( - base_url="//maps.google.com/mapfiles/kml/pushpin/{0}.png", - options=[ - "blue-pushpin", - "grn-pushpin", - "ltblu-pushpin", - "pink-pushpin", - "purple-pushpin", - "red-pushpin", - "wht-pushpin", - "ylw-pushpin", - ], -) # type: Icon - -paddle = Icon( - base_url="//maps.google.com/mapfiles/kml/paddle/{0}.png", - options=[ - "1-lv", - "2-lv", - "3-lv", - "4-lv", - "5-lv", - "6-lv", - "7-lv", - "8-lv", - "9-lv", - "10-lv", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "A", - "B", - "C", - "D", - "E", - "F", - "G", - "H", - "I", - "J", - "K", - "L", - "M", - "N", - "O", - "P", - "Q", - "R", - "S", - "T", - "U", - "V", - "X", - "W", - "Y", - "Z", - "blu-blank-lv", - "blu-blank", - "blu-circle-lv", - "blu-circle", - "blu-diamond-lv", - "blu-diamond", - "blu-square-lv", - "blu-square", - "blu-stars-lv", - "blu-stars", - "grn-blank-lv", - "grn-blank", - "grn-circle-lv", - "grn-circle", - "grn-diamond-lv", - "grn-diamond", - "grn-square-lv", - "grn-square", - "grn-stars-lv", - "grn-stars", - "ltblu-blank", - "ltblu-circle", - "ltblu-diamond", - "ltblu-square", - "ltblu-stars", - "pink-blank", - "pink-circle", - "pink-diamond", - "pink-square", - "pink-stars", - "purple-blank", - "purple-circle-lv", - "purple-circle", - "purple-diamond-lv", - "purple-diamond", - "purple-square-lv", - "purple-square", - "purple-stars-lv", - "purple-stars", - "red-circle-lv", - "red-circle", - "red-diamond-lv", - "red-diamond", - "red-square-lv", - "red-square", - "red-stars-lv", - "red-stars", - "wht-blank", - "wht-blank-lv", - "wht-circle-lv", - "wht-circle", - "wht-diamond-lv", - "wht-diamond", - "wht-square-lv", - "wht-square", - "wht-stars-lv", - "wht-stars", - "ylw-blank", - "ylw-blank-lv", - "ylw-circle-lv", - "ylw-circle", - "ylw-diamond-lv", - "ylw-diamond", - "ylw-square-lv", - "ylw-square", - "ylw-stars-lv", - "ylw-stars", - "orange-blank", - "orange-circle", - "orange-diamond", - "orange-square", - "orange-stars", - "go-lv", - "go", - "pause-lv", - "pause", - "stop-lv", - "stop", - "route", - ], -) # type: Icon diff --git a/flask_googlemaps/image.py b/flask_googlemaps/image.py new file mode 100644 index 0000000..0b4cc56 --- /dev/null +++ b/flask_googlemaps/image.py @@ -0,0 +1,17 @@ +from dataclasses import dataclass + +from flask_googlemaps.marker_content import MarkerContent + + +@dataclass +class Image(MarkerContent): + icon_url: str + + def content(self) -> str: + return self.name + + def dom_element(self) -> str: + return ( + f"const {self.name} = document.createElement('img');\n" + f"{self.name}.src = '{self.icon_url}';" + ) diff --git a/flask_googlemaps/marker.py b/flask_googlemaps/marker.py new file mode 100644 index 0000000..0128c05 --- /dev/null +++ b/flask_googlemaps/marker.py @@ -0,0 +1,64 @@ +from typing import Optional, List, Any, Dict, Tuple + +from flask_googlemaps.marker_content_factory import MarkerContentFactory + + +class Marker(dict): + + def __init__( + self, + latitude: float, + longitude: float, + infobox: Optional[str] = None, + content: Optional[dict] = {}, + ): + self.latitude = Marker.verify_latitude(latitude) + self.longitude = Marker.verify_longitude(longitude) + self.infobox = infobox + self.marker_content = MarkerContentFactory(**content).marker_content + self.content = self.marker_content.content() + self.dom_element = self.marker_content.dom_element() + + dict.__init__( + self, + { + "latitude": self.latitude, + "longitude": self.longitude, + "infobox": self.infobox, + "content": self.content, + "id": self.marker_content.name, + }, + ) + + @staticmethod + def verify_latitude(latitude: float) -> Optional[float]: + if not (90 >= latitude >= -90): + raise AttributeError( + "Latitude must be between -90 and 90 degrees inclusive." + ) + return latitude + + @staticmethod + def verify_longitude(longitude: float) -> Optional[float]: + if not (180 >= longitude >= -180): + raise AttributeError( + "Longitude must be between -180 and 180 degrees inclusive." + ) + return longitude + + @staticmethod + def from_list( + markers: List[Optional[Dict[str, Any] | Tuple[float, float]]] + ) -> List["Marker"]: + if not markers: + return [] + return list(map(marker_constructor, markers)) + + +def marker_constructor(marker: Dict[str, Any] | Tuple[float, float]) -> Marker: + if isinstance(marker, dict): + return Marker(**marker) + elif isinstance(marker, tuple): + return Marker(latitude=marker[0], longitude=marker[1]) + else: + raise TypeError("Marker must be either a dict or a tuple.") diff --git a/flask_googlemaps/marker_content.py b/flask_googlemaps/marker_content.py new file mode 100644 index 0000000..3a08d70 --- /dev/null +++ b/flask_googlemaps/marker_content.py @@ -0,0 +1,18 @@ +import uuid +from abc import ABC, abstractmethod +from dataclasses import dataclass + + +@dataclass +class MarkerContent(ABC): + + def __post_init__(self): + self.name = f"var_{str(uuid.uuid1())[0:8]}" + + @abstractmethod + def content(self) -> str: + pass + + @abstractmethod + def dom_element(self) -> str: + pass diff --git a/flask_googlemaps/marker_content_factory.py b/flask_googlemaps/marker_content_factory.py new file mode 100644 index 0000000..d5489fd --- /dev/null +++ b/flask_googlemaps/marker_content_factory.py @@ -0,0 +1,46 @@ +from enum import Enum +from typing import Optional + +from flask_googlemaps.image import Image +from flask_googlemaps.marker_content import MarkerContent +from flask_googlemaps.pin import Pin + + +class MarkerContentType(Enum): + PIN = 1 + IMAGE = 2 + + +class MarkerContentFactory: + + def __init__(self, **kwargs): + self.kwargs = kwargs + if "icon_url" in kwargs: + self.__content_type = MarkerContentType.IMAGE + elif ( + "border_color" in kwargs + or "glyph_color" in kwargs + or "background" in kwargs + or "glyph" in kwargs + or "scale" in kwargs + ): + self.__content_type = MarkerContentType.PIN + else: + self.__content_type = None + + @property + def marker_content(self) -> Optional[MarkerContent]: + if self.__content_type is MarkerContentType.PIN: + try: + return Pin(**self.kwargs) + except TypeError as e: + print(e) + return Pin() + elif self.__content_type is MarkerContentType.IMAGE: + try: + return Image(**self.kwargs) + except TypeError as e: + print(e) + return Pin() + else: + return Pin() diff --git a/flask_googlemaps/pin.py b/flask_googlemaps/pin.py new file mode 100644 index 0000000..4e13594 --- /dev/null +++ b/flask_googlemaps/pin.py @@ -0,0 +1,59 @@ +from dataclasses import dataclass, fields +from enum import Enum +from typing import Optional + +from flask_googlemaps.marker_content import MarkerContent + +pin_property_mapping = { + "glyph_color": "glyphColor", + "background": "background", + "border_color": "borderColor", + "glyph": "glyph", + "scale": "scale", +} + + +class PinPropertyMapping(Enum): + glyph_color = "glyphColor" + background = "background" + border_color = "borderColor" + glyph = "glyph" + scale = "scale" + + +@dataclass +class Pin(MarkerContent): + + def __post_init__(self): + MarkerContent.__post_init__(self) + self.dom = [] + for field in fields(Pin): + if self.__getattribute__(field.name): + self.dom.append( + f"\t{PinPropertyMapping.__getitem__(field.name).value}: " + ) + if field.name == "scale": + self.dom.append(f"{self.__getattribute__(field.name)},") + else: + self.dom.append(f"'{self.__getattribute__(field.name)}',") + + if self.dom: + self.dom.insert(0, f"const {self.name} = new PinElement({{") + self.dom.append("\t\t});\n") + + def dom_element(self) -> Optional[str]: + + if self.dom: + return "\n".join(self.dom) + return None + + border_color: str = "" + glyph_color: str = "" + background: str = "" + glyph: Optional[str] = "" + scale: Optional[float] = None + + def content(self) -> str: + if self.dom: + return f"{self.name}.element" + return "" diff --git a/flask_googlemaps/templates/googlemaps/gmapjs.html b/flask_googlemaps/templates/googlemaps/gmapjs.html index 36cf23e..7b2a320 100644 --- a/flask_googlemaps/templates/googlemaps/gmapjs.html +++ b/flask_googlemaps/templates/googlemaps/gmapjs.html @@ -1,11 +1,11 @@ {% if not is_googlemaps_loaded() and not gmap.heatmap_layer %} {% if GOOGLEMAPS_KEY %} - + {% else %} - + {% endif %} {{ set_googlemaps_loaded() }} {% endif %}{% if gmap.cluster %} {% endif %}{% if gmap.heatmap_layer %}{% if GOOGLEMAPS_KEY %} - + {% endif %}{% endif%} @@ -23,7 +23,7 @@ var {{gmap.varname}}_polylines = []; var prev_infowindow_{{gmap.varname}} = null; - function initialize_{{gmap.varname}}() { + async function initialize_{{gmap.varname}}() { document.getElementById('{{gmap.identifier}}').style.display = 'block'; {{gmap.varname}} = new google.maps.Map( document.getElementById('{{gmap.identifier}}'), { @@ -37,7 +37,8 @@ rotateControl: {% if gmap.rotate_control %}true{% else %}false{% endif %}, scrollwheel: {% if gmap.scroll_wheel %}true{% else %}false{% endif %}, fullscreenControl: {% if gmap.fullscreen_control %}true{% else %}false{% endif %}, - styles: {{ gmap.styles | tojson }} + styles: {{ gmap.styles | tojson }}, + mapId: "{{ gmap.mapId if gmap.mapId is defined else 'DEMO_MAP_ID' }}" }); //center map location on user location @@ -81,23 +82,27 @@ {% endif %} // add gmap markers - var raw_markers = {{gmap.markers|tojson|safe}}; - for(i=0; i<{{gmap.markers|length}};i++) { - tempMarker = new google.maps.Marker({ - position: new google.maps.LatLng(raw_markers[i].lat, raw_markers[i].lng), + const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker"); + {% for marker in gmap.markers %} + {% if marker.dom_element %} + {{ marker.dom_element |safe }} + {%endif%} + {% endfor %} + for (const marker of {{gmap.markers|tojson|safe}}) { + tempMarker = new AdvancedMarkerElement({ + position: new google.maps.LatLng(marker.latitude, marker.longitude), map: {{gmap.varname}}, - icon: raw_markers[i].icon, - title: raw_markers[i].title ? raw_markers[i].title : null, - label: raw_markers[i].label ? raw_markers[i].label : null + title: null, + content: eval(marker.content), }); - if(raw_markers[i].infobox) + if(marker.infobox) { google.maps.event.addListener( tempMarker, 'click', - getInfoCallback({{gmap.varname}}, raw_markers[i].infobox) + getInfoCallback({{gmap.varname}}, marker.infobox) ); } @@ -106,10 +111,10 @@ google.maps.event.addListener( tempMarker, 'click', - function (event) { markerClickposCallback('{{gmap.markerClickpos_uri}}', event.latLng, raw_markers[i].title, raw_markers[i].label)} + function (event) { markerClickposCallback('{{gmap.markerClickpos_uri}}', event.latLng, marker.title, marker.label)} ); } - {{gmap.varname}}_markers[i] = tempMarker; + {{gmap.varname}}_markers.push(tempMarker); } @@ -298,6 +303,6 @@ window.onload = init_{{gmap.identifier}}_button; } {% else %} - google.maps.event.addDomListener(window, 'load', initialize_{{gmap.varname}}); + window.addEventListener('load', initialize_{{gmap.varname}}); {% endif %} diff --git a/flask_googlemaps/tests/test_map.py b/flask_googlemaps/tests/test_map.py deleted file mode 100644 index ed14d01..0000000 --- a/flask_googlemaps/tests/test_map.py +++ /dev/null @@ -1,44 +0,0 @@ -import pytest -from flask_googlemaps import Map - - -class TestFunctionAddMarker: - """ - This Class is to test function add marker. - """ - - google_map = None - - @pytest.fixture(autouse=True) - def config_test(self): - self.google_map = Map( - identifier="view-side", # for DOM element - varname="mymap", # for JS object name - lat=37.4419, - lng=-122.1419, - ) - - @pytest.mark.parametrize("marker", [{}, {"lat": 1}, {"lng": 1}]) - def test_should_raise_attribute_error_when_is_missing_params(self, marker): - """ - Test check the validation of marker. - This should raise expetion when the lat, lng or both are missing. - """ - with pytest.raises(AttributeError) as error: - self.google_map.add_marker(**marker) - - assert str(error.value) == "lat and lng required" - - @pytest.mark.parametrize( - "marker", - [ - {"lat": 10, "lng": 20, "icon": "red"}, - {"lat": 10, "lng": 20, "icon": "red", "infobox": "teste"}, - ], - ) - def test_it_should_add_to_marker_list_a_new_valid_marker(self, marker): - """ - Test check if add_marker is adding a new market to markers_list. - """ - self.google_map.add_marker(**marker) - assert len(self.google_map.markers) == 1 diff --git a/marker_parts.png b/marker_parts.png new file mode 100644 index 0000000..2cb2d0f Binary files /dev/null and b/marker_parts.png differ diff --git a/poetry.lock b/poetry.lock index fba0150..6b5ebbe 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,19 +1,5 @@ # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. -[[package]] -name = "aspy-yaml" -version = "1.3.0" -description = "A few extensions to pyyaml." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "aspy.yaml-1.3.0-py2.py3-none-any.whl", hash = "sha256:463372c043f70160a9ec950c3f1e4c3a82db5fca01d334b6bc89c7164d744bdc"}, - {file = "aspy.yaml-1.3.0.tar.gz", hash = "sha256:e7c742382eff2caed61f87a39d13f99109088e5e93f04d76eb8d4b28aa143f45"}, -] - -[package.dependencies] -pyyaml = "*" - [[package]] name = "astroid" version = "3.1.0" @@ -46,6 +32,20 @@ six = ">=1.12.0" astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] +[[package]] +name = "babel" +version = "2.14.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + [[package]] name = "black" version = "24.4.0" @@ -316,6 +316,16 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1 [package.extras] toml = ["tomli"] +[[package]] +name = "csscompressor" +version = "0.9.5" +description = "A python port of YUI CSS Compressor" +optional = false +python-versions = "*" +files = [ + {file = "csscompressor-0.9.5.tar.gz", hash = "sha256:afa22badbcf3120a4f392e4d22f9fff485c044a1feda4a950ecc5eba9dd31a05"}, +] + [[package]] name = "decorator" version = "5.1.1" @@ -376,13 +386,13 @@ yaml = ["ruamel.yaml"] [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, ] [package.extras] @@ -436,13 +446,13 @@ pyflakes = ">=3.2.0,<3.3.0" [[package]] name = "flask" -version = "2.3.3" +version = "3.0.3" description = "A simple framework for building complex web applications." optional = false python-versions = ">=3.8" files = [ - {file = "flask-2.3.3-py3-none-any.whl", hash = "sha256:f69fcd559dc907ed196ab9df0e48471709175e696d6e698dd4dbe940f96ce66b"}, - {file = "flask-2.3.3.tar.gz", hash = "sha256:09c347a92aa7ff4a8e7f3206795f30d826654baf38b873d0744cd571ca609efc"}, + {file = "flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3"}, + {file = "flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842"}, ] [package.dependencies] @@ -451,7 +461,7 @@ click = ">=8.1.3" importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} itsdangerous = ">=2.1.2" Jinja2 = ">=3.1.2" -Werkzeug = ">=2.3.7" +Werkzeug = ">=3.0.0" [package.extras] async = ["asgiref (>=3.2)"] @@ -491,24 +501,24 @@ mustache = ["pystache"] test = ["mako", "minimock", "nose", "pystache"] [[package]] -name = "htmlmin" -version = "0.1.12" +name = "htmlmin2" +version = "0.1.13" description = "An HTML Minifier" optional = false python-versions = "*" files = [ - {file = "htmlmin-0.1.12.tar.gz", hash = "sha256:50c1ef4630374a5d723900096a961cff426dff46b48f34d194a81bbe14eca178"}, + {file = "htmlmin2-0.1.13-py3-none-any.whl", hash = "sha256:75609f2a42e64f7ce57dbff28a39890363bde9e7e5885db633317efbdf8c79a2"}, ] [[package]] name = "identify" -version = "2.5.36" +version = "2.5.35" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"}, - {file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"}, + {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"}, + {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"}, ] [package.extras] @@ -804,69 +814,63 @@ files = [ [[package]] name = "mkdocs" -version = "1.6.0" +version = "1.5.3" description = "Project documentation with Markdown." optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "mkdocs-1.6.0-py3-none-any.whl", hash = "sha256:1eb5cb7676b7d89323e62b56235010216319217d4af5ddc543a91beb8d125ea7"}, - {file = "mkdocs-1.6.0.tar.gz", hash = "sha256:a73f735824ef83a4f3bcb7a231dcab23f5a838f88b7efc54a0eef5fbdbc3c512"}, + {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"}, + {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"}, ] [package.dependencies] click = ">=7.0" colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} ghp-import = ">=1.0" -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} jinja2 = ">=2.11.1" -markdown = ">=3.3.6" +markdown = ">=3.2.1" markupsafe = ">=2.0.1" mergedeep = ">=1.3.4" -mkdocs-get-deps = ">=0.2.0" packaging = ">=20.5" pathspec = ">=0.11.1" +platformdirs = ">=2.2.0" pyyaml = ">=5.1" pyyaml-env-tag = ">=0.1" watchdog = ">=2.0" [package.extras] i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] [[package]] -name = "mkdocs-get-deps" -version = "0.2.0" -description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" +name = "mkdocs-material" +version = "9.5.18" +description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, - {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, + {file = "mkdocs_material-9.5.18-py3-none-any.whl", hash = "sha256:1e0e27fc9fe239f9064318acf548771a4629d5fd5dfd45444fd80a953fe21eb4"}, + {file = "mkdocs_material-9.5.18.tar.gz", hash = "sha256:a43f470947053fa2405c33995f282d24992c752a50114f23f30da9d8d0c57e62"}, ] [package.dependencies] -importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} -mergedeep = ">=1.3.4" -platformdirs = ">=2.2.0" -pyyaml = ">=5.1" - -[[package]] -name = "mkdocs-material" -version = "5.5.14" -description = "A Material Design theme for MkDocs" -optional = false -python-versions = "*" -files = [ - {file = "mkdocs-material-5.5.14.tar.gz", hash = "sha256:9f3237df1a72f91e0330a5e3b3711cb7aaa0d5705f9585e6ce6fbacaa16e777f"}, - {file = "mkdocs_material-5.5.14-py2.py3-none-any.whl", hash = "sha256:a0b3b3e67606e04d13e777d13f3195402ea09e0c3ce279abc3666cac2c5b3a6d"}, -] +babel = ">=2.10,<3.0" +colorama = ">=0.4,<1.0" +jinja2 = ">=3.0,<4.0" +markdown = ">=3.2,<4.0" +mkdocs = ">=1.5.3,<1.6.0" +mkdocs-material-extensions = ">=1.3,<2.0" +paginate = ">=0.5,<1.0" +pygments = ">=2.16,<3.0" +pymdown-extensions = ">=10.2,<11.0" +regex = ">=2022.4" +requests = ">=2.26,<3.0" -[package.dependencies] -markdown = ">=3.2" -mkdocs = ">=1.1" -mkdocs-material-extensions = ">=1.0" -Pygments = ">=2.4" -pymdown-extensions = ">=7.0" +[package.extras] +git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] +imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] +recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] [[package]] name = "mkdocs-material-extensions" @@ -881,19 +885,20 @@ files = [ [[package]] name = "mkdocs-minify-plugin" -version = "0.3.0" -description = "An MkDocs plugin to minify HTML and/or JS files prior to being written to disk" +version = "0.8.0" +description = "An MkDocs plugin to minify HTML, JS or CSS files prior to being written to disk" optional = false -python-versions = ">=2.7" +python-versions = ">=3.8" files = [ - {file = "mkdocs-minify-plugin-0.3.0.tar.gz", hash = "sha256:06fecd8ddb9cb90f30bcee2d94c3d4b46a090f403d7ff0edff089a435906c4ee"}, - {file = "mkdocs_minify_plugin-0.3.0-py2-none-any.whl", hash = "sha256:9bac96276b1681debb3eb2cf5bae972586b4c1138e8d78ea63a984ea6276563d"}, + {file = "mkdocs-minify-plugin-0.8.0.tar.gz", hash = "sha256:bc11b78b8120d79e817308e2b11539d790d21445eb63df831e393f76e52e753d"}, + {file = "mkdocs_minify_plugin-0.8.0-py3-none-any.whl", hash = "sha256:5fba1a3f7bd9a2142c9954a6559a57e946587b21f133165ece30ea145c66aee6"}, ] [package.dependencies] -htmlmin = ">=0.1.4" -jsmin = ">=2.2.2" -mkdocs = ">=1.0.4" +csscompressor = ">=0.9.5" +htmlmin2 = ">=0.1.13" +jsmin = ">=3.0.1" +mkdocs = ">=1.4.1" [[package]] name = "mypy" @@ -978,6 +983,16 @@ files = [ {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, ] +[[package]] +name = "paginate" +version = "0.5.6" +description = "Divides large result sets into pages for easier browsing" +optional = false +python-versions = "*" +files = [ + {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, +] + [[package]] name = "parso" version = "0.8.4" @@ -1020,29 +1035,28 @@ ptyprocess = ">=0.5" [[package]] name = "platformdirs" -version = "4.2.1" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +version = "4.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"}, - {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"}, + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] [[package]] name = "pluggy" -version = "1.5.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, ] [package.extras] @@ -1051,24 +1065,21 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "1.21.0" +version = "3.7.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.9" files = [ - {file = "pre_commit-1.21.0-py2.py3-none-any.whl", hash = "sha256:f92a359477f3252452ae2e8d3029de77aec59415c16ae4189bcfba40b757e029"}, - {file = "pre_commit-1.21.0.tar.gz", hash = "sha256:8f48d8637bdae6fa70cc97db9c1dd5aa7c5c8bf71968932a380628c25978b850"}, + {file = "pre_commit-3.7.0-py2.py3-none-any.whl", hash = "sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab"}, + {file = "pre_commit-3.7.0.tar.gz", hash = "sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060"}, ] [package.dependencies] -"aspy.yaml" = "*" cfgv = ">=2.0.0" identify = ">=1.0.0" nodeenv = ">=0.11.1" -pyyaml = "*" -six = "*" -toml = "*" -virtualenv = ">=15.2" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" [[package]] name = "prompt-toolkit" @@ -1178,17 +1189,17 @@ testutils = ["gitpython (>3)"] [[package]] name = "pymdown-extensions" -version = "10.8" +version = "10.7.1" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.8" files = [ - {file = "pymdown_extensions-10.8-py3-none-any.whl", hash = "sha256:3539003ff0d5e219ba979d2dc961d18fcad5ac259e66c764482e8347b4c0503c"}, - {file = "pymdown_extensions-10.8.tar.gz", hash = "sha256:91ca336caf414e1e5e0626feca86e145de9f85a3921a7bcbd32890b51738c428"}, + {file = "pymdown_extensions-10.7.1-py3-none-any.whl", hash = "sha256:f5cc7000d7ff0d1ce9395d216017fa4df3dde800afb1fb72d1c7d3fd35e710f4"}, + {file = "pymdown_extensions-10.7.1.tar.gz", hash = "sha256:c70e146bdd83c744ffc766b4671999796aba18842b268510a329f7f64700d584"}, ] [package.dependencies] -markdown = ">=3.6" +markdown = ">=3.5" pyyaml = "*" [package.extras] @@ -1322,6 +1333,108 @@ files = [ [package.dependencies] pyyaml = "*" +[[package]] +name = "regex" +version = "2024.4.16" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.7" +files = [ + {file = "regex-2024.4.16-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb83cc090eac63c006871fd24db5e30a1f282faa46328572661c0a24a2323a08"}, + {file = "regex-2024.4.16-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c91e1763696c0eb66340c4df98623c2d4e77d0746b8f8f2bee2c6883fd1fe18"}, + {file = "regex-2024.4.16-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:10188fe732dec829c7acca7422cdd1bf57d853c7199d5a9e96bb4d40db239c73"}, + {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:956b58d692f235cfbf5b4f3abd6d99bf102f161ccfe20d2fd0904f51c72c4c66"}, + {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a70b51f55fd954d1f194271695821dd62054d949efd6368d8be64edd37f55c86"}, + {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c02fcd2bf45162280613d2e4a1ca3ac558ff921ae4e308ecb307650d3a6ee51"}, + {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4ed75ea6892a56896d78f11006161eea52c45a14994794bcfa1654430984b22"}, + {file = "regex-2024.4.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd727ad276bb91928879f3aa6396c9a1d34e5e180dce40578421a691eeb77f47"}, + {file = "regex-2024.4.16-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7cbc5d9e8a1781e7be17da67b92580d6ce4dcef5819c1b1b89f49d9678cc278c"}, + {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:78fddb22b9ef810b63ef341c9fcf6455232d97cfe03938cbc29e2672c436670e"}, + {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:445ca8d3c5a01309633a0c9db57150312a181146315693273e35d936472df912"}, + {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:95399831a206211d6bc40224af1c635cb8790ddd5c7493e0bd03b85711076a53"}, + {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:7731728b6568fc286d86745f27f07266de49603a6fdc4d19c87e8c247be452af"}, + {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4facc913e10bdba42ec0aee76d029aedda628161a7ce4116b16680a0413f658a"}, + {file = "regex-2024.4.16-cp310-cp310-win32.whl", hash = "sha256:911742856ce98d879acbea33fcc03c1d8dc1106234c5e7d068932c945db209c0"}, + {file = "regex-2024.4.16-cp310-cp310-win_amd64.whl", hash = "sha256:e0a2df336d1135a0b3a67f3bbf78a75f69562c1199ed9935372b82215cddd6e2"}, + {file = "regex-2024.4.16-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1210365faba7c2150451eb78ec5687871c796b0f1fa701bfd2a4a25420482d26"}, + {file = "regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9ab40412f8cd6f615bfedea40c8bf0407d41bf83b96f6fc9ff34976d6b7037fd"}, + {file = "regex-2024.4.16-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fd80d1280d473500d8086d104962a82d77bfbf2b118053824b7be28cd5a79ea5"}, + {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bb966fdd9217e53abf824f437a5a2d643a38d4fd5fd0ca711b9da683d452969"}, + {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:20b7a68444f536365af42a75ccecb7ab41a896a04acf58432db9e206f4e525d6"}, + {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b74586dd0b039c62416034f811d7ee62810174bb70dffcca6439f5236249eb09"}, + {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8290b44d8b0af4e77048646c10c6e3aa583c1ca67f3b5ffb6e06cf0c6f0f89"}, + {file = "regex-2024.4.16-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2d80a6749724b37853ece57988b39c4e79d2b5fe2869a86e8aeae3bbeef9eb0"}, + {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3a1018e97aeb24e4f939afcd88211ace472ba566efc5bdf53fd8fd7f41fa7170"}, + {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8d015604ee6204e76569d2f44e5a210728fa917115bef0d102f4107e622b08d5"}, + {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:3d5ac5234fb5053850d79dd8eb1015cb0d7d9ed951fa37aa9e6249a19aa4f336"}, + {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:0a38d151e2cdd66d16dab550c22f9521ba79761423b87c01dae0a6e9add79c0d"}, + {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:159dc4e59a159cb8e4e8f8961eb1fa5d58f93cb1acd1701d8aff38d45e1a84a6"}, + {file = "regex-2024.4.16-cp311-cp311-win32.whl", hash = "sha256:ba2336d6548dee3117520545cfe44dc28a250aa091f8281d28804aa8d707d93d"}, + {file = "regex-2024.4.16-cp311-cp311-win_amd64.whl", hash = "sha256:8f83b6fd3dc3ba94d2b22717f9c8b8512354fd95221ac661784df2769ea9bba9"}, + {file = "regex-2024.4.16-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:80b696e8972b81edf0af2a259e1b2a4a661f818fae22e5fa4fa1a995fb4a40fd"}, + {file = "regex-2024.4.16-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d61ae114d2a2311f61d90c2ef1358518e8f05eafda76eaf9c772a077e0b465ec"}, + {file = "regex-2024.4.16-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ba6745440b9a27336443b0c285d705ce73adb9ec90e2f2004c64d95ab5a7598"}, + {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6295004b2dd37b0835ea5c14a33e00e8cfa3c4add4d587b77287825f3418d310"}, + {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4aba818dcc7263852aabb172ec27b71d2abca02a593b95fa79351b2774eb1d2b"}, + {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0800631e565c47520aaa04ae38b96abc5196fe8b4aa9bd864445bd2b5848a7a"}, + {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08dea89f859c3df48a440dbdcd7b7155bc675f2fa2ec8c521d02dc69e877db70"}, + {file = "regex-2024.4.16-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eeaa0b5328b785abc344acc6241cffde50dc394a0644a968add75fcefe15b9d4"}, + {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4e819a806420bc010489f4e741b3036071aba209f2e0989d4750b08b12a9343f"}, + {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:c2d0e7cbb6341e830adcbfa2479fdeebbfbb328f11edd6b5675674e7a1e37730"}, + {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:91797b98f5e34b6a49f54be33f72e2fb658018ae532be2f79f7c63b4ae225145"}, + {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:d2da13568eff02b30fd54fccd1e042a70fe920d816616fda4bf54ec705668d81"}, + {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:370c68dc5570b394cbaadff50e64d705f64debed30573e5c313c360689b6aadc"}, + {file = "regex-2024.4.16-cp312-cp312-win32.whl", hash = "sha256:904c883cf10a975b02ab3478bce652f0f5346a2c28d0a8521d97bb23c323cc8b"}, + {file = "regex-2024.4.16-cp312-cp312-win_amd64.whl", hash = "sha256:785c071c982dce54d44ea0b79cd6dfafddeccdd98cfa5f7b86ef69b381b457d9"}, + {file = "regex-2024.4.16-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e2f142b45c6fed48166faeb4303b4b58c9fcd827da63f4cf0a123c3480ae11fb"}, + {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e87ab229332ceb127a165612d839ab87795972102cb9830e5f12b8c9a5c1b508"}, + {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81500ed5af2090b4a9157a59dbc89873a25c33db1bb9a8cf123837dcc9765047"}, + {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b340cccad138ecb363324aa26893963dcabb02bb25e440ebdf42e30963f1a4e0"}, + {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c72608e70f053643437bd2be0608f7f1c46d4022e4104d76826f0839199347a"}, + {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a01fe2305e6232ef3e8f40bfc0f0f3a04def9aab514910fa4203bafbc0bb4682"}, + {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:03576e3a423d19dda13e55598f0fd507b5d660d42c51b02df4e0d97824fdcae3"}, + {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:549c3584993772e25f02d0656ac48abdda73169fe347263948cf2b1cead622f3"}, + {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:34422d5a69a60b7e9a07a690094e824b66f5ddc662a5fc600d65b7c174a05f04"}, + {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:5f580c651a72b75c39e311343fe6875d6f58cf51c471a97f15a938d9fe4e0d37"}, + {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3399dd8a7495bbb2bacd59b84840eef9057826c664472e86c91d675d007137f5"}, + {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8d1f86f3f4e2388aa3310b50694ac44daefbd1681def26b4519bd050a398dc5a"}, + {file = "regex-2024.4.16-cp37-cp37m-win32.whl", hash = "sha256:dd5acc0a7d38fdc7a3a6fd3ad14c880819008ecb3379626e56b163165162cc46"}, + {file = "regex-2024.4.16-cp37-cp37m-win_amd64.whl", hash = "sha256:ba8122e3bb94ecda29a8de4cf889f600171424ea586847aa92c334772d200331"}, + {file = "regex-2024.4.16-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:743deffdf3b3481da32e8a96887e2aa945ec6685af1cfe2bcc292638c9ba2f48"}, + {file = "regex-2024.4.16-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7571f19f4a3fd00af9341c7801d1ad1967fc9c3f5e62402683047e7166b9f2b4"}, + {file = "regex-2024.4.16-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df79012ebf6f4efb8d307b1328226aef24ca446b3ff8d0e30202d7ebcb977a8c"}, + {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e757d475953269fbf4b441207bb7dbdd1c43180711b6208e129b637792ac0b93"}, + {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4313ab9bf6a81206c8ac28fdfcddc0435299dc88cad12cc6305fd0e78b81f9e4"}, + {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d83c2bc678453646f1a18f8db1e927a2d3f4935031b9ad8a76e56760461105dd"}, + {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9df1bfef97db938469ef0a7354b2d591a2d438bc497b2c489471bec0e6baf7c4"}, + {file = "regex-2024.4.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62120ed0de69b3649cc68e2965376048793f466c5a6c4370fb27c16c1beac22d"}, + {file = "regex-2024.4.16-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c2ef6f7990b6e8758fe48ad08f7e2f66c8f11dc66e24093304b87cae9037bb4a"}, + {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8fc6976a3395fe4d1fbeb984adaa8ec652a1e12f36b56ec8c236e5117b585427"}, + {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:03e68f44340528111067cecf12721c3df4811c67268b897fbe695c95f860ac42"}, + {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ec7e0043b91115f427998febaa2beb82c82df708168b35ece3accb610b91fac1"}, + {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c21fc21a4c7480479d12fd8e679b699f744f76bb05f53a1d14182b31f55aac76"}, + {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:12f6a3f2f58bb7344751919a1876ee1b976fe08b9ffccb4bbea66f26af6017b9"}, + {file = "regex-2024.4.16-cp38-cp38-win32.whl", hash = "sha256:479595a4fbe9ed8f8f72c59717e8cf222da2e4c07b6ae5b65411e6302af9708e"}, + {file = "regex-2024.4.16-cp38-cp38-win_amd64.whl", hash = "sha256:0534b034fba6101611968fae8e856c1698da97ce2efb5c2b895fc8b9e23a5834"}, + {file = "regex-2024.4.16-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a7ccdd1c4a3472a7533b0a7aa9ee34c9a2bef859ba86deec07aff2ad7e0c3b94"}, + {file = "regex-2024.4.16-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6f2f017c5be19984fbbf55f8af6caba25e62c71293213f044da3ada7091a4455"}, + {file = "regex-2024.4.16-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:803b8905b52de78b173d3c1e83df0efb929621e7b7c5766c0843704d5332682f"}, + {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:684008ec44ad275832a5a152f6e764bbe1914bea10968017b6feaecdad5736e0"}, + {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65436dce9fdc0aeeb0a0effe0839cb3d6a05f45aa45a4d9f9c60989beca78b9c"}, + {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea355eb43b11764cf799dda62c658c4d2fdb16af41f59bb1ccfec517b60bcb07"}, + {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98c1165f3809ce7774f05cb74e5408cd3aa93ee8573ae959a97a53db3ca3180d"}, + {file = "regex-2024.4.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cccc79a9be9b64c881f18305a7c715ba199e471a3973faeb7ba84172abb3f317"}, + {file = "regex-2024.4.16-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00169caa125f35d1bca6045d65a662af0202704489fada95346cfa092ec23f39"}, + {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6cc38067209354e16c5609b66285af17a2863a47585bcf75285cab33d4c3b8df"}, + {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:23cff1b267038501b179ccbbd74a821ac4a7192a1852d1d558e562b507d46013"}, + {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:b9d320b3bf82a39f248769fc7f188e00f93526cc0fe739cfa197868633d44701"}, + {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:89ec7f2c08937421bbbb8b48c54096fa4f88347946d4747021ad85f1b3021b3c"}, + {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4918fd5f8b43aa7ec031e0fef1ee02deb80b6afd49c85f0790be1dc4ce34cb50"}, + {file = "regex-2024.4.16-cp39-cp39-win32.whl", hash = "sha256:684e52023aec43bdf0250e843e1fdd6febbe831bd9d52da72333fa201aaa2335"}, + {file = "regex-2024.4.16-cp39-cp39-win_amd64.whl", hash = "sha256:e697e1c0238133589e00c244a8b676bc2cfc3ab4961318d902040d099fec7483"}, + {file = "regex-2024.4.16.tar.gz", hash = "sha256:fa454d26f2e87ad661c4f0c5a5fe4cf6aab1e307d1b94f16ffdfcb089ba685c0"}, +] + [[package]] name = "requests" version = "2.31.0" @@ -1389,17 +1502,6 @@ pure-eval = "*" [package.extras] tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - [[package]] name = "tomli" version = "2.0.1" @@ -1424,18 +1526,18 @@ files = [ [[package]] name = "traitlets" -version = "5.14.3" +version = "5.14.2" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.8" files = [ - {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, - {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, + {file = "traitlets-5.14.2-py3-none-any.whl", hash = "sha256:fcdf85684a772ddeba87db2f398ce00b40ff550d1528c03c14dbf6a02003cd80"}, + {file = "traitlets-5.14.2.tar.gz", hash = "sha256:8cdd83c040dab7d1dee822678e5f5d100b514f7b72b01615b26fc5718916fdf9"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.1)", "pytest-mock", "pytest-mypy-testing"] [[package]] name = "typing-extensions" @@ -1467,13 +1569,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.26.0" +version = "20.25.3" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.26.0-py3-none-any.whl", hash = "sha256:0846377ea76e818daaa3e00a4365c018bc3ac9760cbb3544de542885aad61fb3"}, - {file = "virtualenv-20.26.0.tar.gz", hash = "sha256:ec25a9671a5102c8d2657f62792a27b48f016664c6873f6beed3800008577210"}, + {file = "virtualenv-20.25.3-py3-none-any.whl", hash = "sha256:8aac4332f2ea6ef519c648d0bc48a5b1d324994753519919bddbb1aff25a104e"}, + {file = "virtualenv-20.25.3.tar.gz", hash = "sha256:7bb554bbdfeaacc3349fa614ea5bff6ac300fc7c335e9facf3a3bcfc703f45be"}, ] [package.dependencies] @@ -1572,4 +1674,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9" -content-hash = "81cd518927722c98ca0cfa64a1bf70d0ba72e866967113d0bc567bc7fe237dff" +content-hash = "7f4fb2ba81c7c6dbbd36e21c2ad72f4554bc217de86d4c877d4dffbfb61db2fd" diff --git a/pyproject.toml b/pyproject.toml index b01fc83..1a81166 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "flask_googlemaps" -version = "0.4.1" +version = "0.5.0" description = "Easy way to add GoogleMaps to Flask Applications" authors = ["Riverfount - Vulgo Vicente Marçal "] license = "MIT" @@ -13,7 +13,6 @@ classifiers=[ 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules' @@ -25,12 +24,13 @@ include = ["flask_googlemaps/py.typed"] [tool.poetry.dependencies] python = ">=3.9" -flask = "<3.0.0" -pre-commit = "1.21.0" -mkdocs = "^1.1" -mkdocs-material = "^5.0.2" -mkdocs-minify-plugin = "^0.3.0" -requests = "^2.25.1" +flask = ">=3.0.3" +pre-commit = "3.7.0" +mkdocs = "^1.5.3" +mkdocs-material = "^9.5.18" +mkdocs-minify-plugin = "^0.8.0" +requests = "^2.31.0" +jsmin = "^3.0.1" [tool.poetry.dev-dependencies] ipdb = "^0.13.3" diff --git a/requirements.txt b/requirements.txt index 3beaf57..d1e6bf4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,257 +1,354 @@ -certifi==2020.12.5 \ - --hash=sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830 \ - --hash=sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c -chardet==4.0.0 \ - --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 \ - --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa -click==7.1.2 \ - --hash=sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc \ - --hash=sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a -flask==1.1.2 \ - --hash=sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557 \ - --hash=sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060 -future==0.18.2 \ - --hash=sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d -htmlmin==0.1.12 \ - --hash=sha256:50c1ef4630374a5d723900096a961cff426dff46b48f34d194a81bbe14eca178 -idna==2.10 \ - --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 \ - --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 -importlib-metadata==3.3.0; python_version < "3.8" \ - --hash=sha256:bf792d480abbd5eda85794e4afb09dd538393f7d6e6ffef6e9f03d2014cf9450 \ - --hash=sha256:5c5a2720817414a6c41f0a49993908068243ae02c1635a228126519b509c8aed -itsdangerous==1.1.0 \ - --hash=sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749 \ - --hash=sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19 -jinja2==2.11.2 \ - --hash=sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035 \ - --hash=sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0 -joblib==1.0.0 \ - --hash=sha256:75ead23f13484a2a414874779d69ade40d4fa1abe62b222a23cd50d4bc822f6f \ - --hash=sha256:7ad866067ac1fdec27d51c8678ea760601b70e32ff1881d4dc8e1171f2b64b24 -jsmin==2.2.2 \ - --hash=sha256:b6df99b2cd1c75d9d342e4335b535789b8da9107ec748212706ef7bbe5c2553b -livereload==2.6.3 \ - --hash=sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869 -lunr==0.5.8 \ - --hash=sha256:aab3f489c4d4fab4c1294a257a30fec397db56f0a50273218ccc3efdbf01d6ca \ - --hash=sha256:c4fb063b98eff775dd638b3df380008ae85e6cb1d1a24d1cd81a10ef6391c26e -markdown==3.3.3 \ - --hash=sha256:c109c15b7dc20a9ac454c9e6025927d44460b85bd039da028d85e2b6d0bcc328 \ - --hash=sha256:5d9f2b5ca24bc4c7a390d22323ca4bad200368612b5aaa7796babf971d2b2f18 -markupsafe==1.1.1 \ - --hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \ - --hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \ - --hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \ - --hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \ - --hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \ - --hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \ - --hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \ - --hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \ - --hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \ - --hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \ - --hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \ - --hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \ - --hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \ - --hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \ - --hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \ - --hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \ - --hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \ - --hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \ - --hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \ - --hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \ - --hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \ - --hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \ - --hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \ - --hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \ - --hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \ - --hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \ - --hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \ - --hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \ - --hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \ - --hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \ - --hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \ - --hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be \ - --hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b -mkdocs-material-extensions==1.0.1 \ - --hash=sha256:6947fb7f5e4291e3c61405bad3539d81e0b3cd62ae0d66ced018128af509c68f \ - --hash=sha256:d90c807a88348aa6d1805657ec5c0b2d8d609c110e62b9dce4daf7fa981fa338 -mkdocs-material==5.5.14 \ +aspy-yaml==1.3.0 ; python_version >= "3.8" \ + --hash=sha256:463372c043f70160a9ec950c3f1e4c3a82db5fca01d334b6bc89c7164d744bdc \ + --hash=sha256:e7c742382eff2caed61f87a39d13f99109088e5e93f04d76eb8d4b28aa143f45 +blinker==1.7.0 ; python_version >= "3.8" \ + --hash=sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9 \ + --hash=sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182 +certifi==2024.2.2 ; python_version >= "3.8" \ + --hash=sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f \ + --hash=sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1 +cfgv==3.4.0 ; python_version >= "3.8" \ + --hash=sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9 \ + --hash=sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560 +charset-normalizer==3.3.2 ; python_version >= "3.8" \ + --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ + --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ + --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ + --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ + --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ + --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ + --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ + --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ + --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ + --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ + --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ + --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ + --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ + --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ + --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ + --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ + --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ + --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ + --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ + --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ + --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ + --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ + --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ + --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ + --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ + --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ + --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ + --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ + --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ + --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ + --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ + --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ + --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ + --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ + --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ + --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ + --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ + --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \ + --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \ + --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \ + --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \ + --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \ + --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \ + --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \ + --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \ + --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \ + --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \ + --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \ + --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \ + --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \ + --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \ + --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \ + --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \ + --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \ + --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \ + --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \ + --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \ + --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \ + --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \ + --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \ + --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \ + --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \ + --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \ + --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \ + --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \ + --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \ + --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \ + --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \ + --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \ + --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \ + --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \ + --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \ + --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \ + --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \ + --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \ + --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \ + --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \ + --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \ + --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \ + --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \ + --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \ + --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \ + --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \ + --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \ + --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \ + --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \ + --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \ + --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ + --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ + --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 +click==8.1.7 ; python_version >= "3.8" \ + --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ + --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de +colorama==0.4.6 ; python_version >= "3.8" and platform_system == "Windows" \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 +csscompressor==0.9.5 ; python_version >= "3.8" \ + --hash=sha256:afa22badbcf3120a4f392e4d22f9fff485c044a1feda4a950ecc5eba9dd31a05 +distlib==0.3.8 ; python_version >= "3.8" \ + --hash=sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 \ + --hash=sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64 +filelock==3.13.4 ; python_version >= "3.8" \ + --hash=sha256:404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f \ + --hash=sha256:d13f466618bfde72bd2c18255e269f72542c6e70e7bac83a0232d6b1cc5c8cf4 +flask==3.0.3 ; python_version >= "3.8" \ + --hash=sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3 \ + --hash=sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842 +ghp-import==2.1.0 ; python_version >= "3.8" \ + --hash=sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 \ + --hash=sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343 +htmlmin2==0.1.13 ; python_version >= "3.8" \ + --hash=sha256:75609f2a42e64f7ce57dbff28a39890363bde9e7e5885db633317efbdf8c79a2 +identify==2.5.35 ; python_version >= "3.8" \ + --hash=sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791 \ + --hash=sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e +idna==3.7 ; python_version >= "3.8" \ + --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \ + --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 +importlib-metadata==7.1.0 ; python_version < "3.10" and python_version >= "3.8" \ + --hash=sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570 \ + --hash=sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2 +itsdangerous==2.2.0 ; python_version >= "3.8" \ + --hash=sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef \ + --hash=sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173 +jinja2==3.1.3 ; python_version >= "3.8" \ + --hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \ + --hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90 +jsmin==3.0.1 ; python_version >= "3.8" \ + --hash=sha256:c0959a121ef94542e807a674142606f7e90214a2b3d1eb17300244bbb5cc2bfc +markdown==3.6 ; python_version >= "3.8" \ + --hash=sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f \ + --hash=sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224 +markupsafe==2.1.5 ; python_version >= "3.8" \ + --hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \ + --hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \ + --hash=sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f \ + --hash=sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3 \ + --hash=sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532 \ + --hash=sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f \ + --hash=sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 \ + --hash=sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df \ + --hash=sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4 \ + --hash=sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906 \ + --hash=sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f \ + --hash=sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 \ + --hash=sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8 \ + --hash=sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371 \ + --hash=sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2 \ + --hash=sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465 \ + --hash=sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52 \ + --hash=sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6 \ + --hash=sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169 \ + --hash=sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad \ + --hash=sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 \ + --hash=sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0 \ + --hash=sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029 \ + --hash=sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f \ + --hash=sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a \ + --hash=sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced \ + --hash=sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5 \ + --hash=sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c \ + --hash=sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf \ + --hash=sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9 \ + --hash=sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb \ + --hash=sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad \ + --hash=sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3 \ + --hash=sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 \ + --hash=sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46 \ + --hash=sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc \ + --hash=sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a \ + --hash=sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee \ + --hash=sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900 \ + --hash=sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 \ + --hash=sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea \ + --hash=sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f \ + --hash=sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5 \ + --hash=sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e \ + --hash=sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a \ + --hash=sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f \ + --hash=sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50 \ + --hash=sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a \ + --hash=sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b \ + --hash=sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4 \ + --hash=sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff \ + --hash=sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2 \ + --hash=sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46 \ + --hash=sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b \ + --hash=sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf \ + --hash=sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 \ + --hash=sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5 \ + --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \ + --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \ + --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68 +mergedeep==1.3.4 ; python_version >= "3.8" \ + --hash=sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8 \ + --hash=sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 +mkdocs-material-extensions==1.3.1 ; python_version >= "3.8" \ + --hash=sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443 \ + --hash=sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 +mkdocs-material==5.5.14 ; python_version >= "3.8" \ --hash=sha256:9f3237df1a72f91e0330a5e3b3711cb7aaa0d5705f9585e6ce6fbacaa16e777f \ --hash=sha256:a0b3b3e67606e04d13e777d13f3195402ea09e0c3ce279abc3666cac2c5b3a6d -mkdocs-minify-plugin==0.3.0 \ - --hash=sha256:06fecd8ddb9cb90f30bcee2d94c3d4b46a090f403d7ff0edff089a435906c4ee \ - --hash=sha256:9bac96276b1681debb3eb2cf5bae972586b4c1138e8d78ea63a984ea6276563d -mkdocs==1.1.2 \ - --hash=sha256:096f52ff52c02c7e90332d2e53da862fde5c062086e1b5356a6e392d5d60f5e9 \ - --hash=sha256:f0b61e5402b99d7789efa032c7a74c90a20220a9c81749da06dbfbcbd52ffb39 -nltk==3.5; python_version > "2.7" \ - --hash=sha256:845365449cd8c5f9731f7cb9f8bd6fd0767553b9d53af9eb1b3abf7700936b35 -pygments==2.7.3 \ - --hash=sha256:f275b6c0909e5dafd2d6269a656aa90fa58ebf4a74f8fcf9053195d226b24a08 \ - --hash=sha256:ccf3acacf3782cbed4a989426012f1c535c9a90d3a7fc3f16d231b9372d2b716 -pymdown-extensions==8.1 \ - --hash=sha256:565583c5964ac8253896ef4a7f14023075503ca6514d7d470b343290b96fc6da \ - --hash=sha256:c0b285fdd6e8438895b0c4422847af012f32a487ae083ffafa4c21a151b4983b -pyyaml==5.3.1 \ - --hash=sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f \ - --hash=sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76 \ - --hash=sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2 \ - --hash=sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c \ - --hash=sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2 \ - --hash=sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648 \ - --hash=sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a \ - --hash=sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf \ - --hash=sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97 \ - --hash=sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee \ - --hash=sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a \ - --hash=sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e \ - --hash=sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d -regex==2020.11.13 \ - --hash=sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85 \ - --hash=sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70 \ - --hash=sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee \ - --hash=sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5 \ - --hash=sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7 \ - --hash=sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31 \ - --hash=sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa \ - --hash=sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6 \ - --hash=sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e \ - --hash=sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884 \ - --hash=sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b \ - --hash=sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88 \ - --hash=sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0 \ - --hash=sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1 \ - --hash=sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0 \ - --hash=sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512 \ - --hash=sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba \ - --hash=sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538 \ - --hash=sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4 \ - --hash=sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444 \ - --hash=sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f \ - --hash=sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d \ - --hash=sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af \ - --hash=sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f \ - --hash=sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b \ - --hash=sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8 \ - --hash=sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5 \ - --hash=sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b \ - --hash=sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c \ - --hash=sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683 \ - --hash=sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc \ - --hash=sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364 \ - --hash=sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e \ - --hash=sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e \ - --hash=sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917 \ - --hash=sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b \ - --hash=sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9 \ - --hash=sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c \ - --hash=sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f \ - --hash=sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d \ - --hash=sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562 -requests==2.25.1 \ - --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e \ - --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 -six==1.15.0 \ - --hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced \ - --hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 -tornado==6.1 \ - --hash=sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32 \ - --hash=sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c \ - --hash=sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05 \ - --hash=sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910 \ - --hash=sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b \ - --hash=sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675 \ - --hash=sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5 \ - --hash=sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68 \ - --hash=sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb \ - --hash=sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c \ - --hash=sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921 \ - --hash=sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558 \ - --hash=sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c \ - --hash=sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085 \ - --hash=sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575 \ - --hash=sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795 \ - --hash=sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f \ - --hash=sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102 \ - --hash=sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4 \ - --hash=sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd \ - --hash=sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01 \ - --hash=sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d \ - --hash=sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df \ - --hash=sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37 \ - --hash=sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95 \ - --hash=sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a \ - --hash=sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5 \ - --hash=sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288 \ - --hash=sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f \ - --hash=sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6 \ - --hash=sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326 \ - --hash=sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c \ - --hash=sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5 \ - --hash=sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe \ - --hash=sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea \ - --hash=sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2 \ - --hash=sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0 \ - --hash=sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd \ - --hash=sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c \ - --hash=sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4 \ - --hash=sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791 -tornado==6.1; python_version > "2.7" \ - --hash=sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32 \ - --hash=sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c \ - --hash=sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05 \ - --hash=sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910 \ - --hash=sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b \ - --hash=sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675 \ - --hash=sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5 \ - --hash=sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68 \ - --hash=sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb \ - --hash=sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c \ - --hash=sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921 \ - --hash=sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558 \ - --hash=sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c \ - --hash=sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085 \ - --hash=sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575 \ - --hash=sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795 \ - --hash=sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f \ - --hash=sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102 \ - --hash=sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4 \ - --hash=sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd \ - --hash=sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01 \ - --hash=sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d \ - --hash=sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df \ - --hash=sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37 \ - --hash=sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95 \ - --hash=sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a \ - --hash=sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5 \ - --hash=sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288 \ - --hash=sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f \ - --hash=sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6 \ - --hash=sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326 \ - --hash=sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c \ - --hash=sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5 \ - --hash=sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe \ - --hash=sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea \ - --hash=sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2 \ - --hash=sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0 \ - --hash=sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd \ - --hash=sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c \ - --hash=sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4 \ - --hash=sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791 -tqdm==4.55.0 \ - --hash=sha256:0cd81710de29754bf17b6fee07bdb86f956b4fa20d3078f02040f83e64309416 \ - --hash=sha256:f4f80b96e2ceafea69add7bf971b8403b9cba8fb4451c1220f91c79be4ebd208 -typing-extensions==3.7.4.3; python_version < "3.8" \ - --hash=sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f \ - --hash=sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918 \ - --hash=sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c -urllib3==1.22 \ - --hash=sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b \ - --hash=sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f -werkzeug==1.0.1 \ - --hash=sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43 \ - --hash=sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c -zipp==3.4.0 \ - --hash=sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108 \ - --hash=sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb +mkdocs-minify-plugin==0.8.0 ; python_version >= "3.8" \ + --hash=sha256:5fba1a3f7bd9a2142c9954a6559a57e946587b21f133165ece30ea145c66aee6 \ + --hash=sha256:bc11b78b8120d79e817308e2b11539d790d21445eb63df831e393f76e52e753d +mkdocs==1.5.3 ; python_version >= "3.8" \ + --hash=sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1 \ + --hash=sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2 +nodeenv==1.8.0 ; python_version >= "3.8" \ + --hash=sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2 \ + --hash=sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec +packaging==24.0 ; python_version >= "3.8" \ + --hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \ + --hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9 +pathspec==0.12.1 ; python_version >= "3.8" \ + --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \ + --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712 +platformdirs==4.2.0 ; python_version >= "3.8" \ + --hash=sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068 \ + --hash=sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768 +pre-commit==1.21.0 ; python_version >= "3.8" \ + --hash=sha256:8f48d8637bdae6fa70cc97db9c1dd5aa7c5c8bf71968932a380628c25978b850 \ + --hash=sha256:f92a359477f3252452ae2e8d3029de77aec59415c16ae4189bcfba40b757e029 +pygments==2.17.2 ; python_version >= "3.8" \ + --hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \ + --hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367 +pymdown-extensions==10.7.1 ; python_version >= "3.8" \ + --hash=sha256:c70e146bdd83c744ffc766b4671999796aba18842b268510a329f7f64700d584 \ + --hash=sha256:f5cc7000d7ff0d1ce9395d216017fa4df3dde800afb1fb72d1c7d3fd35e710f4 +python-dateutil==2.9.0.post0 ; python_version >= "3.8" \ + --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ + --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 +pyyaml-env-tag==0.1 ; python_version >= "3.8" \ + --hash=sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb \ + --hash=sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069 +pyyaml==6.0.1 ; python_version >= "3.8" \ + --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ + --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ + --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ + --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ + --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ + --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ + --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ + --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ + --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ + --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ + --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ + --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ + --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ + --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ + --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ + --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ + --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ + --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ + --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ + --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ + --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ + --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ + --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ + --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ + --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \ + --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ + --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ + --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ + --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ + --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ + --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ + --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ + --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ + --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ + --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ + --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ + --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ + --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ + --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ + --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ + --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ + --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ + --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ + --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f +requests==2.31.0 ; python_version >= "3.8" \ + --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ + --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 +setuptools==69.5.1 ; python_version >= "3.8" \ + --hash=sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987 \ + --hash=sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32 +six==1.16.0 ; python_version >= "3.8" \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 +toml==0.10.2 ; python_version >= "3.8" \ + --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ + --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f +urllib3==2.2.1 ; python_version >= "3.8" \ + --hash=sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d \ + --hash=sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19 +virtualenv==20.25.1 ; python_version >= "3.8" \ + --hash=sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a \ + --hash=sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197 +watchdog==4.0.0 ; python_version >= "3.8" \ + --hash=sha256:11e12fafb13372e18ca1bbf12d50f593e7280646687463dd47730fd4f4d5d257 \ + --hash=sha256:2895bf0518361a9728773083908801a376743bcc37dfa252b801af8fd281b1ca \ + --hash=sha256:39cb34b1f1afbf23e9562501673e7146777efe95da24fab5707b88f7fb11649b \ + --hash=sha256:45cc09cc4c3b43fb10b59ef4d07318d9a3ecdbff03abd2e36e77b6dd9f9a5c85 \ + --hash=sha256:4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b \ + --hash=sha256:5369136a6474678e02426bd984466343924d1df8e2fd94a9b443cb7e3aa20d19 \ + --hash=sha256:557ba04c816d23ce98a06e70af6abaa0485f6d94994ec78a42b05d1c03dcbd50 \ + --hash=sha256:6a4db54edea37d1058b08947c789a2354ee02972ed5d1e0dca9b0b820f4c7f92 \ + --hash=sha256:6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269 \ + --hash=sha256:6a9c71a0b02985b4b0b6d14b875a6c86ddea2fdbebd0c9a720a806a8bbffc69f \ + --hash=sha256:6c47bdd680009b11c9ac382163e05ca43baf4127954c5f6d0250e7d772d2b80c \ + --hash=sha256:6e949a8a94186bced05b6508faa61b7adacc911115664ccb1923b9ad1f1ccf7b \ + --hash=sha256:73c7a935e62033bd5e8f0da33a4dcb763da2361921a69a5a95aaf6c93aa03a87 \ + --hash=sha256:76ad8484379695f3fe46228962017a7e1337e9acadafed67eb20aabb175df98b \ + --hash=sha256:8350d4055505412a426b6ad8c521bc7d367d1637a762c70fdd93a3a0d595990b \ + --hash=sha256:87e9df830022488e235dd601478c15ad73a0389628588ba0b028cb74eb72fed8 \ + --hash=sha256:8f9a542c979df62098ae9c58b19e03ad3df1c9d8c6895d96c0d51da17b243b1c \ + --hash=sha256:8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3 \ + --hash=sha256:9a03e16e55465177d416699331b0f3564138f1807ecc5f2de9d55d8f188d08c7 \ + --hash=sha256:ba30a896166f0fee83183cec913298151b73164160d965af2e93a20bbd2ab605 \ + --hash=sha256:c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935 \ + --hash=sha256:c522392acc5e962bcac3b22b9592493ffd06d1fc5d755954e6be9f4990de932b \ + --hash=sha256:d0f9bd1fd919134d459d8abf954f63886745f4660ef66480b9d753a7c9d40927 \ + --hash=sha256:d18d7f18a47de6863cd480734613502904611730f8def45fc52a5d97503e5101 \ + --hash=sha256:d31481ccf4694a8416b681544c23bd271f5a123162ab603c7d7d2dd7dd901a07 \ + --hash=sha256:e3e7065cbdabe6183ab82199d7a4f6b3ba0a438c5a512a68559846ccb76a78ec \ + --hash=sha256:eed82cdf79cd7f0232e2fdc1ad05b06a5e102a43e331f7d041e5f0e0a34a51c4 \ + --hash=sha256:f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245 \ + --hash=sha256:f9b2fdca47dc855516b2d66eef3c39f2672cbf7e7a42e7e67ad2cbfcd6ba107d +werkzeug==3.0.2 ; python_version >= "3.8" \ + --hash=sha256:3aac3f5da756f93030740bc235d3e09449efcf65f2f55e3602e1d851b8f48795 \ + --hash=sha256:e39b645a6ac92822588e7b39a692e7828724ceae0b0d702ef96701f90e70128d +zipp==3.18.1 ; python_version < "3.10" and python_version >= "3.8" \ + --hash=sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b \ + --hash=sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715 diff --git a/runtime.txt b/runtime.txt index 548d713..a02597f 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -3.7 \ No newline at end of file +3.9 \ No newline at end of file diff --git a/flask_googlemaps/tests/__init__.py b/tests/__init__.py similarity index 100% rename from flask_googlemaps/tests/__init__.py rename to tests/__init__.py diff --git a/tests/test_image.py b/tests/test_image.py new file mode 100644 index 0000000..dea6a37 --- /dev/null +++ b/tests/test_image.py @@ -0,0 +1,23 @@ +import pytest + +from flask_googlemaps.image import Image + + +@pytest.fixture +def image(): + return Image( + icon_url="https://developers.google.com/maps/documentation/" + "javascript/examples/full/images/beachflag.png" + ) + + +def test_content(image): + content = image.content() + assert content.startswith("var_") + assert len(content) == 12 + + +def test_dom_image_element(image): + variable, url_set = image.dom_element().split("\n") + assert variable == f"const {image.name} = document.createElement('img');" + assert url_set == f"{image.name}.src = '{image.icon_url}';" diff --git a/tests/test_map.py b/tests/test_map.py new file mode 100644 index 0000000..7a2888f --- /dev/null +++ b/tests/test_map.py @@ -0,0 +1,50 @@ +from typing import Dict, List, Any + +import pytest + +from flask_googlemaps import Map + + +@pytest.fixture +def map_properties() -> Dict[str, Any]: + return dict(identifier="gmap", varname="gmap", lat=37.4419, lng=-122.1419) + + +@pytest.fixture +def markers() -> List[Dict]: + return [ + { + "content": { + "icon_url": "http://maps.google.com/" + "mapfiles/ms/icons/green-dot.png" + }, + "latitude": 37.4419, + "longitude": -122.1419, + "infobox": "Hello World", + }, + { + "latitude": 37.4300, + "longitude": -122.1400, + "infobox": "Hello World from other place", + "content": { + "border_color": "", + "glyph_colors": "", + "background": "", + "glyph": "", + "scale": 2.0, + }, + }, + ] + + +def test_map_markers(markers: List[Dict], map_properties): + assert len(Map(markers=markers, **map_properties).markers) == 2 + + +def test_map_markers_expected_errors(markers: List[Dict], map_properties): + markers.append({"latitude": -1, "longitude": 250}) + with pytest.raises(AttributeError) as exception_info: + Map(markers=markers, **map_properties) + assert str(exception_info.value) == ( + "Longitude must be between -180 and 180 degrees inclusive." + ) diff --git a/tests/test_marker.py b/tests/test_marker.py new file mode 100644 index 0000000..4e0f8ae --- /dev/null +++ b/tests/test_marker.py @@ -0,0 +1,89 @@ +from typing import Dict + +import pytest + +from flask_googlemaps.marker import Marker +from flask_googlemaps.pin import Pin + + +@pytest.fixture +def coordinates() -> Dict[str, float]: + return dict(latitude=37.4419, longitude=-122.1419) + + +@pytest.fixture +def marker_pin_object(coordinates) -> Marker: + return Marker( + content=dict(border_color="", glyph_color="", background=""), + infobox="Hello World", + **coordinates + ) + + +@pytest.fixture +def marker_pin_url() -> Marker: + return Marker( + latitude=37.4419, + longitude=-122.1419, + content={ + "icon_url": "https://developers.google.com/maps/" + "documentation/javascript/examples/" + "full/images/beachflag.png" + }, + infobox="Hello World", + ) + + +def test_marker_without_lat_long(): + with pytest.raises(TypeError): + Marker() + + +def test_marker_with_wrong_latitude(): + with pytest.raises(AttributeError) as exception_info: + Marker(latitude=150, longitude=150) + assert str(exception_info.value) == ( + "Latitude must be between -90 and 90 degrees inclusive." + ) + + +def test_marker_with_wrong_longitude(): + with pytest.raises(AttributeError) as exception_info: + Marker(latitude=90, longitude=-190) + assert str(exception_info.value) == ( + "Longitude must be between -180 and 180 degrees inclusive." + ) + + +def test_marker_with_pin_object(marker_pin_object): + assert isinstance(marker_pin_object.marker_content, Pin) + + +def test_from_list_dictionary(coordinates): + markers = Marker.from_list([coordinates]) + for marker in markers: + assert isinstance(marker, Marker) + + +def test_from_list_tuple(coordinates): + markers = Marker.from_list( + [(coordinates["latitude"], coordinates["longitude"])] + ) + for marker in markers: + assert isinstance(marker, Marker) + + +def test_from_list_mixed_tuple_dict(coordinates): + markers = Marker.from_list( + [(coordinates["latitude"], coordinates["longitude"]), coordinates] + ) + for marker in markers: + assert isinstance(marker, Marker) + + +def test_from_list_type_error(coordinates): + with pytest.raises(TypeError) as exception_info: + Marker.from_list([[coordinates["latitude"], coordinates["longitude"]]]) + assert str(exception_info.value) == ( + "Marker must be either a dict or a tuple." + ) diff --git a/tests/test_marker_content_factory.py b/tests/test_marker_content_factory.py new file mode 100644 index 0000000..6ebbb03 --- /dev/null +++ b/tests/test_marker_content_factory.py @@ -0,0 +1,18 @@ +from flask_googlemaps.marker_content_factory import MarkerContentFactory +from flask_googlemaps.pin import Pin + + +def test_marker_content_unknown_keys(): + marker_content_factory = MarkerContentFactory(**{"bla": "bla"}) + marker_content = marker_content_factory.marker_content + assert isinstance(marker_content, Pin) + assert marker_content.dom_element() is None + + +def test_marker_content_unknown(): + marker_content_factory = MarkerContentFactory( + **{"background": "", "glyph_colors": ""} + ) + marker_content = marker_content_factory.marker_content + assert isinstance(marker_content, Pin) + assert marker_content.dom_element() is None diff --git a/tests/test_pin.py b/tests/test_pin.py new file mode 100644 index 0000000..0e7286b --- /dev/null +++ b/tests/test_pin.py @@ -0,0 +1,63 @@ +import json + +import pytest + +from flask_googlemaps.pin import Pin, PinPropertyMapping + + +@pytest.fixture +def empty_pin(): + return Pin() + + +@pytest.fixture +def pin(): + return Pin(border_color="red", scale=2.0) + + +def test_content_empty(empty_pin): + content = empty_pin.content() + assert content == "" + + +def test_content(pin): + content = pin.content() + assert content.startswith("var_") + assert len(content) == 20 + + +@pytest.mark.parametrize( + "p", + [ + Pin(border_color="blue", scale=3.0), + Pin(background="red", glyph_color="black", scale=2.0), + Pin(glyph="Test", border_color="red"), + ], +) +def test_dom_element(p): + dom_element = p.dom_element() + _, js_element = dom_element.split(" = ") + + js_element = js_element_to_dict(js_element) + reversed_dict = {item.value: item.name for item in list(PinPropertyMapping)} + + for property_name, value in js_element.items(): + if property_name == "scale": + value = float(value) + assert value == p.__getattribute__(reversed_dict[property_name]) + + +def js_element_to_dict(js_element: str) -> dict: + js_element = ( + js_element.strip("new PinElement(") + .strip(");\n") + .replace("\n", "") + .replace("\t", "") + .replace("'", '"') + .replace("{", '{"') + .replace(",}", "}") + .replace(",", ',"') + .replace(":", '":') + ) + + return json.loads(js_element) diff --git a/tests/test_version.py b/tests/test_version.py index b1a1b1f..e5ef562 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -2,4 +2,4 @@ def test_version(): - assert __version__ == "0.4.1" + assert __version__ == "0.5.0"