Repository: cuducos/webassets-elm (language: python)

Issue:
Full switch to elm 0.19
This is perhaps a big change, but adding support for elm 0.19 and keeping backward compatibility with `elm-make` (elm <= 0.18) is not worth the effort in my opinion.

Instead, those that still need to work with the older elm releases could just pin `webassets-elm` to a previous release.

This would fully resolve #8 


Discussion / hints:

Fix patch:
diff --git a/.landscape.yml b/.landscape.yml
deleted file mode 100644
index b5cab02..0000000
--- a/.landscape.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-strictness: veryhigh
-python-targets:
-  - 2
-  - 3
-pep8:
-  full: true
diff --git a/.travis.yml b/.travis.yml
index c163144..8223055 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,29 +1,20 @@
+dist: xenial  # support for Python >= 3.7
 language: python
-sudo: false
-
-branches:
-  only:
-    - master
-
 python:
-  - "3.6"
+  - 3.5
+  - 3.6
+  - 3.7
 
 matrix:
   include:
-    - python: 3.5
-      env:
-      - TOXENV=py35
-
-env:
-  - TOXENV=py33
-  - TOXENV=py34
-  - TOXENV=py36
-  - TOXENV=cover
+    - python: "3.7"
+      env: TOXENV=cover
+    - python: "3.7"
+      env: TOXENV=black
 
 install:
   - npm i -g elm
-  - elm-package install --yes
-  - pip install tox
+  - pip install tox-travis
 
 script:
   - tox
diff --git a/CHANGELOG b/CHANGELOG
index d95ebc8..441c7fe 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,10 @@
 # Changelog
 
+**0.2.0**
+  * Added support for Elm 0.19 (including `--optimize` and `--debug` options)
+  * Drop support for Elm 0.18 and older Elm versions
+  * Drop support for Python 3.3 and 3.4
+  * Drop `ELM_MAKE_CHANGE_DIRECTORY` setting
 **0.1.7**
   * Add option to change directory before running `elm-make`
 **0.1.6**
diff --git a/LICENSE b/LICENSE
index 74160b8..edb8e71 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright 2017 Eduardo Cuducos
+Copyright 2019 Eduardo Cuducos
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
diff --git a/README.rst b/README.rst
index 224e31c..89a3163 100644
--- a/README.rst
+++ b/README.rst
@@ -1,6 +1,3 @@
-Elm filter for webassets
-########################
-
 .. image:: https://img.shields.io/travis/cuducos/webassets-elm.svg?style=flat
   :target: https://travis-ci.org/cuducos/webassets-elm
   :alt: Travis CI
@@ -9,12 +6,6 @@ Elm filter for webassets
   :target: https://coveralls.io/github/cuducos/webassets-elm
   :alt: Covearge
 
-.. image:: https://landscape.io/github/cuducos/webassets-elm/master/landscape.svg?style=flat
-  :target: https://landscape.io/github/cuducos/webassets-elm/master
-  :alt: Code Health
-
-Filter for compiling `Elm <http://elm-lang.org>`_ files using `webassets <http://webassets.readthedocs.org>`_.
-
 .. image:: https://img.shields.io/pypi/status/webassets-elm.svg?style=flat
   :target: https://pypi.python.org/pypi/webassets-elm
   :alt: Status
@@ -31,6 +22,11 @@ Filter for compiling `Elm <http://elm-lang.org>`_ files using `webassets <http:/
   :target: https://pypi.python.org/pypi/webassets-elm
   :alt: License
 
+Elm filter for webassets
+########################
+
+Filter for compiling `Elm <http://elm-lang.org>`_ files using `webassets <http://webassets.readthedocs.org>`_.
+
 Install
 *******
 
@@ -38,6 +34,10 @@ Install
 
     pip install webassets-elm
 
+As of version 0.2.0, this plugin requires **Elm 0.19** or newer (building with ``elm make``).
+
+If you need to build your Elm project with ``elm-make`` (Elm 0.18 and older), you can pin your ``webassets-elm`` package to version ``0.1.7``.
+
 Basic usage
 ***********
 
@@ -53,9 +53,11 @@ Settings
 
 **Optionally** as an evironment variable you can have:
 
-* `ELM_MAKE_BIN`: alternative path to `elm-make` if it is **not** available globally (e.g. `node_modules/.bin/elm-make`) 
+* ``ELM_BIN``: alternative path to ``elm`` if it is **not** available globally (e.g. ``node_modules/.bin/elm``).
 
