diff --git a/.travis.yml b/.travis.yml
index 46a1b13..a88237d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,6 +11,9 @@ python:
   - "3.5"
   - "3.5-dev" # 3.5 development branch
   - "nightly" # currently points to 3.6-dev
+matrix:
+  allow_failures:
+    - python: nightly
 install:
  - pip install unittest2 pylint
 script:
diff --git a/dns/name.py b/dns/name.py
index ef812cf..5288e1e 100644
--- a/dns/name.py
+++ b/dns/name.py
@@ -488,9 +488,6 @@ class Name(object):
     def __getitem__(self, index):
         return self.labels[index]
 
-    def __getslice__(self, start, stop):
-        return self.labels[start:stop]
-
     def __add__(self, other):
         return self.concatenate(other)
 
diff --git a/dns/resolver.py b/dns/resolver.py
index 5bd1e8d..c9a7c78 100644
--- a/dns/resolver.py
+++ b/dns/resolver.py
@@ -282,9 +282,6 @@ class Answer(object):
     def __delitem__(self, i):
         del self.rrset[i]
 
-    def __getslice__(self, i, j):
-        return self.rrset[i:j]
-
 
 class Cache(object):
 
diff --git a/dns/set.py b/dns/set.py
index 0efc7d9..ef7fd29 100644
--- a/dns/set.py
+++ b/dns/set.py
@@ -232,9 +232,6 @@ class Set(object):
     def __delitem__(self, i):
         del self.items[i]
 
-    def __getslice__(self, i, j):
-        return self.items[i:j]
-
     def issubset(self, other):
         """Is I{self} a subset of I{other}?
 
diff --git a/dns/wiredata.py b/dns/wiredata.py
index b381f7b..ccef595 100644
--- a/dns/wiredata.py
+++ b/dns/wiredata.py
@@ -15,6 +15,7 @@
 
 """DNS Wire Data Helper"""
 
+import sys
 
 import dns.exception
 from ._compat import binary_type, string_types
@@ -26,12 +27,16 @@ from ._compat import binary_type, string_types
 # out what constant Python will use.
 
 
-class _SliceUnspecifiedBound(str):
+class _SliceUnspecifiedBound(binary_type):
 
-    def __getslice__(self, i, j):
-        return j
+    def __getitem__(self, key):
+        return key.stop
+
+    if sys.version_info < (3,):
+        def __getslice__(self, i, j):  # pylint: disable=getslice-method
+            return self.__getitem__(slice(i, j))
 
-_unspecified_bound = _SliceUnspecifiedBound('')[1:]
+_unspecified_bound = _SliceUnspecifiedBound()[1:]
 
 
 class WireData(binary_type):
@@ -40,26 +45,40 @@ class WireData(binary_type):
     def __getitem__(self, key):
         try:
             if isinstance(key, slice):
-                return WireData(super(WireData, self).__getitem__(key))
+                # make sure we are not going outside of valid ranges,
+                # do stricter control of boundaries than python does
+                # by default
+                start = key.start
+                stop = key.stop
+
+                if sys.version_info < (3,):
+                    if stop == _unspecified_bound:
+                        # handle the case where the right bound is unspecified
+                        stop = len(self)
+
+                    if start < 0 or stop < 0:
+                        raise dns.exception.FormError
+                    # If it's not an empty slice, access left and right bounds
+                    # to make sure they're valid
+                    if start != stop:
+                        super(WireData, self).__getitem__(start)
+                        super(WireData, self).__getitem__(stop - 1)
+                else:
+                    for index in (start, stop):
+                        if index is None:
+                            continue
+                        elif abs(index) > len(self):
+                            raise dns.exception.FormError
+
+                return WireData(super(WireData, self).__getitem__(
+                    slice(start, stop)))
             return bytearray(self.unwrap())[key]
         except IndexError:
             raise dns.exception.FormError
 
-    def __getslice__(self, i, j):
-        try:
-            if j == _unspecified_bound:
-                # handle the case where the right bound is unspecified
-                j = len(self)
-            if i < 0 or j < 0:
-                raise dns.exception.FormError
-            # If it's not an empty slice, access left and right bounds
-            # to make sure they're valid
-            if i != j:
-                super(WireData, self).__getitem__(i)
-                super(WireData, self).__getitem__(j - 1)
-            return WireData(super(WireData, self).__getslice__(i, j))
-        except IndexError:
-            raise dns.exception.FormError
+    if sys.version_info < (3,):
+        def __getslice__(self, i, j):  # pylint: disable=getslice-method
+            return self.__getitem__(slice(i, j))
 
     def __iter__(self):
         i = 0
diff --git a/dns/zone.py b/dns/zone.py
index 4a73e1e..1b5dca2 100644
--- a/dns/zone.py
+++ b/dns/zone.py
@@ -19,6 +19,7 @@ from __future__ import generators
 
 import sys
 import re
+import os
 from io import BytesIO
 
 import dns.exception
@@ -498,18 +499,27 @@ class Zone(object):
         @type nl: string or None
         """
 
