Repository: obspy/obspy

Issue:
Network: Enable using an empty string as network code?
Currently it's not possible to set an empty string as network code (due to an `if not value:` in the setter), I think this should probably be possible. Similar `if not ...:` checks might also affect other places in `core.inventory` I guess.

```python
from obspy.core.inventory import Network
Network(code='')
```

```
/home/megies/git/obspy/obspy/core/inventory/util.pyc in code(self, value)
     77         if not value:
     78             msg = "A Code is required"
---> 79             raise ValueError(msg)
     80         self._code = str(value).strip()
     81 

ValueError: A Code is required
```


Discussion:

Resolving patch:
diff --git a/obspy/core/inventory/inventory.py b/obspy/core/inventory/inventory.py
--- a/obspy/core/inventory/inventory.py
+++ b/obspy/core/inventory/inventory.py
@@ -105,8 +105,8 @@ class Inventory(ComparingObject):
 
     In essence just a container for one or more networks.
     """
-    def __init__(self, networks, source, sender=None, created=None,
-                 module=SOFTWARE_MODULE, module_uri=SOFTWARE_URI):
+    def __init__(self, networks=None, source=SOFTWARE_MODULE, sender=None,
+                created=None, module=SOFTWARE_MODULE, module_uri=SOFTWARE_URI):
         """
         :type networks: list of
             :class:`~obspy.core.inventory.network.Network`
@@ -132,7 +132,7 @@ def __init__(self, networks, source, sender=None, created=None,
             StationXML standard and how to output it to StationXML
             see the :ref:`ObsPy Tutorial <stationxml-extra>`.
         """
-        self.networks = networks
+        self.networks = networks if networks is not None else []
         self.source = source
         self.sender = sender
         self.module = module
diff --git a/obspy/core/inventory/util.py b/obspy/core/inventory/util.py
--- a/obspy/core/inventory/util.py
+++ b/obspy/core/inventory/util.py
@@ -74,8 +74,8 @@ def code(self):
 
     @code.setter
     def code(self, value):
-        if not value:
-            msg = "A Code is required"
+        if value is None:
+            msg = "A code is required"
             raise ValueError(msg)
         self._code = str(value).strip()
 


Test patch:
diff --git a/obspy/core/tests/test_inventory.py b/obspy/core/tests/test_inventory.py
--- a/obspy/core/tests/test_inventory.py
+++ b/obspy/core/tests/test_inventory.py
@@ -15,6 +15,7 @@
 from future.utils import PY2, native_str
 
 import builtins
+import io
 import os
 import unittest
 import warnings
@@ -466,6 +467,24 @@ def test_read_invalid_filename(self):
             self.assertEqual(
                 str(e.exception), exception_msg.format(doesnt_exist))
 
+    def test_inventory_can_be_initialized_with_no_arguments(self):
+        """
+        Source and networks need not be specified.
+        """
+        inv = Inventory()
+        self.assertEqual(inv.networks, [])
+        self.assertEqual(inv.source, "ObsPy %s" % obspy.__version__)
+
+        # Should also be serializable.
+        with io.BytesIO() as buf:
+            # This actually would not be a valid StationXML file but there
+            # might be uses for this.
+            inv.write(buf, format="stationxml")
+            buf.seek(0, 0)
+            inv2 = read_inventory(buf)
+
+        self.assertEqual(inv, inv2)
+
 
 @unittest.skipIf(not BASEMAP_VERSION, 'basemap not installed')
 class InventoryBasemapTestCase(unittest.TestCase):
diff --git a/obspy/core/tests/test_network.py b/obspy/core/tests/test_network.py
--- a/obspy/core/tests/test_network.py
+++ b/obspy/core/tests/test_network.py
@@ -27,7 +27,8 @@
 from obspy.core.util import (
     BASEMAP_VERSION, CARTOPY_VERSION, MATPLOTLIB_VERSION)
 from obspy.core.util.testing import ImageComparison
-from obspy.core.inventory import Channel, Network, Response, Station
+from obspy.core.inventory import (Channel, Inventory, Network, Response,
+                                  Station)
 
 
 class NetworkTestCase(unittest.TestCase):
@@ -258,6 +259,28 @@ def test_network_select_with_empty_stations(self):
         self.assertEqual(len(net.select(time=UTCDateTime(2007, 1, 1))), 1)
         self.assertEqual(len(net.select(time=UTCDateTime(2008, 1, 1))), 2)
 
+    def test_empty_network_code(self):
+        """
+        Tests that an empty sring is acceptabble.
+        """
+        # An empty string is allowed.
+        n = Network(code="")
+        self.assertEqual(n.code, "")
+
+        # But None is not allowed.
+        with self.assertRaises(ValueError) as e:
+            Network(code=None)
+        self.assertEqual(e.exception.args[0], "A code is required")
+
+        # Should still serialize to something.
+        inv = Inventory(networks=[n])
+        with io.BytesIO() as buf:
+            inv.write(buf, format="stationxml", validate=True)
+            buf.seek(0, 0)
+            inv2 = read_inventory(buf)
+
+        self.assertEqual(inv, inv2)
+
 
 @unittest.skipIf(not BASEMAP_VERSION, 'basemap not installed')
 class NetworkBasemapTestCase(unittest.TestCase):