-* `ELM_MAKE_CHANGE_DIRECTORY`: if set the filter will switch to `source_path` directory (where the main `.elm` is located) prior to compilation
+* ``ELM_OPTIMIZE``: enable the Elm compiler optimization option. Recommended for production output.
+
+* ``ELM_DEBUG``: enable the Elm compiler debug option.
 
 Examples
 ========
@@ -97,14 +99,11 @@ Contributing
 
 Feel free to `report an issue <http://github.com/cuducos/webassets-elm/issues>`_, `open a pull request <http://github.com/cuducos/webassets-elm/pulls>`_, or `drop a line <http://twitter.com/cuducos>`_.
 
-Don't forget to write and run tests:
+Don't forget to write and run tests, and format code with `Black <https://black.readthedocs.io/>`_:
 
 ::
 
     python setup.py test
+    black .
 
-You need `elm` binaries available to run tests. `Install Elm <http://elm-lang.org/install>`_ and then the required packages:
-
-::
-
-    elm-package install
\ No newline at end of file
+Please note you need ``elm`` binary available to run tests, here you can find different ways to `install Elm <http://elm-lang.org/install>`_.
\ No newline at end of file
diff --git a/elm-package.json b/elm-package.json
deleted file mode 100644
index f5ba1c5..0000000
--- a/elm-package.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "version": "1.0.0",
-    "summary": "helpful summary of your project, less than 80 characters",
-    "repository": "https://github.com/user/project.git",
-    "license": "BSD3",
-    "source-directories": [
-        "."
-    ],
-    "exposed-modules": [],
-    "dependencies": {
-        "elm-lang/core": "5.1.1 <= v < 6.0.0",
-        "elm-lang/html": "2.0.0 <= v < 3.0.0"
-    },
-    "elm-version": "0.18.0 <= v < 0.19.0"
-}
diff --git a/setup.py b/setup.py
index 54951f9..b8fc0a3 100644
--- a/setup.py
+++ b/setup.py
@@ -1,32 +1,32 @@
+from pathlib import Path
 from setuptools import setup, find_packages
 
-with open('README.rst') as readme:
 
-    setup(
-        author='Eduardo Cuducos',
-        author_email='cuducos@gmail.com',
-        classifiers=[
-            'Development Status :: 4 - Beta',
-            'Environment :: Web Environment',
-            'Framework :: Django',
-            'Framework :: Flask',
-            'Intended Audience :: Developers',
-            'License :: OSI Approved :: MIT License',
-            'Programming Language :: Python :: 3.3',
-            'Programming Language :: Python :: 3.4',
-            'Programming Language :: Python :: 3.5',
-            'Programming Language :: Python :: 3.6'
-        ],
-        description='Elm filter for webassets',
-        install_requires=['webassets'],
-        keywords=['elm', 'webassets', 'assets', 'django', 'flask'],
-        license='MIT',
-        long_description=readme.read(),
-        name='webassets-elm',
-        packages=find_packages(),
-        test_suite='nose.collector',
-        tests_require=['nose'],
-        url='https://github.com/cuducos/webassets-elm',
-        version='0.1.7',
-        zip_safe=False
-    )
+setup(
+    author="Eduardo Cuducos",
+    author_email="cuducos@gmail.com",
+    classifiers=[
+        "Development Status :: 4 - Beta",
+        "Environment :: Web Environment",
+        "Framework :: Django",
+        "Framework :: Flask",
+        "Intended Audience :: Developers",
+        "License :: OSI Approved :: MIT License",
+        "Programming Language :: Python :: 3.5",
+        "Programming Language :: Python :: 3.6",
+        "Programming Language :: Python :: 3.7",
+    ],
+    python_requires=">=3.5",
+    description="Elm filter for webassets",
+    install_requires=["webassets"],
+    keywords=["elm", "webassets", "assets", "django", "flask"],
+    license="MIT",
+    long_description=Path("README.rst").read_text(),
+    name="webassets-elm",
+    packages=find_packages(),
+    test_suite="nose.collector",
+    tests_require=["nose"],
+    url="https://github.com/cuducos/webassets-elm",
+    version="0.2.0",
+    zip_safe=False,
+)
diff --git a/tox.ini b/tox.ini
index 95d8041..0dadb4a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,17 +1,23 @@
 [tox]