-        str_type = string_types
+        if isinstance(f, string_types):
+            f = open(f, 'wb')
+            want_close = True
+        else:
+            want_close = False
+
+        # must be in this way, f.encoding may contain None, or even attribute
+        # may not be there
+        file_enc = getattr(f, 'encoding', None)
+        if file_enc is None:
+            file_enc = 'utf-8'
 
         if nl is None:
-            opts = 'wb'
+            nl_b = os.linesep.encode(file_enc)  # binary mode, '\n' is not enough
+            nl = u'\n'
+        elif isinstance(nl, string_types):
+            nl_b = nl.encode(file_enc)
         else:
-            opts = 'wb'
+            nl_b = nl
+            nl = nl.decode()
 
-        if isinstance(f, str_type):
-            f = open(f, opts)
-            want_close = True
-        else:
-            want_close = False
         try:
             if sorted:
                 names = list(self.keys())
@@ -520,11 +530,15 @@ class Zone(object):
                 l = self[n].to_text(n, origin=self.origin,
                                     relativize=relativize)
                 if isinstance(l, text_type):
-                    l = l.encode()
-                if nl is None:
-                    f.write(l)
-                    f.write('\n')
+                    l_b = l.encode(file_enc)
                 else:
+                    l_b = l
+                    l = l.decode()
+
+                try:
+                    f.write(l_b)
+                    f.write(nl_b)
+                except TypeError:  # textual mode
                     f.write(l)
                     f.write(nl)
         finally:
diff --git a/pylintrc b/pylintrc
index c37ac1e..3f16509 100644
--- a/pylintrc
+++ b/pylintrc
@@ -23,7 +23,6 @@ disable=
     bare-except,
     deprecated-method,
     fixme,
-    getslice-method,
     global-statement,
     invalid-name,
     missing-docstring,

