def download(self, source_urls, workdir, conform=None):
        output_files = []
        download_path = os.path.join(workdir, 'esri')
        mkdirsp(download_path)

        query_fields = self.field_names_to_request(conform)

        for source_url in source_urls:
            size = 0
            file_path = self.get_file_path(source_url, download_path)

            if os.path.exists(file_path):
                output_files.append(file_path)
                _L.debug("File exists %s", file_path)
                continue

            metadata = self.get_layer_metadata(source_url)
            
            if query_fields is None:
                field_names = [f['name'] for f in metadata['fields']]
            else:
                field_names = query_fields[:]

            if X_FIELDNAME not in field_names:
                field_names.append(X_FIELDNAME)
            if Y_FIELDNAME not in field_names:
                field_names.append(Y_FIELDNAME)
            if GEOM_FIELDNAME not in field_names:
                field_names.append(GEOM_FIELDNAME)

            query_url = source_url + '/query'

            # Get the count of rows in the layer
            count_json = self.get_layer_feature_count(query_url)

            row_count = count_json.get('count')
            page_size = metadata.get('maxRecordCount', 500)
            if page_size > 1000:
                page_size = 1000

            _L.info("Source has {} rows".format(row_count))

            page_args = []

            if metadata.get('supportsPagination') or \
               (metadata.get('advancedQueryCapabilities') and metadata['advancedQueryCapabilities']['supportsPagination']):
                # If the layer supports pagination, we can use resultOffset/resultRecordCount to paginate

                # There's a bug where some servers won't handle these queries in combination with a list of
                # fields specified. We'll make a single, 1 row query here to check if the server supports this
                # and switch to querying for all fields if specifying the fields fails.
                if query_fields and not self.can_handle_pagination(query_url, query_fields):
                    _L.info("Source does not support pagination with fields specified, so querying for all fields.")
                    query_fields = None

                for offset in range(0, row_count, page_size):
                    page_args.append({
                        'resultOffset': offset,
                        'resultRecordCount': page_size,
                        'where': '1=1',
                        'geometryPrecision': 7,
                        'returnGeometry': 'true',
                        'outSR': 4326,
                        'outFields': ','.join(query_fields or ['*']),
                        'f': 'json',
                    })
                _L.info("Built {} requests using resultOffset method".format(len(page_args)))
            else:
                # If not, we can still use the `where` argument to paginate

                use_oids = True
                if metadata.get('supportsStatistics'):
                    # If the layer supports statistics, we can request maximum and minimum object ID
                    # to help build the pages

                    oid_field_name = self.find_oid_field_name(metadata)

                    try:
                        (oid_min, oid_max) = self.get_layer_min_max(query_url, oid_field_name)

                        for page_min in range(oid_min - 1, oid_max, page_size):
                            page_max = min(page_min + page_size, oid_max)
                            page_args.append({
                                'where': '{} > {} AND {} <= {}'.format(
                                    oid_field_name,
                                    page_min,
                                    oid_field_name,
                                    page_max,
                                ),
                                'geometryPrecision': 7,
                                'returnGeometry': 'true',
                                'outSR': 4326,
                                'outFields': ','.join(query_fields or ['*']),
                                'f': 'json',
                            })
                        _L.info("Built {} requests using OID where clause method".format(len(page_args)))

                        # If we reach this point we don't need to fall through to enumerating all object IDs
                        # because the statistics method worked
                        use_oids = False
                    except DownloadError:
                        _L.exception("Finding max/min from statistics failed. Trying OID enumeration.")

                if use_oids:
                    # If the layer does not support statistics, we can request
                    # all the individual IDs and page through them one chunk at
                    # a time.

                    oid_data = self.get_layer_oids(query_url)
                    oids = oid_data['objectIds']

                    for i in range(0, len(oids), 100):
                        oid_chunk = map(long if PY2 else int, oids[i:i+100])
                        page_args.append({
                            'objectIds': ','.join(map(str, oid_chunk)),
                            'geometryPrecision': 7,
                            'returnGeometry': 'true',
                            'outSR': 4326,
                            'outFields': ','.join(query_fields or ['*']),
                            'f': 'json',
                        })
                    _L.info("Built {} requests using OID enumeration method".format(len(page_args)))

            with csvopen(file_path, 'w', encoding='utf-8') as f:
                writer = csvDictWriter(f, fieldnames=field_names, encoding='utf-8')
                writer.writeheader()

                for query_args in page_args:
                    try:
                        response = request('POST', query_url, headers=self.headers, data=query_args)

                        data = self.handle_esri_errors(response, "Could not retrieve this chunk of objects from ESRI source")
                    except socket.timeout as e:
                        raise DownloadError("Timeout when connecting to URL", e)
                    except __HOLE__ as e:
                        raise DownloadError("Could not parse JSON", e)
                    except Exception as e:
                        raise DownloadError("Could not connect to URL", e)
                    finally:
                        # Wipe out whatever we had written out so far
                        f.truncate()

                    error = data.get('error')
                    if error:
                        raise DownloadError("Problem querying ESRI dataset with args {}. Server said: {}".format(query_args, error['message']))

                    geometry_type = data.get('geometryType')
                    features = data.get('features')

                    for feature in features:
                        try:
                            ogr_geom = self.build_ogr_geometry(geometry_type, feature)
                            row = feature.get('attributes', {})
                            row[GEOM_FIELDNAME] = ogr_geom.ExportToWkt()
                            try:
                                centroid = ogr_geom.Centroid()
                            except RuntimeError as e:
                                if 'Invalid number of points in LinearRing found' not in str(e):
                                    raise
                                xmin, xmax, ymin, ymax = ogr_geom.GetEnvelope()
                                row[X_FIELDNAME] = round(xmin/2 + xmax/2, 7)
                                row[Y_FIELDNAME] = round(ymin/2 + ymax/2, 7)
                            else:
                                row[X_FIELDNAME] = round(centroid.GetX(), 7)
                                row[Y_FIELDNAME] = round(centroid.GetY(), 7)

                            writer.writerow({fn: row.get(fn) for fn in field_names})
                            size += 1
                        except TypeError:
                            _L.debug("Skipping a geometry", exc_info=True)

            _L.info("Downloaded %s ESRI features for file %s", size, file_path)
            output_files.append(file_path)
        return output_files
dataset/ETHPy150Open openaddresses/machine/openaddr/cache.py/EsriRestDownloadTask.download