Repository: openaddresses/machine
Pull request #599 (2017-04-05 18:13:53)

Improve Tippecanoe commandline
Modified openaddr.slippymap to accept multiple filenames or URLs for sources, to make it easier to generate vector tilesets for multi-source countries.

1. Install Machine for [local development using Vagrant](https://github.com/openaddresses/machine/blob/master/docs/install.md#local-development).
2. Log in to the Vagrant machine, and ensure that openaddr.slippymap is available by running this command:
    
        cd ~/machine
        python3 -m openaddr.slippymap --help
    
    You should see usage help like this:
    
        usage: slippymap.py [-h] [-v] [-q]
                            mbtiles_filename [src_filenames [src_filenames ...]]
        
        Generate a single source slippy map MBTiles file with Tippecanoe.
    
3. Additionally install Tippecanoe on the Vagrant image:
    
        sudo ~/machine/chef/run.sh dotmap
    
4. Generate a vector tiles MBTiles file. This example combines four recent data sources for Spain:
     
          python3 -m openaddr.slippymap /tmp/es.mbtiles \
               https://s3.amazonaws.com/data.openaddresses.io/runs/173437/es/25830.zip \
               https://s3.amazonaws.com/data.openaddresses.io/runs/173514/es/25829.zip \
               https://s3.amazonaws.com/data.openaddresses.io/runs/173553/es/25831.zip \
               https://s3.amazonaws.com/data.openaddresses.io/runs/173856/es/32628.zip


Patch:
diff --git a/openaddr/slippymap.py b/openaddr/slippymap.py
index 8fcdfb6..dbc0b3e 100644
--- a/openaddr/slippymap.py
+++ b/openaddr/slippymap.py
@@ -4,25 +4,27 @@ import logging; _L = logging.getLogger('openaddr.slippymap')
 from zipfile import ZipFile
 from io import TextIOWrapper
 from csv import DictReader
-from tempfile import gettempdir
+from tempfile import gettempdir, mkstemp
 from argparse import ArgumentParser
 from urllib.parse import urlparse
 import os, subprocess, json
+import requests
 
-def generate(filename_or_url, mbtiles_filename):
+def generate(mbtiles_filename, *filenames_or_urls):
     '''
     '''
-    src_filename = get_local_filename(filename_or_url)
-    
     cmd = 'tippecanoe', '-l', 'dots', '-r', '3', \
           '-n', 'OpenAddresses Dots', '-f', \
           '-t', gettempdir(), '-o', mbtiles_filename
     
     tippecanoe = subprocess.Popen(cmd, stdin=subprocess.PIPE, bufsize=1)
     
-    for feature in iterate_file_features(src_filename):
-        tippecanoe.stdin.write(json.dumps(feature).encode('utf8'))
-        tippecanoe.stdin.write(b'\n')
+    for filename_or_url in filenames_or_urls:
+        src_filename = get_local_filename(filename_or_url)
+    
+        for feature in iterate_file_features(src_filename):
+            tippecanoe.stdin.write(json.dumps(feature).encode('utf8'))
+            tippecanoe.stdin.write(b'\n')
 
     tippecanoe.stdin.close()
     tippecanoe.wait()
@@ -82,8 +84,8 @@ def iterate_file_features(filename):
 
 parser = ArgumentParser(description='Generate a single source slippy map MBTiles file with Tippecanoe.')
 
-parser.add_argument('src_filename', help='Input Zip or CSV filename or URL.')
 parser.add_argument('mbtiles_filename', help='Output MBTiles filename.')
+parser.add_argument('src_filenames', help='Input Zip or CSV filename or URL.', nargs='*')
 
 parser.add_argument('-v', '--verbose', help='Turn on verbose logging',
                     action='store_const', dest='loglevel',
@@ -97,7 +99,7 @@ def main():
     args = parser.parse_args()
     from .ci import setup_logger
     setup_logger(None, None, None, log_level=args.loglevel)
-    generate(args.src_filename, args.mbtiles_filename)
+    generate(args.mbtiles_filename, *args.src_filenames)
 
 if __name__ == '__main__':
     exit(main())


Test patch:
diff --git a/openaddr/tests/slippymap.py b/openaddr/tests/slippymap.py
index 4e169b3..376d904 100644
--- a/openaddr/tests/slippymap.py
+++ b/openaddr/tests/slippymap.py
@@ -28,7 +28,7 @@ class TestSlippyMap (unittest.TestCase):
 
         try:
             with mock.patch('subprocess.Popen') as Popen:
-                slippymap.generate(zip_filename, mbtiles_filename)
+                slippymap.generate(mbtiles_filename, zip_filename)
 
             self.assertEqual(len(Popen.return_value.stdin.write.mock_calls), 2 * 5305)
             self.assertEqual(len(Popen.return_value.stdin.close.mock_calls), 1)
@@ -54,7 +54,7 @@ class TestSlippyMap (unittest.TestCase):
                 csv_filename = file.name
         
             with mock.patch('subprocess.Popen') as Popen:
-                slippymap.generate(csv_filename, mbtiles_filename)
+                slippymap.generate(mbtiles_filename, csv_filename)
 
             self.assertEqual(len(Popen.return_value.stdin.write.mock_calls), 2 * 767)
             self.assertEqual(len(Popen.return_value.stdin.close.mock_calls), 1)