Skip to content

Commit

Permalink
Merge pull request #1015 from ocefpaf/firefox_headless
Browse files Browse the repository at this point in the history
Use firefox headless instead of phantomjs
  • Loading branch information
ocefpaf authored Nov 20, 2018
2 parents 48aa49e + 86f87c2 commit 8adfb77
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 67 deletions.
63 changes: 34 additions & 29 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,37 @@ Whenever possible, please also include a [short, self-contained code example](ht

First of all, thanks for your interest in contributing!

- If you are new to git/Github, please take check a few tutorials
on [git](https://git-scm.com/docs/gittutorial) and [GitHub](https://guides.github.com/).
- The basic workflow for contributing is:
1. [Fork](https://help.github.com/articles/fork-a-repo/) the repository
2. [Clone](https://help.github.com/articles/cloning-a-repository/) the repository to create a local copy on your computer:
```
git clone [email protected]:${user}/folium.git
cd folium
```
3. Create a branch for your changes
```
git checkout -b name-of-your-branch
```
4. Make change to your local copy of the folium repository
5. Make sure the tests pass:
* in the repository folder do `pip install -e .` (needed for notebook tests)
* along with all the dependencies install `phantomjs` via `npm install -g phantomjs` or by downloading it from [here](http://phantomjs.org/download.html) and installing manually
* run `python -m pytest tests`
* resolve all errors
6. Commit those changes
```
git add file1 file2 file3
git commit -m 'a descriptive commit message'
```
7. Push your updated branch to your fork
```
git push origin name-of-your-branch
```
8. [Open a pull request](https://help.github.com/articles/creating-a-pull-request/) to the python-visualization/folium
If you are new to git/Github, please take check a few tutorials
on [git](https://git-scm.com/docs/gittutorial) and [GitHub](https://guides.github.com/).

The basic workflow for contributing is:

1. [Fork](https://help.github.com/articles/fork-a-repo/) the repository
2. [Clone](https://help.github.com/articles/cloning-a-repository/) the repository to create a local copy on your computer:
```
git clone [email protected]:${user}/folium.git
cd folium
```
3. Create a branch for your changes
```
git checkout -b name-of-your-branch
```
4. Install the dependencies listed in `requirements.txt` and `requirements-dev.txt`.
5. Install Firefox, download [geckodriver](https://github.com/mozilla/geckodriver/releases)
and put it in the PATH.
6. Make changes to your local copy of the folium repository
7. Make sure the tests pass:
* in the repository folder do `pip install -e .` (needed for notebook tests)
* run `python -m pytest tests`
* run `flake8 folium --max-line-length=120`
* resolve all errors
8. Commit those changes
```
git add file1 file2 file3
git commit -m 'a descriptive commit message'
```
9. Push your updated branch to your fork
```
git push origin name-of-your-branch
```
10. [Open a pull request](https://help.github.com/articles/creating-a-pull-request/) to the python-visualization/folium
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ examples/results/*
/codestyles/*.xml
/_mac/*.xml
/inspection/*.xml
geckodriver.log
13 changes: 12 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ language: minimal

sudo: false

env:
- MOZ_HEADLESS=1

addons:
firefox: latest

env:
global:
- secure: "gRT413onDOvwgiHpNXRsiqo+ZZSjwwBpjZryQ9h6IqYw6cTN9YVivYF15uTMD//mZyFeHRz+F/7/0EG2z+UYIBKbgktiNMbie/KizwRBnCThGpcch1VeizkBkPluWSQXndXM6STkHvn0eZBZBBh0QdTm1qaI0babUmgZuWhrX38="
Expand Down Expand Up @@ -31,8 +37,13 @@ before_install:
- conda update conda
- conda config --remove channels defaults --force
- conda config --add channels conda-forge --force
- conda create --name TEST python=$PY phantomjs --file requirements.txt --file requirements-dev.txt
- conda create --name TEST python=$PY --file requirements.txt --file requirements-dev.txt
- source activate TEST
# firefox headless driver
- wget https://github.com/mozilla/geckodriver/releases/download/v0.23.0/geckodriver-v0.23.0-linux64.tar.gz -O geckodriver.tar.gz
- mkdir geckodriver
- tar -xzf geckodriver.tar.gz -C geckodriver
- export PATH=$PATH:$PWD/geckodriver

- if [[ "$PY" == "2.7" ]]; then
conda install mock ;
Expand Down
40 changes: 17 additions & 23 deletions folium/folium.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@

from __future__ import (absolute_import, division, print_function)

import os
import time
import warnings

from branca.element import CssLink, Element, Figure, JavascriptLink, MacroElement

from folium.map import FitBounds
from folium.raster_layers import TileLayer
from folium.utilities import _parse_size, _validate_location
from folium.utilities import _parse_size, _tmp_html, _validate_location

from jinja2 import Environment, PackageLoader, Template

Expand Down Expand Up @@ -202,10 +201,10 @@ class Map(MacroElement):
zoomControl: {{this.zoom_control.__str__().lower()}},
});
{% if this.control_scale %}L.control.scale().addTo({{this.get_name()}});{% endif %}
{% if this.objects_to_stay_in_front %}
function objects_in_front() {
{% for obj in this.objects_to_stay_in_front %}
{% for obj in this.objects_to_stay_in_front %}
{{ obj.get_name() }}.bringToFront();
{% endfor %}
};
Expand Down Expand Up @@ -290,35 +289,30 @@ def _repr_html_(self, **kwargs):
def _to_png(self, delay=3):
"""Export the HTML to byte representation of a PNG image.
Uses Phantom JS to render the HTML and record a PNG. You may need to
Uses selenium to render the HTML and record a PNG. You may need to
adjust the `delay` time keyword argument if maps render without data or tiles.
Examples
--------
>>> map._to_png()
>>> map._to_png(time=10) # Wait 10 seconds between render and snapshot.
"""
"""
if self._png_image is None:
import selenium.webdriver
from selenium import webdriver

options = webdriver.firefox.options.Options()
options.add_argument('--headless')
driver = webdriver.Firefox(options=options)

driver = selenium.webdriver.PhantomJS(
service_log_path=os.path.devnull
)
driver.get('about:blank')
html = self.get_root().render()
html = html.replace('\'', '"').replace('"', '\\"')
html = html.replace('\n', '')
driver.execute_script('document.write(\"{}\")'.format(html))
driver.maximize_window()
# Ignore user map size.
# todo: fix this
# driver.execute_script("document.body.style.width = '100%';") # noqa
# We should probably monitor if some element is present,
# but this is OK for now.
time.sleep(delay)
png = driver.get_screenshot_as_png()
driver.quit()
with _tmp_html(html) as fname:
# We need the tempfile to avoid JS security issues.
driver.get('file:///{path}'.format(path=fname))
driver.maximize_window()
time.sleep(delay)
png = driver.get_screenshot_as_png()
driver.quit()
self._png_image = png
return self._png_image

Expand Down
16 changes: 16 additions & 0 deletions folium/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
import math
import os
import struct
import tempfile
import zlib
from contextlib import contextmanager

import numpy as np

Expand Down Expand Up @@ -385,3 +387,17 @@ def iter_points(x):
return [x]
else:
return []


@contextmanager
def _tmp_html(data):
"""Yields the path of a temporary HTML file containing data."""
filepath = ''
try:
fid, filepath = tempfile.mkstemp(suffix='.html', prefix='folium_')
os.write(fid, data.encode('utf8'))
os.close(fid)
yield filepath
finally:
if os.path.isfile(filepath):
os.remove(filepath)
32 changes: 18 additions & 14 deletions tests/test_repr.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

from __future__ import (absolute_import, division, print_function)

import sys
import io
import sys

import PIL.Image

Expand All @@ -19,18 +19,22 @@


@pytest.fixture
def make_map(png_enabled=False):
m = folium.Map(png_enabled=png_enabled)
return m
def m():
yield folium.Map(png_enabled=False)


@pytest.fixture
def m_png():
yield folium.Map(png_enabled=True)


def test__repr_html_is_str():
html = make_map()._repr_html_()
def test__repr_html_is_str(m):
html = m._repr_html_()
assert isinstance(html, str)


def test_valid_html():
html = make_map()._repr_html_()
def test_valid_html(m):
html = m._repr_html_()
parts = html.split('><')
assert len(parts) == 6
assert parts[0].lstrip('<div ') == 'style="width:100%;"'
Expand All @@ -41,19 +45,19 @@ def test_valid_html():
assert parts[5] == '/div>'


def test__repr_png_no_image():
png = make_map(png_enabled=False)._repr_png_()
def test__repr_png_no_image(m):
png = m._repr_png_()
assert png is None


def test__repr_png_is_bytes():
png = make_map(png_enabled=True)._repr_png_()
def test__repr_png_is_bytes(m_png):
png = m_png._repr_png_()
assert isinstance(png, bytes)


@pytest.mark.skipif(sys.version_info < (3, 0),
reason="Doesn't work on Python 2.7.")
def test_valid_png():
png = make_map(png_enabled=True)._repr_png_()
def test_valid_png(m_png):
png = m_png._repr_png_()
img = PIL.Image.open(io.BytesIO(png))
isinstance(img, PIL.PngImagePlugin.PngImageFile)

0 comments on commit 8adfb77

Please sign in to comment.