1# -*- coding: utf-8 -*-
2# Copyright 2014 Google Inc. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""Helper for cat and cp streaming download."""
16
17from __future__ import absolute_import
18
19import sys
20
21from gslib.exception import CommandException
22from gslib.wildcard_iterator import StorageUrlFromString
23
24
25class CatHelper(object):
26
27  def __init__(self, command_obj):
28    """Initializes the helper object.
29
30    Args:
31      command_obj: gsutil command instance of calling command.
32    """
33    self.command_obj = command_obj
34
35  def CatUrlStrings(self, url_strings, show_header=False, start_byte=0,
36                    end_byte=None):
37    """Prints each of the url strings to stdout.
38
39    Args:
40      url_strings: String iterable.
41      show_header: If true, print a header per file.
42      start_byte: Starting byte of the file to print, used for constructing
43                  range requests.
44      end_byte: Ending byte of the file to print; used for constructing range
45                requests. If this is negative, the start_byte is ignored and
46                and end range is sent over HTTP (such as range: bytes -9)
47    Returns:
48      0 on success.
49
50    Raises:
51      CommandException if no URLs can be found.
52    """
53    printed_one = False
54    # We manipulate the stdout so that all other data other than the Object
55    # contents go to stderr.
56    cat_outfd = sys.stdout
57    sys.stdout = sys.stderr
58    try:
59      for url_str in url_strings:
60        did_some_work = False
61        # TODO: Get only the needed fields here.
62        for blr in self.command_obj.WildcardIterator(url_str).IterObjects():
63          did_some_work = True
64          if show_header:
65            if printed_one:
66              print
67            print '==> %s <==' % blr
68            printed_one = True
69          cat_object = blr.root_object
70          storage_url = StorageUrlFromString(blr.url_string)
71          if storage_url.IsCloudUrl():
72            self.command_obj.gsutil_api.GetObjectMedia(
73                cat_object.bucket, cat_object.name, cat_outfd,
74                start_byte=start_byte, end_byte=end_byte,
75                object_size=cat_object.size, generation=storage_url.generation,
76                provider=storage_url.scheme)
77          else:
78            cat_outfd.write(open(storage_url.object_name, 'rb').read())
79        if not did_some_work:
80          raise CommandException('No URLs matched %s' % url_str)
81      sys.stdout = cat_outfd
82    finally:
83      sys.stdout = cat_outfd
84
85    return 0
86