Commits

murarth committed 052513c

Added command to setup.py for compiling JavaScript, removed Makefile, added example configuration files

  • Participants
  • Parent commits f00f705

Comments (0)

Files changed (7)

File Makefile

-# Makefile for reddish web app
-
-CAT = cat
-PYTHON = python
-# Closure Compiler, optionally used to minify JavaScript files
-# Project page: http://code.google.com/closure/compiler/
-# Download: http://closure-compiler.googlecode.com/files/compiler-latest.zip
-# Web service, used if compiler.jar location is not given:
-# http://closure-compiler.appspot.com/
-JSCOMPILER =
-
-# Pre-compiled JavaScript libraries from an external source
-EXTERN_JS = \
-	jquery.js \
-
-# Project JavaScript files compiled into a single output
-JS_INPUT = \
-	util.js \
-	json-form.js \
-	api.js \
-	edit.js \
-	ready.js \
-
-JS_DIR = reddish/public/script
-JS_FILES = $(foreach js,$(JS_INPUT),$(JS_DIR)/$(js))
-EXTERN_JS_FILES = $(foreach js,$(EXTERN_JS),$(JS_DIR)/$(js))
-
-COMPILED_JS = $(patsubst %.js,%.jsc,$(JS_FILES))
-
-JS_OUTPUT = $(JS_DIR)/reddish.js
-
-all: $(JS_OUTPUT)
-
-clean:
-	-rm -f $(JS_OUTPUT) $(COMPILED_JS)
-
-ifeq ($(JSCOMPILER),)
-$(COMPILED_JS) : %.jsc : %.js
-	$(PYTHON) compiler.py -o $@ $<
-else
-$(COMPILED_JS) : %.jsc : %.js
-	$(PYTHON) compiler.py -o $@ $< --jar $(JSCOMPILER)
-endif
-
-$(JS_OUTPUT): $(EXTERN_JS_FILES) $(COMPILED_JS)
-	$(CAT) > $@ $(EXTERN_JS_FILES) $(COMPILED_JS)
-
-.PHONY: all clean
 Installation and Setup
 ======================
 
-Install ``reddish`` using easy_install::
+Install ``reddish``::
 
-    easy_install reddish
+	python setup.py build
+	python setup.py build_js
+	python setup.py install
 
-Make a config file as follows::
-
-    paster make-config reddish config.ini
-
-Tweak the config file as appropriate and then setup the application::
+Create a config file using one of the examples, then setup the application::
 
     paster setup-app config.ini
 
 COMPILATION_LEVEL = 'SIMPLE_OPTIMIZATIONS'
 WARNING_LEVEL = 'DEFAULT'
 
+COMPILER_URL = 'http://closure-compiler.appspot.com/compile'
+
 class CompilerResponse(object):
 
     def compiled_code(self):
             return ['{0}:{lineno}:{warning}'.format(fname, **w)
                 for w in res['warnings']]
 
+class LocalCompiler(object):
+
+    def __init__(self, jar):
+        self.jar = jar
+
+    def compile(self, fname):
+        return LocalResponse(fname, self.jar)
+
+class WebCompiler(object):
+
+    def __init__(self, url = COMPILER_URL):
+        self.url = url
+
+    def compile(self, fname):
+        return WebCompilerResponse(fname, self.url)
+
 def local_compile(fname, jar):
     return LocalResponse(fname, jar)
 
         self.add_option('-o', '--output', action = 'store', metavar = 'NAME',
             help = 'Output filename, defaults to stdout')
         self.add_option('-w', '--web-service', action = 'store', metavar = 'URL',
-            default = 'http://closure-compiler.appspot.com/compile',
+            default = COMPILER_URL,
             help = 'URL of Closure Compiler web service')
 
-if __name__ == '__main__':
-    p = CompilerOptions()
-    opts, args = p.parse_args()
-
-    if not args:
-        print('Missing input filename', file = sys.stderr)
-        raise sys.exit(1)
-
-    fname = args[0]
-
-    if opts.jar:
-        r = local_compile(fname, opts.jar)
+def compile_js(fname, jar = None, url = COMPILER_URL):
+    if isinstance(fname, CompilerResponse):
+        r = fname
     else:
