root/Trunk/setup.py

Revision 1369, 10.6 KB (checked in by todd, 3 years ago)

stable again (such as it is) in Trunk!
updated all the assets and asset types to deal with the new typing stuff;
other misc tweaks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1#!/usr/bin/python
2
3# $Id$
4
5'''
6
7Copyright 2006 - 2008 Todd D. Esposito.
8
9This file is part of TurtolCMS.
10
11    TurtolCMS is free software: you can redistribute it and/or modify
12    it under the terms of the GNU Affero General Public License as
13    published by the Free Software Foundation, either version 3 of the
14    License, or (at your option) any later version.
15
16    TurtolCMS is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU Affero General Public License for more details.
20
21    You should have received a copy of the GNU Affero General Public
22    License along with TurtolCMS.  If not, see <http://www.gnu.org/licenses/>.
23
24'''
25
26# Most of this is creating python that will generate resource files on the
27# fly (javascript, css, and images). The actual "build" process is at the
28# bottom of the file.
29
30import sys, os, os.path, shutil
31from datetime import datetime
32from sha import sha
33
34def MakeETag(filepath):
35  return sha("%s%s" % (filepath, str( datetime.now() ) ) ).hexdigest()
36 
37def rcs_to_py (name):
38  ''' make a python module name from a source file name
39  '''
40  if name[-3:] == ".py":
41    return name
42  return "%s.py" % name.replace ('.', '_')
43
44_pageheader = '''# DO NOT EDIT THIS FILE BY HAND!
45# TurtolCMS setup generated this file; any edits here will be lost
46# the next time TurtolCMS is updated.  See the developer documentation
47# at http://www.turtolcms.org/ for further information.
48'''
49
50_starttextpage = '''
51from TurtolCMS.Core import Asset
52
53class AssetProxy (Asset):
54  def __init__ (self, uri, ctx):
55    super (AssetProxy, self).__init__ (uri, ctx, types=['TurtolCMS.Types.Page', 'TurtolCMS.Types.RawTextPage'])
56    self['etag'] = '%(etag)s'
57    #self['modified'] = %(modified)s
58    self['TurtolCMS.Types.RawTextPage.type'] = '%(type)s'
59'''
60
61_startdatapage = '''
62from TurtolCMS.Core import Asset
63
64class AssetProxy (Asset):
65  def __init__ (self, uri, ctx):
66    super (AssetProxy, self).__init__ (uri, ctx, types=['TurtolCMS.Types.Page', 'TurtolCMS.Types.RawDataPage'])
67    self['etag'] = '%(etag)s'
68    #self['modified'] = %(modified)s
69    self['TurtolCMS.Types.RawDataPage.type'] = '%(type)s'
70    self['TurtolCMS.Types.RawDataPage.length'] = %(length)s
71'''
72
73_starttext = "\n    self['TurtolCMS.Types.RawTextPage.text'] = '''"
74
75_startdata = "\n    self['TurtolCMS.Types.RawDataPage.data'] = '''"
76
77_endtext = "'''\n"
78
79_enddata = "'''\n"
80
81_endpage = ""
82
83def GenTextPage (src, target, type):
84  rval = True
85  etag = MakeETag (target)
86  modified = datetime.now()
87  try:
88    out = file (target, 'w')
89    out.write (_pageheader % locals())
90    out.write (_starttextpage % locals())
91
92    out.write (_starttext % locals())
93    for line in src:
94      out.write (line.replace("\\", "\%s" %"\\"))
95    out.write (_endtext % locals())
96
97    out.write (_endpage % locals())
98    out.close()
99  except:
100    rval = False
101  return rval
102
103def GenImagePage (src, target, type):
104  rval = True
105  etag = MakeETag (target)
106  modified = datetime.now()
107
108  # IMPORTANT NOTE: src must support seeking for this to work; shouldn't be an issue
109  src.seek (0, 2)
110  length = src.tell()
111  src.seek (0, 0)
112
113  try:
114    out = file (target, 'w')
115    out.write (_pageheader % locals())
116    out.write (_startdatapage % locals())
117
118    out.write (_startdata % locals())
119    for c in src.read():
120      if ord(c) < ord (' ') or ord(c) > ord ('~'):
121        if ord (c) < 16:
122          out.write ('\\x0%s' % hex(ord(c))[-1:])
123        else:
124          out.write ('\\x%s' % hex (ord(c))[-2:])
125      elif c == '\\':
126        out.write ('\\\\')
127      elif c == "'":
128        out.write("\\'")
129      else:
130        out.write (c)
131    out.write (_enddata % locals())
132
133    out.write (_endpage % locals())
134    out.close()
135  except:
136    rval = False
137  return rval
138 
139def PassThru (src, target, type):
140  # just copy the source to target
141  out = file (target, 'w')
142  for l in src.readlines():
143    out.write (l)
144  out.close()
145  return True
146
147def CssMinifier (src):
148  # TODO: minify the CSS
149  return file (src, 'r')
150
151  #create the css file by passing the source through the css_slimmer
152  from slimmer.slimmer import css_slimmer
153  src = file (inputFile)
154  # for line in src:
155  out.write ("    w('''")
156  out.write (css_slimmer (src.read()))
157  #out.write (line.replace("\\", "\%s" %"\\").strip())
158  out.write ("\\n ''')\n")
159  src.close()
160  out.close()
161
162def JsMinifier (src):
163  # TODO: minify the Js
164  return file (src, 'r')
165
166  #create the js file by passing the source through the JSMinifier
167  from jsmin import JavascriptMinify
168  import StringIO
169  src = file (inputFile)
170  # for line in src:
171  out.write ("    w('''")
172  JavascriptMinify().minify(src, out)
173  #out.write (line.replace("\\", "\%s" %"\\").strip())
174  out.write ("\\n ''')\n")
175  # src.close()  -- Done by minify()
176  out.close()
177
178def GenerateResources():
179  import mimetypes
180  # some configuration constants
181  api_source = 'api_resources'
182  src_len = len (api_source)
183  api_base = 'TurtolCMS/Api'
184  api_init = '%s/__init__.py' % api_base
185
186  # this maps content (mime) types to the appropriate generators/processor
187  # each value tuple consists of the output generator function and
188  # corresponding input filter for each MIME type.  The 'file' filter
189  # can be used to just read the file straight up.
190  generators = { 'application/javascript' : (GenTextPage, JsMinifier)
191               , 'text/css'               : (GenTextPage, CssMinifier)
192               , 'text/plain'             : (GenTextPage, file)
193               , 'text/x-python'          : (PassThru, file)
194               , 'image/png'              : (GenImagePage, file)
195               }
196
197  print "Generating api code modules from source..."
198  modified = False
199  mimetypes.init()
200  mimetypes.add_type("text/plain", ".htc")
201 
202  # make sure we have the api base directory
203  if not os.path.isdir (api_base):
204    try:
205      os.mkdir (api_base)
206      modified = True
207    except:
208      print "Error: Cannot create '%s' for API generation" % api_base
209      sys.exit (1)
210
211  # walk the resources tree
212  walker = os.walk (api_source)
213  for root, dirs, files in walker:
214    # we don't want to process svn control directories
215    if '.svn' in dirs:
216      dirs.remove ('.svn')
217
218    # we can also dump readme and license files
219    # This is principly for tiny_mce
220    if 'readme.txt' in files:
221      files.remove ('readme.txt')
222    if 'license.txt' in files:
223      files.remove ('license.txt')
224
225    target = "%s%s" % (api_base, root[src_len:])
226   
227    #append target to Api_Packages so sub-directories are copied to site-packages during build
228    Api_Packages.append(target.replace("/", "."))
229
230    # make sure an equiv to root exists in api, generate if needed
231    if not os.path.exists (target):
232      try:
233        os.mkdir (target)
234        ifile = file("%s/__init__.py" % target, 'w')
235        ifile.close()
236        modified = True
237      except:
238        print "Error: Cannot create '%s' for API generation" % target
239        sys.exit (1)
240    for f in files:
241      # skip any files starting with "."
242      if f[0] != ".":
243        # check that an equiv to f exists in api, and is not newer
244        sourcefile = os.path.join (root, f)
245        targetfile = os.path.join (target, rcs_to_py(f))
246        if (not os.path.exists (targetfile)) \
247        or os.path.getmtime (targetfile) < os.path.getmtime (sourcefile):
248          contentType = mimetypes.guess_type(sourcefile)[0]
249          if contentType:
250            print "Generating '%s' (%s) from '%s'..." % (targetfile, contentType, f)
251            proc, filter = generators.get (contentType, (None, None))
252            if proc:
253              if proc (filter (sourcefile), targetfile, contentType):
254                modified = True
255              else:
256                print "Fatal Error while converting source file '%s'" % sourcefile
257                sys.exit (1)
258            else:
259              print "Warning: unhandled source file '%s' of type '%s'" % (sourcefile, fullContentType)
260          else:
261            print "Warning: unhandled source file '%s' of UNKNOWN type" % sourcefile
262
263  # if we've found a modified file and/or the api module init wasn't there, set the install time
264  if modified or not os.path.isfile (api_init):
265    initsrc = file (api_init, 'w')
266    initsrc.write ('#!/usr/bin/python\n\n')
267    initsrc.write("# This file is created on the fly by setup and should not be edited by human hands\n\n")
268    initsrc.write('CMS_INSTALL_TIME = "%s"\n' % datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT"))
269    initsrc.close()
270
271def EnumerateAssetTypes ():
272  print "Generating Type List..."
273  types = ['TurtolCMS.Core.CmsType']  # the only guaranteed type
274  # Create the list of all known types
275  for l in Libraries:
276    print "... from library '%s'" % l
277    walker = os.walk (l)
278    for root, dirs, files in walker:
279      if '.svn' in dirs:
280        dirs.remove ('.svn')
281
282      for f in files:
283        if f[-3:] == '.py' and f[:2] != '__':
284          types.append ("%s.%s" % (l, f[0:-3]))
285  if types:
286    f = file ('TurtolCMS/Api/TypeList.py', 'w')
287    f.write ('TypeList = [\n')
288    for t in types:
289      f.write (  "'%s',\n" % t.replace ('/', '.'))
290    f.write (' ]\n')
291    f.close()
292  else:
293    print "types is none?"
294
295Api_Packages = []
296Libraries = ['TurtolCMS/Types']
297
298# This next is naive, but good enough for now.
299if len(sys.argv) > 1 and sys.argv[1] in ['gen', 'build', 'build_py', 'install', 'install_py']:
300  #generate our js, css and img resources from source
301  GenerateResources()
302  EnumerateAssetTypes()
303  if sys.argv[1] == 'gen':
304    sys.exit (0)
305
306# raise RuntimeError ('aborting; testing mode')
307
308from TurtolCMS import __version__ as cms_version
309from distutils.core import setup
310setup (name='TurtolCMS',
311      description='Turtol Content Management System',
312      author='The TurtolCMS Team',
313      author_email='Dev@TurtolCMS.org',
314      url='http://www.turtolcms.org',
315      version= cms_version,
316      license='AGPL-3',
317      packages = [ 'TurtolCMS'
318                 , 'TurtolCMS.Api'
319#                 , 'TurtolCMS.Application'
320#                 , 'TurtolCMS.Assets'
321                 , 'TurtolCMS.BootStrap'
322#                 , 'TurtolCMS.Calendar'
323#                 , 'TurtolCMS.Controls'
324                 , 'TurtolCMS.Core'
325#                 , 'TurtolCMS.Forms'
326#                 , 'TurtolCMS.GoogleTools'
327                 , 'TurtolCMS.Libs'                 
328#                 , 'TurtolCMS.Newsletter'
329#                 , 'TurtolCMS.Pages'
330                 , 'TurtolCMS.Storage'
331                 , 'TurtolCMS.Types'
332#                 , 'TurtolCMS.Widgets'
333                 ] + Api_Packages + Libraries,
334      data_files = [ ('/usr/bin', ['utils/tcms']) # , 'utils/tcmsSend'])
335#                   , ('/usr/share/TurtolCMS', ['utils/tcms5to6.sql'])
336                   ]
337      )
338
339# vim: set ts=2 sw=2 expandtab: #
Note: See TracBrowser for help on using the browser.