STATIC_URL = BASE_PATH + 'static/' # Absolute path to the directory that shall hold all uploaded files as well as # files created at runtime. # Example: "/home/media/media.lawrence.com/" UPLOAD_ROOT = join(dirname(dirname(dirname(__file__))),'data') EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': UPLOAD_ROOT+'/Database', } } JPLAGJAR = join(dirname(dirname(dirname(__file__))), 'jplag.jar') PRIVATE_KEY = join(dirname(dirname(dirname(__file__))), 'examples', 'certificates', 'privkey.pem') # Finally load defaults for missing setttings. import defaults defaults.load_defaults(globals()) # To get exceptions logged as well: MIDDLEWARE_CLASSES += ( 'utilities.exceptionlogger.ExceptionLoggingMiddleware', )
class Wrangler(object): defaults = defaults.load_defaults() # Default config just loads the YAML config file config = { "wrangler": { "verbose": False, "force": False, "nocache": False, "input_dir": False, "output_dir": False, "data_formats": None }, "site": {}, "extensions": {} } # User config path config_path = 'wrangler.yaml' extension_results = {} # Hmm it turns out there's not going to be any global options at all, the whole app # works best as a series of subcommands with very independent options. def parse_args(self, args=None): d = '\033[32mProcess recursive directories of JSON files through Jinja2 templates. \033[0m' parser = argparse.ArgumentParser(description=d) subparsers = parser.add_subparsers(dest="subparser", help='sub-command help') # --------------------------------------------------------------------- # wrangler create . # --------------------------------------------------------------------- # Creating a new project/scaffolding parser_generate = subparsers.add_parser('create', help='create help') parser_generate.add_argument('path', type=str, help='wrangler create path') # --------------------------------------------------------------------- # wrangler serve www # --------------------------------------------------------------------- # Serving up content on a specified URL parser_serve = subparsers.add_parser('serve', help='server help') parser_serve.add_argument('path', type=str, help='wrangler server path') parser_serve.add_argument( "-p", "--port", help='\033[34mThe port number, eg `8000`\033[0m', type=int) # --------------------------------------------------------------------- # wrangler build [i] [o] # --------------------------------------------------------------------- # Running the build command parser_build = subparsers.add_parser('build', help='build help') parser_build.add_argument( 'input_dir', help='\033[34mInput directory such as `content`\033[0m') parser_build.add_argument( 'output_dir', help='\033[34mOutput directory such as `www`\033[0m') parser_build.add_argument( "-t", "--templates_dir", help='\033[34mTemplate directory such as `templates`\033[0m') parser_build.add_argument( "-c", "--config", help='\033[34mPath to `wrangler.json`\033[0m') parser_build.add_argument( "-o", "--output_file_extension", help='\033[34mType of files to output such as `html`\033[0m') parser_build.add_argument( "-d", "--data_format", help= '\033[34mType of files to match in input_dir, such as `json`\033[0m' ) parser_build.add_argument("-v", "--verbose", action="store_true", help='\033[34mPrint all the plumbing\033[0m') parser_build.add_argument( "-f", "--force", action="store_true", help= '\033[34mSmash out all the templates regardless of mtime\033[0m') parser_build.add_argument( "-n", "--nocache", action="store_true", help='\033[34mTurn off data persistence\033[0m') # --------------------------------------------------------------------- # wrangler watch [i] [o] # --------------------------------------------------------------------- # Same config as build.. parser_watch = subparsers.add_parser('watch', help='build help') parser_watch.add_argument( 'input_dir', help='\033[34mInput directory such as `content`\033[0m') parser_watch.add_argument( 'output_dir', help='\033[34mOutput directory such as `www`\033[0m') parser_watch.add_argument( "-f", "--force", action="store_true", help= '\033[34mSmash out all the templates regardless of mtime\033[0m') parser_watch.add_argument( "-n", "--nocache", action="store_true", help='\033[34mTurn off data persistence\033[0m') parser_watch.add_argument("-v", "--verbose", action="store_true", help='\033[34mPrint all the plumbing\033[0m') parser_clean = subparsers.add_parser('clean', help='clean help') return parser.parse_args(args) def update_config(self, args): userConfig = None # Load the defaults self.config.update(self.defaults) # Check for custom config in the arguments if (hasattr(args, "config")): if args.config != None: self.config_path = args.config # Load custom config if it exists _path = u"%s" % (self.config_path) if os.path.exists(_path): userConfig = yaml.load(file(_path)) self.config.update(userConfig) # # Apply command line flags if set, ignore Nones. self.config["wrangler"].update( (k, v) for k, v in args.__dict__.iteritems() if v is not None) # If there's a library path, load all the modules if "lib_path" in self.config["wrangler"]: self.load_classes(self.config["wrangler"]["lib_path"]) def main(self, args=None): args = self.parse_args(args) self.update_config(args) # Reporter only really needs to check the verbosity level self._reporter = Core.Reporter(self.config, self.config_path) if "subparser" in args: if args.subparser == "create": generate.NewProject(args.path, self._reporter) exit() if args.subparser == "serve": port = None if args.port: port = args.port serve.BasicServer(args.path, self._reporter, port) if args.subparser == "build": self._reporter.log( "Wrangling %s" % (self.config['wrangler']['input_dir']), "green") self.render() if args.subparser == "watch": watch_init = signal('watch_init') watch_change = signal('watch_change') watch_init.connect(self.on_watch_ready) watch_change.connect(self.on_watch_change) watcher = watch.Watcher( self.config["wrangler"]["input_dir"], self.config["wrangler"]["templates_dir"]) if args.subparser == "clean": # self.update_config(args) files = [ self.config["wrangler"]["compiled_templates_file"], self.config["wrangler"]["build_cache_file"] ] for f in files: if os.path.exists(f): try: os.remove(f) self._reporter.log("Cleaning up: %s" % (f), "blue") except: self._reporter.log("Couldn't access: %s" % (f), "red") self._reporter.log("Done", "green") exit() else: return None def on_watch_ready(self, sender): conf = self.config["wrangler"] self._reporter.log( messages.watch_start % (conf['input_dir'], conf['templates_dir']), "blue") def on_watch_change(self, sender): self._reporter.log(messages.watch_change % (sender.src_path), "green") self.render() def render(self): conf = self.config["wrangler"] self._reader = Reader.Reader(self.config, self._reporter) self._writer = Core.Writer(conf["output_dir"], conf["output_file_extension"], self._reporter) self._renderer = renderer.JinjaStaticRenderer(self.config, self._reporter, self._writer) self.graph = self._reader.fetch() total_nodes = 0 for key, node in self.graph.all().items(): if node.tag == 'file': cargo = node.get_cargo() if cargo: cargo.set_output_path( self._writer.generate_output_path(cargo.relpath())) total_nodes += 1 before = signal('wranglerBeforeRender') result = before.send('wrangler', config=self.config, renderer=self._renderer, reporter=self._reporter, nodes=self.graph) self.process_extensions() rendered = 0 for key, node in self.graph.all().items(): if node.tag == 'file': # Leaky boat. cargo = node.get_cargo() if cargo: cargo.set_parents(node.get_parents()) cargo.set_children(node.get_child_pages()) cargo.set_siblings(node.get_siblings()) cargo.set_parents_siblings(node.get_parents_siblings()) _rel = cargo.get_related() if _rel != None: arr = self.graph.all() related = [] for item in _rel: _item = arr.get(item) if _item: related.append(_item) cargo.set_related_nodes(related) # The important bit that does the saving and the rendering if self._writer.save( self._renderer.render( cargo, meta=cargo.get_metadata(), data=cargo.get_content(), site=self.config["site"], extensions=self.extension_results)): rendered += 1 cargo.cleanup() del cargo after = signal('wranglerAfterRender') final_result = after.send('wrangler', config=self.config, renderer=self._renderer, reporter=self._reporter, nodes=self.graph) if rendered > 0: self._reporter.log( messages.built_n_of_n % (rendered, total_nodes, conf["output_dir"]), "green") self._reporter.set_last_build_time() else: self._reporter.log( messages.nochange % (conf["input_dir"], conf["templates_dir"]), "red") def load_classes(self, views): """ Pull in files from the lib directory """ classfiles = [ os.path.join(dirpath, f) for dirpath, dirnames, files in os.walk(views) for f in files if f.endswith('.py') ] path = list(sys.path) sys.path.insert(0, views) moduleNames = [] for f in classfiles: moduleNames.append(os.path.basename(f.replace(".py", ""))) if len(moduleNames) > 0: try: map(__import__, moduleNames) finally: # restore the syspath sys.path[:] = path def process_extensions(self): """ Load extensions from the core and import any from the site/lib directory too """ sig = signal("wranglerExtension") results = sig.send('wrangler') # Results returns a list of tuples. # First one will be the decorator, second will be the fn for result in results: responder = result[1] self.extension_results[responder.__name__] = responder( config=self.config, reporter=self._reporter, nodes=self.graph)
# URL to use when referring to static files. STATIC_URL = BASE_PATH + 'static/' # Absolute path to the directory that shall hold all uploaded files as well as # files created at runtime. # Example: "/home/media/media.lawrence.com/" UPLOAD_ROOT = join(dirname(dirname(dirname(__file__))), 'data') EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': UPLOAD_ROOT + '/Database', } } JPLAGJAR = join(dirname(dirname(dirname(__file__))), 'jplag.jar') PRIVATE_KEY = join(dirname(dirname(dirname(__file__))), 'examples', 'certificates', 'privkey.pem') # Finally load defaults for missing setttings. import defaults defaults.load_defaults(globals()) # To get exceptions logged as well: MIDDLEWARE_CLASSES += ( 'utilities.exceptionlogger.ExceptionLoggingMiddleware', )
# Mark-Representation for db # represents a specific <Mark> asigned to one specific <Student> in a specific <Course> class Mark(db.Model): __tablename__ = "marks" __table_args__ = ( db.UniqueConstraint("metaid", "studentid", name="MetaStudentUnique"), # just one mark per student ) mid = db.Column(db.Integer, primary_key=True) metaid = db.Column(db.Integer, db.ForeignKey("markmeta.mid")) studentid = db.Column(db.Integer, db.ForeignKey("students.uid")) mark = db.Column(db.Integer) meta = db.relationship("MarkMeta", back_populates=__tablename__, lazy=True) student = db.relationship("Student", back_populates=__tablename__, lazy=True) def serialize(self): return { "name":self.meta.name, "metaid":self.metaid, "studentid":self.studentid, "mark":self.mark, "subject":self.meta.course.subject.subname } db.create_all() db.session.commit() import defaults defaults.load_defaults()