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. 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:
-### 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!"
"
@@ -161,7 +162,7 @@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çalYou 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>