Repository: pytorch/ignite

Issue:
Terminate on Nan tests fail with pytorch-nightly
https://travis-ci.org/vfdev-5/ignite/builds/458179313

Discussion:
vfdev-5: @jasonkriss , @alykhantejani what do you think about if we extend testing grid to 
- py27, py35, py36
-  pytorch 0.4.1 , 1.0-preview

I would say this extends the testing by ~ 8 mins as in Tests travis allows to run on 5 machines in parallel and we have 6 cases.

alykhantejani: hmm, running on 1.0-preview is probably good. 8 minutes seems crazy long though. Do we need to test py35 and py36?

Patch:
diff --git a/.travis.yml b/.travis.yml
index b50ef8a2..cb967eb1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,11 @@ language: python
 
 python:
   - "2.7"
-  - "3.5"
+  - "3.6"
+
+env:
+  - PYTORCH_PACKAGE=pytorch-cpu
+  - PYTORCH_PACKAGE=pytorch-nightly-cpu
 
 stages:
   - Lint check
@@ -20,7 +24,7 @@ before_install: &before_install
   - conda update -q conda
   # Useful for debugging any issues with conda
   - conda info -a
-  - conda create -q -n test-environment -c pytorch python=$TRAVIS_PYTHON_VERSION pytorch-cpu
+  - conda create -q -n test-environment -c pytorch python=$TRAVIS_PYTHON_VERSION $PYTORCH_PACKAGE
   - source activate test-environment
   - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then pip install enum34; fi
   # Test contrib dependencies
@@ -106,6 +110,8 @@ jobs:
 
     - stage: Deploy
       python: "3.5"
+      env:
+        - PYTORCH_PACKAGE=pytorch-cpu
       if: tag IS present
 
       # Use previously defined before_install
diff --git a/ignite/_six.py b/ignite/_six.py
new file mode 100644
index 00000000..a68e8999
--- /dev/null
+++ b/ignite/_six.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2010-2017 Benjamin Peterson
+#
+# 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:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+def with_metaclass(meta, *bases):
+    """Create a base class with a metaclass."""
+    # This requires a bit of explanation: the basic idea is to make a dummy
+    # metaclass for one level of class instantiation that replaces itself with
+    # the actual metaclass.
+    class metaclass(meta):
+
+        def __new__(cls, name, this_bases, d):
+            return meta(name, bases, d)
+    return type.__new__(metaclass, 'temporary_class', (), {})
diff --git a/ignite/metrics/metric.py b/ignite/metrics/metric.py
index 03b6e2c2..1f367029 100644
--- a/ignite/metrics/metric.py
+++ b/ignite/metrics/metric.py
@@ -1,11 +1,10 @@
 from abc import ABCMeta, abstractmethod
-
+from ignite._six import with_metaclass
 from ignite.engine import Events
-
 import torch
 
 
-class Metric(object):
+class Metric(with_metaclass(ABCMeta, object)):
     """
     Base class for all Metrics.
 
@@ -16,7 +15,6 @@ class Metric(object):
             you want to compute the metric with respect to one of the outputs.
 
     """
-    __metaclass__ = ABCMeta
 
     def __init__(self, output_transform=lambda x: x):
         self._output_transform = output_transform


Test patch:
diff --git a/tests/ignite/handlers/test_terminate_on_nan.py b/tests/ignite/handlers/test_terminate_on_nan.py
index 2c6a6044..b122b450 100644
--- a/tests/ignite/handlers/test_terminate_on_nan.py
+++ b/tests/ignite/handlers/test_terminate_on_nan.py
@@ -41,7 +41,7 @@ def test_terminate_on_nan_and_inf():
     assert trainer.should_terminate
     trainer.should_terminate = False
 
-    trainer.state.output = (10.0, 1.0 / torch.randint(0, 2, size=(4,)), 1.0)
+    trainer.state.output = (10.0, 1.0 / torch.randint(0, 2, size=(4,)).type(torch.float), 1.0)
     h(trainer)
     assert trainer.should_terminate
     trainer.should_terminate = False
@@ -50,7 +50,7 @@ def test_terminate_on_nan_and_inf():
     h(trainer)
     assert not trainer.should_terminate
 
-    trainer.state.output = 1.0 / torch.randint(0, 2, size=(4, 4))
+    trainer.state.output = 1.0 / torch.randint(0, 2, size=(4, 4)).type(torch.float)
     h(trainer)
     assert trainer.should_terminate
     trainer.should_terminate = False
@@ -95,7 +95,7 @@ def test_with_terminate_on_inf():
     torch.manual_seed(12)
 
     data = [1.0, 0.8, torch.rand(4, 4),
-            (1.0 / torch.randint(0, 2, size=(4,)), torch.tensor(1.234)),
+            (1.0 / torch.randint(0, 2, size=(4,)).type(torch.float), torch.tensor(1.234)),
             torch.rand(5), torch.asin(torch.randn(4, 4)), 0.0, 1.0]
 
     def update_fn(engine, batch):
diff --git a/tests/ignite/metrics/test_metric.py b/tests/ignite/metrics/test_metric.py
index 675169b8..371f2581 100644
--- a/tests/ignite/metrics/test_metric.py
+++ b/tests/ignite/metrics/test_metric.py
@@ -2,6 +2,7 @@ from ignite.metrics import Metric
 from ignite.engine import Engine, State
 import torch
 from mock import MagicMock
+from pytest import raises
 
 
 def test_no_transform():
@@ -113,3 +114,8 @@ def test_attach():
     assert m2.reset_count == 5
     assert m2.compute_count == 10
     assert m2.update_count == 50
+
+
+def test_abstract_class():
+    with raises(TypeError):
+        Metric()