-envlist = py33, py34, py35, py36
+envlist = py35, py36, py37
 
 [testenv]
 commands = nosetests
 deps =
     nose
     webassets
+setenv = HOME = {envtmpdir}
+
+[testenv:black]
+deps = black
+commands = black . --check
 
 [testenv:cover]
 passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH
 deps =
     {[testenv]deps}
     coveralls
+setenv = HOME = {envtmpdir}
 commands =
     nosetests --with-cover --cover-package=webassets_elm
     coveralls
diff --git a/webassets_elm.py b/webassets_elm.py
new file mode 100644
index 0000000..a9717a8
--- /dev/null
+++ b/webassets_elm.py
@@ -0,0 +1,55 @@
+from io import StringIO
+from pathlib import Path
+from tempfile import TemporaryDirectory
+
+from webassets.filter import ExternalTool
+
+__all__ = ("Elm",)
+
+
+class Elm(ExternalTool):
+    """Elm filter for webassets.
+
+    Requires the ``elm-make`` to be available from the system path.
+
+    Supports the following external configuration:
+
+    ELM_BIN (string, path to Elm binary)
+        The path to the ``elm`` binary. If not set, assumes ``elm``
+        is in the system path.
+
+    ELM_OPTIMIZE (boolean)
+        If set to True, turns on the Elm compiler optimizations.
+
+    ELM_DEBUG (boolean)
+        If set to True, turns on the Elm compiler time traveling debugger
+        option.
+
+    """
+
+    name = "elm"
+    options = {"binary": "ELM_BIN", "optimize": "ELM_OPTIMIZE", "debug": "ELM_DEBUG"}
+    max_debug_level = None
+
+    def input(self, _in, out, **kw):
+        """Currently Elm does not write to stdout
+        (https://github.com/elm-lang/elm-make/issues/177), so we need to
+        write the compiled contents to a temporary file and then read it in
+        order to output to stdout."""
+        elm = self.binary or "elm"
+        source = Path(kw["source_path"])
+
+        assert source.exists()
+        assert source.is_file()
+
+        command = [elm, "make", str(source)]
+        if self.optimize:
+            command.append("--optimize")
+        if self.debug:
+            command.append("--debug")
+
+        with TemporaryDirectory() as directory, StringIO() as buffer_:
+            compiled = Path(directory) / "output.js"
+            command.extend(["--output", str(compiled)])
+            self.subprocess(command, buffer_, cwd=str(source.parent))
+            print(compiled.read_text(), file=out)
diff --git a/webassets_elm/__init__.py b/webassets_elm/__init__.py
deleted file mode 100644
index 5648cd0..0000000
--- a/webassets_elm/__init__.py
+++ /dev/null
@@ -1,70 +0,0 @@
-from contextlib import contextmanager
-import os
-import os.path
-from sys import platform
-from tempfile import NamedTemporaryFile, TemporaryFile
-
-from webassets.filter import ExternalTool
-
-__all__ = ('Elm')
-
-
-@contextmanager
-def excursion(directory):
-    """Context-manager that temporarily changes to a new working directory."""
-    old_dir = os.getcwd()
-    try:
-        os.chdir(directory)
-        yield
-    finally:
-        os.chdir(old_dir)
-
-
-class Elm(ExternalTool):
-    """Elm filter for webassets.
-
-    Requires the ``elm-make`` to be available from the system path.
-
-    Supports the following external configuration:
-
-    ELM_MAKE_BIN
-        The path to the ``elm-make`` binary. If not set, assumes ``elm-make``
-        is in the system path.
-
-    ELM_MAKE_CHANGE_DIRECTORY
-        If set the filter will switch to ``source_path`` directory prior to
-        compilation.
-
-    """
-
-    name = 'elm'
-    options = {'binary': 'ELM_MAKE_BIN',
-               'change_directory': 'ELM_MAKE_CHANGE_DIRECTORY'}
-    max_debug_level = None
-
-    def input(self, _in, out, **kw):
-        """
-        Currently Elm does not write to stdout
-        (https://github.com/elm-lang/elm-make/issues/39), so we need to write
-        the compiled contents to a temporary file and then read it in order to
-        output to stdout.
-        """
-        # create a temp file
-        tmp = NamedTemporaryFile(suffix='.js', delete=False)
-        tmp.close()  # close it so windows can read it
-
-        # write to a temp file
-        elm_make = self.binary or 'elm-make'
-        change_directory = bool(self.change_directory or False)
-        source = kw['source_path']
-        source_dir = os.path.dirname(source)
-        exec_dir = source_dir if change_directory else os.getcwd()
-        write_args = [elm_make, source, '--output', tmp.name, '--yes']
-        with excursion(exec_dir), TemporaryFile(mode='w') as fake_write_obj:
-            self.subprocess(write_args, fake_write_obj)
-
-        # read the temp file
-        cat_or_type = 'type' if platform == 'win32' else 'cat'
-        read_args = [cat_or_type, tmp.name]
-        self.subprocess(read_args, out)
-        os.remove(tmp.name)


