1 # -*- coding: utf-8 -*-
3 # -- Dual Licence ----------------------------------------------------------
5 ############################################################################
8 # This file is a SCons (http://www.scons.org/) builder #
9 # Copyright (c) 2012-14, Philipp Kraus, <philipp.kraus@flashpixx.de> #
10 # This program is free software: you can redistribute it and/or modify #
11 # it under the terms of the GNU General Public License as #
12 # published by the Free Software Foundation, either version 3 of the #
13 # License, or (at your option) any later version. #
15 # This program is distributed in the hope that it will be useful, #
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
18 # GNU General Public License for more details. #
20 # You should have received a copy of the GNU General Public License #
21 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
22 ############################################################################
24 # --------------------------------------------------------------------------
26 ############################################################################
27 # BSD 3-Clause License #
29 # This file is a SCons (http://www.scons.org/) builder #
30 # Copyright (c) 2012-14, Philipp Kraus, <philipp.kraus@flashpixx.de> #
31 # All rights reserved. #
33 # Redistribution and use in source and binary forms, with or without #
34 # modification, are permitted provided that the following conditions are #
37 # 1. Redistributions of source code must retain the above copyright #
38 # notice, this list of conditions and the following disclaimer. #
40 # 2. Redistributions in binary form must reproduce the above copyright #
41 # notice, this list of conditions and the following disclaimer in the #
42 # documentation and/or other materials provided with the distribution. #
44 # 3. Neither the name of the copyright holder nor the names of its #
45 # contributors may be used to endorse or promote products derived from #
46 # this software without specific prior written permission. #
48 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS #
49 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT #
50 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A #
51 # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT #
52 # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, #
53 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED #
54 # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR #
55 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF #
56 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
57 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS #
58 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #
59 ############################################################################
63 # the URLDownload-Builder can be download any data from an URL into a target file
64 # and can replace the target file name with the URL filename (the setting variable
65 # within the environment object is a boolean type with the name "URLDOWNLOAD_USEURLFILENAM",
66 # default setting replaces the target name with the URL filename)
69 import urllib2, urlparse
70 import SCons.Builder, SCons.Node, SCons.Errors
73 # define an own node, for checking the data behind the URL,
74 # we must download only than, if the data is changed, the
75 # node derivates from the Python.Value node
76 class URLNode(SCons.Node.Python.Value) :
78 # overload the get_csig (copy the source from the
79 # Python.Value node and append the data of the URL header
80 def get_csig(self, calc=None):
82 return self.ninfo.csig
83 except AttributeError:
87 response = urllib2.urlopen( str(self.value) ).info()
89 raise SCons.Errors.StopError( "%s [%s]" % (e, self.value) )
92 if "Last-Modified" in response :
93 contents = contents + response["Last-Modified"]
94 if "Content-Length" in response :
95 contents = contents + response["Content-Length"]
97 contents = self.get_contents()
98 self.get_ninfo().csig = contents
103 # creates the downloading output message
104 # @param s original message
105 # @param target target name
106 # @param source source name
107 # @param env environment object
108 def __message( s, target, source, env ) :
109 print "downloading [%s] to [%s] ..." % (source[0], target[0])
112 # the download function, which reads the data from the URL
113 # and writes it down to the file
114 # @param target target file on the local drive
115 # @param source URL for download
116 # @@param env environment object
117 def __action( target, source, env ) :
119 stream = urllib2.urlopen( str(source[0]) )
120 file = open( str(target[0]), "wb" )
121 file.write(stream.read())
124 except Exception, e :
125 raise SCons.Errors.StopError( "%s [%s]" % (e, source[0]) )
128 # defines the emitter of the builder
129 # @param target target file on the local drive
130 # @param source URL for download
131 # @param env environment object
132 def __emitter( target, source, env ) :
133 # we need a temporary file, because the dependency graph
134 # of Scons need a physical existing file - so we prepare it
137 if not env.get("URLDOWNLOAD_USEURLFILENAME", False) :
138 return target, source
141 url = urlparse.urlparse( urllib2.urlopen( str(source[0]) ).geturl() )
142 except Exception, e :
143 raise SCons.Errors.StopError( "%s [%s]" % (e, source[0]) )
145 return url.path.split("/")[-1], source
150 # generate function, that adds the builder to the environment,
151 # the value "DOWNLOAD_USEFILENAME" replaces the target name with
152 # the filename of the URL
153 # @param env environment object
154 def generate( env ) :
155 env["BUILDERS"]["URLDownload"] = SCons.Builder.Builder( action = __action, emitter = __emitter, target_factory = SCons.Node.FS.File, source_factory = URLNode, single_source = True, PRINT_CMD_LINE_FUNC = __message )
156 env.Replace(URLDOWNLOAD_USEURLFILENAME = True )
159 # existing function of the builder
160 # @param env environment object