diff --git a/tests/test_wiredata.py b/tests/test_wiredata.py
new file mode 100644
index 0000000..eccc3e2
--- /dev/null
+++ b/tests/test_wiredata.py
@@ -0,0 +1,126 @@
+# Copyright (C) 2016
+# Author: Martin Basti <martin.basti@gmail.com>
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose with or without fee is hereby granted,
+# provided that the above copyright notice and this permission notice
+# appear in all copies.
+
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
+from dns.exception import FormError
+from dns.wiredata import WireData
+
+
+class WireDataSlicingTestCase(unittest.TestCase):
+
+    def testSliceAll(self):
+        """Get all data"""
+        inst = WireData(b'0123456789')
+        self.assertEqual(inst[:], WireData(b'0123456789'))
+
+    def testSliceAllExplicitlyDefined(self):
+        """Get all data"""
+        inst = WireData(b'0123456789')
+        self.assertEqual(inst[0:10], WireData(b'0123456789'))
+
+    def testSliceLowerHalf(self):
+        """Get lower half of data"""
+        inst = WireData(b'0123456789')
+        self.assertEqual(inst[:5], WireData(b'01234'))
+
+    def testSliceLowerHalfWithNegativeIndex(self):
+        """Get lower half of data"""
+        inst = WireData(b'0123456789')
+        self.assertEqual(inst[:-5], WireData(b'01234'))
+
+    def testSliceUpperHalf(self):
+        """Get upper half of data"""
+        inst = WireData(b'0123456789')
+        self.assertEqual(inst[5:], WireData(b'56789'))
+
+    def testSliceMiddle(self):
+        """Get data from middle"""
+        inst = WireData(b'0123456789')
+        self.assertEqual(inst[3:6], WireData(b'345'))
+
+    def testSliceMiddleWithNegativeIndex(self):
+        """Get data from middle"""
+        inst = WireData(b'0123456789')
+        self.assertEqual(inst[-6:-3], WireData(b'456'))
+
+    def testSliceMiddleWithMixedIndex(self):
+        """Get data from middle"""
+        inst = WireData(b'0123456789')
+        self.assertEqual(inst[-8:3], WireData(b'2'))
+        self.assertEqual(inst[5:-3], WireData(b'56'))
+
+    def testGetOne(self):
+        """Get data one by one item"""
+        data = b'0123456789'
+        inst = WireData(data)
+        for i, byte in enumerate(bytearray(data)):
+            self.assertEqual(inst[i], byte)
+        for i in range(-1, len(data) * -1, -1):
+            self.assertEqual(inst[i], bytearray(data)[i])
+
+    def testEmptySlice(self):
+        """Test empty slice"""
+        data = b'0123456789'
+        inst = WireData(data)
+        for i, byte in enumerate(data):
+            self.assertEqual(inst[i:i], b'')
+        for i in range(-1, len(data) * -1, -1):
+            self.assertEqual(inst[i:i], b'')
+        self.assertEqual(inst[-3:-6], b'')
+
+    def testSliceStartOutOfLowerBorder(self):
+        """Get data from out of lower border"""
+        inst = WireData(b'0123456789')
+        with self.assertRaises(FormError):
+            inst[-11:]  # pylint: disable=pointless-statement
+
+    def testSliceStopOutOfLowerBorder(self):
+        """Get data from out of lower border"""
+        inst = WireData(b'0123456789')
+        with self.assertRaises(FormError):
+            inst[:-11]  # pylint: disable=pointless-statement
+
+    def testSliceBothOutOfLowerBorder(self):
+        """Get data from out of lower border"""
+        inst = WireData(b'0123456789')
+        with self.assertRaises(FormError):
+            inst[-12:-11]  # pylint: disable=pointless-statement
+
+    def testSliceStartOutOfUpperBorder(self):
+        """Get data from out of upper border"""
+        inst = WireData(b'0123456789')
+        with self.assertRaises(FormError):
+            inst[11:]  # pylint: disable=pointless-statement
+
+    def testSliceStopOutOfUpperBorder(self):
+        """Get data from out of upper border"""
+        inst = WireData(b'0123456789')
+        with self.assertRaises(FormError):
+            inst[:11]  # pylint: disable=pointless-statement
+
+    def testSliceBothOutOfUpperBorder(self):
+        """Get data from out of lower border"""
+        inst = WireData(b'0123456789')
+        with self.assertRaises(FormError):
+            inst[10:20]  # pylint: disable=pointless-statement
+
+    def testGetOneOutOfLowerBorder(self):
+        """Get item outside of range"""
+        inst = WireData(b'0123456789')
+        with self.assertRaises(FormError):
+            inst[-11]  # pylint: disable=pointless-statement
+
+    def testGetOneOutOfUpperBorder(self):
+        """Get item outside of range"""
+        inst = WireData(b'0123456789')
+        with self.assertRaises(FormError):
+            inst[10]  # pylint: disable=pointless-statement
diff --git a/tests/test_zone.py b/tests/test_zone.py
index 712b590..3d53e93 100644
--- a/tests/test_zone.py
+++ b/tests/test_zone.py
@@ -132,6 +132,59 @@ class ZoneTestCase(unittest.TestCase):
                 os.unlink(here('example2.out'))
         self.failUnless(ok)
 