Test patch:
diff --git a/tests/Main.elm b/tests/Main.elm
new file mode 100644
index 0000000..d84b0b4
--- /dev/null
+++ b/tests/Main.elm
@@ -0,0 +1,7 @@
+module Main exposing (main)
+
+import Html exposing (h1, text)
+
+
+main =
+    h1 [] [ text "I ❤️ Elm" ]
diff --git a/tests/elm.json b/tests/elm.json
new file mode 100644
index 0000000..e3ac4b3
--- /dev/null
+++ b/tests/elm.json
@@ -0,0 +1,14 @@
+{
+    "type": "package",
+    "name": "webassets-elm/test",
+    "summary": "this is only here because we want to be able to run tests",
+    "license": "BSD-3-Clause",
+    "version": "1.0.0",
+    "exposed-modules": [],
+    "elm-version": "0.19.0 <= v < 0.20.0",
+    "dependencies": {
+        "elm/core": "1.0.0 <= v < 2.0.0",
+        "elm/html": "1.0.0 <= v < 2.0.0"
+    },
+    "test-dependencies": {}
+}
diff --git a/tests/test_filter.py b/tests/test_filter.py
new file mode 100644
index 0000000..b583fa6
--- /dev/null
+++ b/tests/test_filter.py
@@ -0,0 +1,36 @@
+from pathlib import Path
+from unittest import TestCase
+
+from webassets.filter import register_filter
+from webassets.test import TempEnvironmentHelper
+from webassets_elm import Elm
+
+MAIN = Path(__file__).parent / "Main.elm"
+JSON = Path(__file__).parent / "elm.json"
+
+register_filter(Elm)
+
+
+class ElmFilterTestCase(TempEnvironmentHelper, TestCase):
+    default_files = {"Main.elm": MAIN.read_text(), "elm.json": JSON.read_text()}
+
+    def setUp(self):
+        super(ElmFilterTestCase, self).setup()
+
+    def test_elm_filter(self):
+        self.mkbundle("Main.elm", filters="elm", output="app.js").build()
+        self.assertIn("I ❤️ Elm", self.get("app.js"))
+        self.assertIn("Compiled in DEV mode", self.get("app.js"))
+        self.assertNotIn("Compiled in DEBUG mode", self.get("app.js"))
+
+    def test_elm_filter_optimized(self):
+        self.env.config["ELM_OPTIMIZE"] = True
+        self.mkbundle("Main.elm", filters="elm", output="app.js").build()
+        self.assertNotIn("Compiled in DEV mode", self.get("app.js"))
+        self.assertNotIn("Compiled in DEBUG mode", self.get("app.js"))
+
+    def test_elm_filter_debug(self):
+        self.env.config["ELM_DEBUG"] = True
+        self.mkbundle("Main.elm", filters="elm", output="app.js").build()
+        self.assertNotIn("Compiled in DEV mode", self.get("app.js"))
+        self.assertIn("Compiled in DEBUG mode", self.get("app.js"))
diff --git a/webassets_elm/tests.py b/webassets_elm/tests.py
deleted file mode 100644
index 334ac2b..0000000
--- a/webassets_elm/tests.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from unittest import TestCase
-from webassets.filter import register_filter
-from webassets.test import TempEnvironmentHelper
-from webassets_elm import Elm
-
-
-register_filter(Elm)
-
-
-class ElmFilterTestCase(TempEnvironmentHelper, TestCase):
-
-    elm_code = 'import Html exposing (h1, text)\nmain = h1 [] [text "I<3elm"]'
-    default_files = {'main.elm': elm_code}
-
-    def setUp(self):
-        super(ElmFilterTestCase, self).setup()
-
-    def test_elm_filter(self):
-        self.mkbundle('main.elm', filters='elm', output='app.js').build()
-        self.assertIn('I<3elm', self.get('app.js'))