-        r = web_service_compile(fname, opts.web_service)
+        if jar:
+            r = local_compile(fname, jar)
+        else:
+            r = web_service_compile(fname, url)
 
     errors = r.errors()
 
         print('Warnings:', file = sys.stderr)
         [print(w, file = sys.stderr) for w in warnings]
 
-    code = r.compiled_code()
+    return r.compiled_code()
+
+if __name__ == '__main__':
+    p = CompilerOptions()
+    opts, args = p.parse_args()
+
+    if not args:
+        print('Missing input filename', file = sys.stderr)
+        raise sys.exit(1)
+
+    fname = args[0]
+
+    if opts.jar:
+        code = compile_js(fname, jar = opts.jar)
+    else:
+        code = compile_js(fname, url = opts.web_service)
 
     with open(opts.output, 'w') if opts.output else sys.stdout as f:
         f.write(code)

File development.ini.example

+#
+# reddish - Pylons development environment configuration
+#
+# The %(here)s variable will be replaced with the parent directory of this file
+#
+[DEFAULT]
+debug = true
+# Uncomment and replace with the address which should receive any error reports
+#email_to = you@yourdomain.com
+#smtp_server = localhost
+#error_email_from = paste@localhost
+
+[server:main]
+use = egg:Paste#http
+host = 127.0.0.1
+port = 5000
+
+[app:main]
+use = egg:reddish
+full_stack = true
+static_files = true
+
+cache_dir = %(here)s/data
+# Name of session cookie
+session.key = reddish
+# Allowed domain for cookies
+#session.cookie_domain = .my-reddish-site.com
+
+# URI to MongoDB server
+mongodb.host = mongodb://user:password@hostname/reddish_dev
+
+# Names of authorized Administrator users
+admins = admin
+# Displayed admin contact email
+contact_email = admin@my-reddish-site.com
+# Expiry of 'remember me' cookies
+cookie_expires = 1y
+# Default domain name
+domain = my-reddish-site.com
+# Accepted domain names which won't result in a redirect
+# Implicitly includes above named domain
+domains = other-reddish-site.com
+# Noun used to indicate a user
+demonym = user
+# Plural form of demonym
+demonym_pl = users
+# Default frontpage communities
+default_communities =
+# Domain in From header for outgoing email; defaults to 'domain' if missing
+email_domain = my-reddish-site.com
+# Whether to enable CAPTCHA verification for submissions and registration
+enable_captcha = true
+# Whether to enable HTTPS by default for logins
+enable_https = false
+# Whether to force HTTPS on all pages
+force_https = false
+# Whether to force HTTPS for logins
+force_https_login = false
+# google_ad_client value for Google AdSense
+google_ad_client =
+# google_ad_slot value for Google AdSense
+google_ad_slot =
+# Account value for Google Analytics
+google_analytics =
+# Headline in title on frontpage
+headline =
+# Optional alternate domain name for HTTPS requests
+https_domain = ssl.my-reddish-site.com
+# Optional favicon URI
+icon = /icons/my-icon.png
+# MIME type for icon
+icon_type = image/png
+# Whether to log server errors
+log_errors = false
+# URI to alternate compiled Javascript
+script_name = /script/reddish.js
+# Secret used in generating cryptographic hashes
+secret = somesecret
+# Hostname for SMTP server, defaults to localhost
+smtp_host = localhost
+# URI to alternate CSS stylesheet
+stylesheet = /reddish.css
+# Website title
+title = reddish
+
+# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
+# Debug mode will enable the interactive debugging tool, allowing ANYONE to
+# execute malicious code after an exception is raised.
+#set debug = false
+
+# Logging configuration
+[loggers]
+keys = root, routes, reddish, mail, mongodb, util
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_routes]
+level = INFO
+handlers =
+qualname = routes.middleware
+# "level = DEBUG" logs the route matched and routing variables.
+
+[logger_reddish]
+level = DEBUG
+handlers =
+qualname = reddish
+
+[logger_mail]
+level = DEBUG
+handlers =
+qualname = mail
+
+[logger_mongodb]
+level = WARN
+handlers =
+qualname = mongodb
+
+[logger_util]
+level = WARN
+handlers =
+qualname = util
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s
+datefmt = %H:%M:%S

