Repository: geopandas/geopandas

Issue:
tools module 
As mentioned in a [discussion](https://github.com/geopandas/geopandas/pull/121#discussion-diff-14860486) on #121, utility functions like `geocode` and `sjoin` should go in a common `tools` module.

Imports would work like this:

```
from geopandas.tools import sjoin, geocode
```



Discussion:
I've started this in the overlay and sjoin branches but it is currently in a single file `geopandas/tools.py` ... since  I'm working off of the `spatial_index` branch, I'll probably just follow suite: abandon that branch and re implement it as a directory `geopandas/tools/*` on top of the new work. 


Resolving patch:
diff --git a/geopandas/tools/__init__.py b/geopandas/tools/__init__.py
--- a/geopandas/tools/__init__.py
+++ b/geopandas/tools/__init__.py
@@ -1,10 +1,13 @@
 from __future__ import absolute_import
 
+from .geocoding import geocode, reverse_geocode
 from .overlay import overlay
 from .sjoin import sjoin
 
 __all__ = [
     'overlay',
     'sjoin',
+    'geocode',
+    'reverse_geocode'
 ]
 
diff --git a/geopandas/geocode.py b/geopandas/tools/geocoding.py
similarity index 100%
rename from geopandas/geocode.py
rename to geopandas/tools/geocoding.py


Test patch:
diff --git a/tests/test_geocode.py b/tests/test_geocode.py
--- a/tests/test_geocode.py
+++ b/tests/test_geocode.py
@@ -8,7 +8,9 @@
 import geopandas as gpd
 import nose
 
-from geopandas.geocode import geocode, reverse_geocode, _prepare_geocode_result
+from geopandas.tools import geocode, reverse_geocode
+from geopandas.tools.geocoding import _prepare_geocode_result
+
 from .util import unittest
 
 
@@ -32,7 +34,6 @@ def setUp(self):
     def test_prepare_result(self):
         # Calls _prepare_result with sample results from the geocoder call
         # loop
-        from geopandas.geocode import _prepare_geocode_result
         p0 = Point(12.3, -45.6) # Treat these as lat/lon
         p1 = Point(-23.4, 56.7)
         d = {'a': ('address0', p0.coords[0]),
@@ -56,7 +57,6 @@ def test_prepare_result(self):
         self.assertAlmostEqual(coords[1], test[0])
 
     def test_prepare_result_none(self):
-        from geopandas.geocode import _prepare_geocode_result
         p0 = Point(12.3, -45.6) # Treat these as lat/lon
         d = {'a': ('address0', p0.coords[0]),
              'b': (None, None)}
@@ -72,7 +72,6 @@ def test_prepare_result_none(self):
         self.assert_(pd.np.isnan(row['address']))
     
     def test_bad_provider_forward(self):
-        from geopandas.geocode import geocode
         with self.assertRaises(ValueError):
             geocode(['cambridge, ma'], 'badprovider')
 
@@ -81,17 +80,14 @@ def test_bad_provider_reverse(self):
             reverse_geocode(['cambridge, ma'], 'badprovider')
 
     def test_googlev3_forward(self):
-        from geopandas.geocode import geocode
         g = geocode(self.locations, provider='googlev3', timeout=2)
         self.assertIsInstance(g, gpd.GeoDataFrame)
 
     def test_googlev3_reverse(self):
-        from geopandas.geocode import geocode
         g = reverse_geocode(self.points, provider='googlev3', timeout=2)
         self.assertIsInstance(g, gpd.GeoDataFrame)
 
     def test_openmapquest_forward(self):
-        from geopandas.geocode import geocode
         g = geocode(self.locations, provider='openmapquest', timeout=2)
         self.assertIsInstance(g, gpd.GeoDataFrame)
 
@@ -99,6 +95,5 @@ def test_openmapquest_forward(self):
 
     @unittest.skip('Nominatim server is unreliable for tests.')
     def test_nominatim(self):
-        from geopandas.geocode import geocode
         g = geocode(self.locations, provider='nominatim', timeout=2)
         self.assertIsInstance(g, gpd.GeoDataFrame)