+    def testToFileTextualStream(self):
+        z = dns.zone.from_text(example_text, 'example.', relativize=True)
+        f = StringIO()
+        z.to_file(f)
+        out = f.getvalue()
+        f.close()
+        self.assertEqual(out, example_text_output)
+
+    def testToFileBinaryStream(self):
+        z = dns.zone.from_text(example_text, 'example.', relativize=True)
+        f = BytesIO()
+        z.to_file(f)
+        out = f.getvalue()
+        f.close()
+        self.assertEqual(out, example_text_output.encode())
+
+    def testToFileTextual(self):
+        z = dns.zone.from_file(here('example'), 'example')
+        try:
+            f = open(here('example3-textual.out'), 'w')
+            z.to_file(f)
+            f.close()
+            ok = filecmp.cmp(here('example3-textual.out'),
+                             here('example3.good'))
+        finally:
+            if not _keep_output:
+                os.unlink(here('example3-textual.out'))
+        self.failUnless(ok)
+
+    def testToFileBinary(self):
+        z = dns.zone.from_file(here('example'), 'example')
+        try:
+            f = open(here('example3-binary.out'), 'wb')
+            z.to_file(f)
+            f.close()
+            ok = filecmp.cmp(here('example3-binary.out'),
+                             here('example3.good'))
+        finally:
+            if not _keep_output:
+                os.unlink(here('example3-binary.out'))
+        self.failUnless(ok)
+
+    def testToFileFilename(self):
+        z = dns.zone.from_file(here('example'), 'example')
+        try:
+            z.to_file('example3-filename.out')
+            ok = filecmp.cmp(here('example3-filename.out'),
+                             here('example3.good'))
+        finally:
+            if not _keep_output:
+                os.unlink(here('example3-filename.out'))
+        self.failUnless(ok)
+
     def testToText(self):
         z = dns.zone.from_file(here('example'), 'example')
         ok = False

py3: Zone.to_file failed
Hello,

```
#!/usr/local/bin/python3

import dns.zone
from dns.rdatatype import SOA

zone_obj = dns.zone.Zone(dns.name.from_text('test.zone'))
zone_obj.find_rdataset('@', rdtype=SOA, create=True)

zone_obj.to_file(open('/dev/null', 'w'))

Traceback (most recent call last):
  File "./t.py", line 9, in <module>
    zone_obj.to_file(open('/dev/null', 'w'))
  File "/opt/hosting/software/python3/lib/python3.5/site-packages/dns/zone.py", line 516, in to_file
    f.write(l)
TypeError: write() argument must be str, not bytes

zone_obj.to_file(open('/dev/null', 'wb'))

Traceback (most recent call last):
  File "./t.py", line 10, in <module>
    zone_obj.to_file(open('/dev/null', 'wb'))
  File "/opt/hosting/software/python3/lib/python3.5/site-packages/dns/zone.py", line 517, in to_file
    f.write('\n')
TypeError: a bytes-like object is required, not 'str'
```