File production.ini.example

+#
+# reddish - Pylons development environment configuration
+#
+# The %(here)s variable will be replaced with the parent directory of this file
+#
+[DEFAULT]
+debug = false
+# Uncomment and replace with the address which should receive any error reports
+#email_to = you@yourdomain.com
+#smtp_server = localhost
+#error_email_from = paste@localhost
+
+[server:main]
+use = egg:Paste#http
+host = 0.0.0.0
+port = 8080
+
+[app:main]
+use = egg:reddish
+full_stack = true
+static_files = true
+
+cache_dir = %(here)s/data
+# Name of session cookie
+session.key = reddish
+# Allowed domain for cookies
+#session.cookie_domain = .my-reddish-site.com
+
+# URI to MongoDB server
+mongodb.host = mongodb://user:password@hostname/reddish
+
+# Names of authorized Administrator users
+admins = admin
+# Displayed admin contact email
+contact_email = admin@my-reddish-site.com
+# Expiry of 'remember me' cookies
+cookie_expires = 1y
+# Default domain name
+domain = my-reddish-site.com
+# Accepted domain names which won't result in a redirect
+# Implicitly includes above named domain
+domains = other-reddish-site.com
+# Noun used to indicate a user
+demonym = user
+# Plural form of demonym
+demonym_pl = users
+# Default frontpage communities
+default_communities =
+# Domain in From header for outgoing email; defaults to 'domain' if missing
+email_domain = my-reddish-site.com
+# Whether to enable CAPTCHA verification for submissions and registration
+enable_captcha = true
+# Whether to enable HTTPS by default for logins
+enable_https = false
+# Whether to force HTTPS on all pages
+force_https = false
+# Whether to force HTTPS for logins
+force_https_login = false
+# google_ad_client value for Google AdSense
+google_ad_client =
+# google_ad_slot value for Google AdSense
+google_ad_slot =
+# Account value for Google Analytics
+google_analytics =
+# Headline in title on frontpage
+headline =
+# Optional alternate domain name for HTTPS requests
+https_domain = ssl.my-reddish-site.com
+# Optional favicon URI
+icon = /icons/my-icon.png
+# MIME type for icon
+icon_type = image/png
+# Whether to log server errors
+log_errors = false
+# URI to alternate compiled Javascript
+script_name = /script/reddish.js
+# Secret used in generating cryptographic hashes
+secret = somesecret
+# Hostname for SMTP server, defaults to localhost
+smtp_host = localhost
+# URI to alternate CSS stylesheet
+stylesheet = /reddish.css
+# Website title
+title = reddish
+
+# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
+# Debug mode will enable the interactive debugging tool, allowing ANYONE to
+# execute malicious code after an exception is raised.
+set debug = false
+
+# Logging configuration
+[loggers]
+keys = root, routes, reddish, mail, mongodb, util
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_routes]
+level = INFO
+handlers =
+qualname = routes.middleware
+# "level = DEBUG" logs the route matched and routing variables.
+
+[logger_reddish]
+level = DEBUG
+handlers =
+qualname = reddish
+
+[logger_mail]
+level = DEBUG
+handlers =
+qualname = mail
+
+[logger_mongodb]
+level = WARN
+handlers =
+qualname = mongodb
+
+[logger_util]
+level = WARN
+handlers =
+qualname = util
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s
+datefmt = %H:%M:%S

File reddish/config/deployment.ini_tmpl

-#
-# reddish - Pylons configuration
-#
-# The %(here)s variable will be replaced with the parent directory of this file
-#
-[DEFAULT]
-debug = true
-email_to = you@yourdomain.com
-smtp_server = localhost
-error_email_from = paste@localhost
-
-[server:main]
-use = egg:Paste#http
-host = 0.0.0.0
-port = 5000
-
-[app:main]
-use = egg:reddish
-full_stack = true
-static_files = true
-
-cache_dir = %(here)s/data
-beaker.session.key = reddish
-beaker.session.secret = ${app_instance_secret}
-app_instance_uuid = ${app_instance_uuid}
-
-# If you'd like to fine-tune the individual locations of the cache data dirs
-# for the Cache data, or the Session saves, un-comment the desired settings
-# here:
-#beaker.cache.data_dir = %(here)s/data/cache
-#beaker.session.data_dir = %(here)s/data/sessions
-
-# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
-# Debug mode will enable the interactive debugging tool, allowing ANYONE to
-# execute malicious code after an exception is raised.
-set debug = false
-
-
-# Logging configuration
-[loggers]
-keys = root
-
-[handlers]
-keys = console
-
-[formatters]
-keys = generic
-
-[logger_root]
-level = INFO
-handlers = console
-
-[handler_console]
-class = StreamHandler
-args = (sys.stderr,)
-level = NOTSET
-formatter = generic
-
-[formatter_generic]
-format = %(asctime)s %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s
     use_setuptools()
     from setuptools import setup, find_packages, Extension
 
+from compiler import compile_js, LocalCompiler, WebCompiler
+from distutils.core import Command
+from distutils.command.build import build
+import os
+import shutil
+
+class build_js(Command):
+
+    description = '''Compile JavaScript files'''
+
+    user_options = [
+        ('js-compiler=', None,
+            'path to Closure Compiler or URL to compiler service'),
+        ('js-output=', None,
+            'output for compiled JavaScript'),
+    ]
+
+    JS_PATH = 'reddish/public/script/'
+
+    extern_js = [
+        'jquery.js',
+    ]
+
+    js_files = [
+        'util.js',
+        'json-form.js',
+        'api.js',
+        'edit.js',
+        'ready.js',
+    ]
+
+    def initialize_options(self):
+        self.js_compiler = None
+        self.js_output = 'reddish.js'
+
+    def finalize_options(self):
+        if '/' not in self.js_output:
+            self.js_output = self.JS_PATH + self.js_output
+
+    def run(self):
+        PATH = self.JS_PATH
+        js_compiler = self.js_compiler
+
+        if not js_compiler:
+            compiler = WebCompiler()
+        elif js_compiler.startswith('http://') or js_compiler.startswith('https://'):
+            compiler = WebCompiler(js_compiler)
+        else:
+            compiler = LocalCompiler(js_compiler)
+
+        try:
+            target = os.stat(self.js_output).st_mtime
+        except OSError:
+            target = 0
+
+        for js in self.js_files:
+            fname = PATH + js
+            if self.file_modified(fname):
+                print 'Compiling JavaScript file', fname
+                code = compile_js(compiler.compile(fname))
+                with open(fname + 'c', 'w') as f:
+                    f.write(code)
+
+        if self.inputs_modified():
+            print 'Concatenating compiled JavaScript to', self.js_output
+            with open(self.js_output, 'w') as out:
+                for js in self.js_inputs():
+                    with open(js, 'r') as f:
+                        shutil.copyfileobj(f, out)
+
+    def file_modified(self, fname):
+        mtime = os.stat(fname).st_mtime
+        try:
+            return mtime > os.stat(fname + 'c').st_mtime
+        except OSError:
+            return True
+
+    def js_inputs(self):
+        BASE = self.JS_PATH
+
+        for js in self.extern_js:
+            yield BASE + js
+
+        for js in self.js_files:
+            yield BASE + js + 'c'
+
+    def inputs_modified(self):
+        try:
+            mtime = os.stat(self.js_output).st_mtime
+        except OSError:
+            return True
+
+        for js in self.js_inputs():
+            if os.stat(js).st_mtime > mtime:
+                return True
+
+        return False
+
 import glob
 import sys
 
     install_requires = dependencies,
     setup_requires = ["PasteScript>=1.6.3"],
     packages = find_packages(exclude = ['ez_setup']),
+    cmdclass = {
+        'build_js': build_js,
+    },
     ext_modules = [
         Extension(
             name = 'reddish.lib.sundown',