looks like a bug ?
tests/test_wiredata.py::WireDataSlicingTestCase::testSliceBothOutOfLowerBorder tests/test_wiredata.py::WireDataSlicingTestCase::testSliceBothOutOfUpperBorder tests/test_wiredata.py::WireDataSlicingTestCase::testSliceStartOutOfLowerBorder tests/test_wiredata.py::WireDataSlicingTestCase::testSliceStartOutOfUpperBorder tests/test_wiredata.py::WireDataSlicingTestCase::testSliceStopOutOfLowerBorder tests/test_wiredata.py::WireDataSlicingTestCase::testSliceStopOutOfUpperBorder tests/test_zone.py::ZoneTestCase::testToFileBinaryStream tests/test_zone.py::ZoneTestCase::testToFileTextualStream
tests/test_wiredata.py::WireDataSlicingTestCase::testEmptySlice tests/test_wiredata.py::WireDataSlicingTestCase::testGetOne tests/test_wiredata.py::WireDataSlicingTestCase::testGetOneOutOfLowerBorder tests/test_wiredata.py::WireDataSlicingTestCase::testGetOneOutOfUpperBorder tests/test_wiredata.py::WireDataSlicingTestCase::testSliceAll tests/test_wiredata.py::WireDataSlicingTestCase::testSliceAllExplicitlyDefined tests/test_wiredata.py::WireDataSlicingTestCase::testSliceLowerHalf tests/test_wiredata.py::WireDataSlicingTestCase::testSliceLowerHalfWithNegativeIndex tests/test_wiredata.py::WireDataSlicingTestCase::testSliceMiddle tests/test_wiredata.py::WireDataSlicingTestCase::testSliceMiddleWithMixedIndex tests/test_wiredata.py::WireDataSlicingTestCase::testSliceMiddleWithNegativeIndex tests/test_wiredata.py::WireDataSlicingTestCase::testSliceUpperHalf tests/test_zone.py::ZoneTestCase::testBadDirective tests/test_zone.py::ZoneTestCase::testDeleteRdataset1 tests/test_zone.py::ZoneTestCase::testDeleteRdataset2 tests/test_zone.py::ZoneTestCase::testEqual tests/test_zone.py::ZoneTestCase::testFindRRset1 tests/test_zone.py::ZoneTestCase::testFindRRset2 tests/test_zone.py::ZoneTestCase::testFindRdataset1 tests/test_zone.py::ZoneTestCase::testFindRdataset2 tests/test_zone.py::ZoneTestCase::testFirstRRStartsWithWhitespace tests/test_zone.py::ZoneTestCase::testFromText tests/test_zone.py::ZoneTestCase::testGetRRset1 tests/test_zone.py::ZoneTestCase::testGetRRset2 tests/test_zone.py::ZoneTestCase::testGetRdataset1 tests/test_zone.py::ZoneTestCase::testGetRdataset2 tests/test_zone.py::ZoneTestCase::testIterateAllRdatas tests/test_zone.py::ZoneTestCase::testIterateAllRdatasets tests/test_zone.py::ZoneTestCase::testIterateRdatas tests/test_zone.py::ZoneTestCase::testIterateRdatasets tests/test_zone.py::ZoneTestCase::testNoNS tests/test_zone.py::ZoneTestCase::testNoSOA tests/test_zone.py::ZoneTestCase::testNodeDeleteRdataset1 tests/test_zone.py::ZoneTestCase::testNodeDeleteRdataset2 tests/test_zone.py::ZoneTestCase::testNodeFindRdataset1 tests/test_zone.py::ZoneTestCase::testNodeFindRdataset2 tests/test_zone.py::ZoneTestCase::testNodeGetRdataset1 tests/test_zone.py::ZoneTestCase::testNodeGetRdataset2 tests/test_zone.py::ZoneTestCase::testNotEqual1 tests/test_zone.py::ZoneTestCase::testNotEqual2 tests/test_zone.py::ZoneTestCase::testNotEqual3 tests/test_zone.py::ZoneTestCase::testReplaceRdataset1 tests/test_zone.py::ZoneTestCase::testReplaceRdataset2 tests/test_zone.py::ZoneTestCase::testTTLs tests/test_zone.py::ZoneTestCase::testZoneOrigin tests/test_zone.py::ZoneTestCase::testZoneOriginNone