<commit_before>from abc import ABCMeta, abstractmethod

DEFAULT_PRIORITY = 30000  # Layer 4
'''
Layer 2: 20000 ~ 9999
Layer 3: 30000 ~ 9999
Layer 4: 40000 ~ 9999
'''

class Service(metaclass=ABCMeta):
    '''
    this abstract class provides software designed service
    designed for connecting networks
    ex. l2sw, l3sw, napt route, firewall and so on
    '''

    @abstractmethod
    def generate_flow(self, *args, **kwargs):
        '''
        return {
            datapath: (
                match,
                actions
            )
        }
        '''
        pass

    @abstractmethod
    def add_host(self, ev, host, app):
        '''
        add new host
        '''
        pass

    @abstractmethod
    def delete_host(self, ev, host, app):
        '''
        delete host
        '''
        pass

    @abstractmethod
    def modify_host(self, ev, host, app):
        '''
        modify host
        changed host status
        '''
        pass

    @abstractmethod
    def add_link(self, ev, link, app):
        '''
        add new link
        '''
        pass

    @abstractmethod
    def delete_link(self, ev, link, app):
        '''
        delete link
        '''
        pass

    @abstractmethod
    def modify_link(self, ev, link, app):
        '''
        modify link
        changed link status
        '''
        pass

    @abstractmethod
    def add_switch(self, switch):
        '''
        add switch
        '''
        pass

    @abstractmethod
    def delete_switch(self, switch):
        '''
        delete switch
        '''
        pass

    @abstractmethod
    def packet_in_handler(self, ev, app):
        '''
        this method called when packet in
        '''
        pass

    @abstractmethod
    def reinit_ports(self, ev, switch, app):
        '''
        this method called when switch registered
        check and initilize objects
        '''
        pass
<commit_msg>updated service for register UUIDObject and add, delete switch<commit_after>from abc import ABCMeta, abstractmethod

from mike.lib.mike_object import UUIDObject, UUIDObjectType

DEFAULT_PRIORITY = 30000  # Layer 4
'''
Layer 2: 20000 ~ 9999
Layer 3: 30000 ~ 9999
Layer 4: 40000 ~ 9999
'''

class Service(metaclass=ABCMeta):
    '''
    this abstract class provides software designed service
    designed for connecting networks
    ex. l2sw, l3sw, napt route, firewall and so on
    '''

    def __init__(self, uuid):
        '''
        register UUIDObject and generate uuid
        '''
        if uuid:
            self.uuid_object = UUIDObject(uuid=uuid)
        else:
            t = UUIDObjectType.objects.filter(name=self.__class__.__name__)
            self.uuid_object = UUIDObject(type=t)
            self.uuid_object.save()

    @abstractmethod
    def generate_flow(self, *args, **kwargs):
        '''
        return {
            datapath: (
                match,
                actions
            )
        }
        '''
        pass

    @abstractmethod
    def add_host(self, ev, host, app):
        '''
        add new host
        '''
        pass

    @abstractmethod
    def delete_host(self, ev, host, app):
        '''
        delete host
        '''
        pass

    @abstractmethod
    def modify_host(self, ev, host, app):
        '''
        modify host
        changed host status
        '''
        pass

    @abstractmethod
    def add_link(self, ev, link, app):
        '''
        add new link
        '''
        pass

    @abstractmethod
    def delete_link(self, ev, link, app):
        '''
        delete link
        '''
        pass

    @abstractmethod
    def modify_link(self, ev, link, app):
        '''
        modify link
        changed link status
        '''
        pass

    def add_switch(self, switch):
        switch.services.add(self.uuid_object)

    def delete_switch(self, switch):
        switch.services.remove(self.uuid_object)

    @abstractmethod
    def packet_in_handler(self, ev, app):
        '''
        this method called when packet in
        '''
        pass

    @abstractmethod
    def reinit_ports(self, ev, switch, app):
        '''
        this method called when switch registered
        check and initilize objects
        '''
        pass

    def delete(self):
        '''
        delete self
        '''
        raise NotImplementedError()

<|endoftext|>


<commit_before>from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
from .query import *
from cantools import util
from six import with_metaclass

def choice_validator(choices):
    def cval(s, k, v):
        if v not in choices:
            util.error("can't set %s! %s not in %s"%(k, v, choices))
        return v
    return cval

class CTMeta(DeclarativeMeta):
    def query(cls, *args, **kwargs):
        return Query(cls, *args, **kwargs)

    def __new__(cls, name, bases, attrs):
        lname = name.lower()
        attrs["__tablename__"] = lname
        if lname != "modelbase":
            attrs["__mapper_args__"] = {
                "polymorphic_identity": lname
            }
            attrs["index"] = sqlForeignKey(bases[0], primary_key=True)
            if "label" not in attrs:
                for label in ["name", "title", "topic"]:
                    if label in attrs:
                        attrs["label"] = label
                        break
            schema = attrs["_schema"] = merge_schemas(bases, attrs.get("label"))
            for key, val in list(attrs.items()):
                if getattr(val, "_ct_type", None):
                    schema[key] = val._ct_type
                    if val._ct_type.startswith("key"):
                        schema["_kinds"][key] = val._kinds
                if getattr(val, "choices", None):
                    attrs["%s_validator"%(key,)] = sqlalchemy.orm.validates(key)(choice_validator(val.choices))
        modelsubs[lname] = super(CTMeta, cls).__new__(cls, name, bases, attrs)
        modelsubs[lname].__name__ = lname
        return modelsubs[lname]

sa_dbase = declarative_base(metadata=metadata)

class ModelBase(with_metaclass(CTMeta, sa_dbase)):
    index = Integer(primary_key=True)
    polytype = String()
    key = CompositeKey()
    __mapper_args__ = {
        "polymorphic_on": polytype,
        "polymorphic_identity": "modelbase",
        "with_polymorphic": "*"
    }
    label = "key"
    _data_omit = []

    def __init__(self, *args, **kwargs):
        sa_dbase.__init__(self, *args, **kwargs)
        self._defaults()
        self._init()

    @orm.reconstructor
    def _init(self):
        self._name = "%s(%s)"%(self.polytype, getattr(self, self.label))
        self._orig_fkeys = {}
        for prop in self._schema["_kinds"]:
            self._orig_fkeys[prop] = getattr(self, prop)

    def _defaults(self):
        for prop in self._schema["_kinds"]:
            if getattr(self, prop, None) is None:
                if self._schema[prop].endswith("list"):
                    val = []
                else:
                    val = KeyWrapper()
                setattr(self, prop, val)
        self.key = KeyWrapper()
        for key, val in list(self.__class__.__dict__.items()):
            if getattr(self, key, None) is None and getattr(val, "_default", None) is not None:
                setattr(self, key, val._default)

    def __eq__(self, other):
        return self.id() == (other and hasattr(other, "id") and other.id())

    def __ne__(self, other):
        return not self.__eq__(other)

    def put(self, session=session):
        put_multi([self], session)

    def rm(self, commit=True, session=session):
        session.delete(self)
        if commit:
            session.commit()

    def collection(self, entity_model, property_name=None, fetch=True, keys_only=False, data=False):
        if isinstance(entity_model, str):
            entity_model = get_model(entity_model)
        q = entity_model.query(getattr(entity_model, property_name or self.polytype) == self.key)
        if not fetch:
            return q
        if not data:
            return q.fetch(1000, keys_only=keys_only)
        return [d.data() for d in q.fetch(1000)]

    def modeltype(self):
        return self.__tablename__

    def id(self):
        return self.key.urlsafe()

    def _has_complete_key(self):
        return bool(self.id())

    def mydata(self, isexport=False):
        cols = {}
        for key, prop in list(self._schema.items()):
            if not isexport and key in self._data_omit:
                continue
            if not key.startswith("_"):
                val = getattr(self, key)
                if prop.startswith("key"):
                    if type(val) is list:
                        val = [v.urlsafe() for v in val]
                    elif hasattr(val, "urlsafe"):
                        val = val.urlsafe()
                elif prop == "blob" and hasattr(val, "urlsafe"):
                    val = val.urlsafe()
                elif val and prop == "datetime":
                    val = str(val)[:19]
                elif prop in ["string", "text"]:
                    val = val or ""
                cols[key] = val
        return cols

    def _basic(self, d):
        d["key"] = self.id()
        d["index"] = self.index
        d["modelName"] = self.polytype
        d["_label"] = self.label
        d["label"] = d[self.label] or "%s %s"%(self.polytype, self.index)
        return d

    def data(self):
        return self._basic(self.mydata())

    def export(self):
        return self._basic(ModelBase.mydata(self, True))

class TimeStampedBase(ModelBase):
    created = DateTime(auto_now_add=True)
    modified = DateTime(auto_now=True)<commit_msg>Model: beforeremove() and afterremove() rm() hooks<commit_after>from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
from .query import *
from cantools import util
from six import with_metaclass

def choice_validator(choices):
    def cval(s, k, v):
        if v not in choices:
            util.error("can't set %s! %s not in %s"%(k, v, choices))
        return v
    return cval

class CTMeta(DeclarativeMeta):
    def query(cls, *args, **kwargs):
        return Query(cls, *args, **kwargs)

    def __new__(cls, name, bases, attrs):
        lname = name.lower()
        attrs["__tablename__"] = lname
        if lname != "modelbase":
            attrs["__mapper_args__"] = {
                "polymorphic_identity": lname
            }
            attrs["index"] = sqlForeignKey(bases[0], primary_key=True)
            if "label" not in attrs:
                for label in ["name", "title", "topic"]:
                    if label in attrs:
                        attrs["label"] = label
                        break
            schema = attrs["_schema"] = merge_schemas(bases, attrs.get("label"))
            for key, val in list(attrs.items()):
                if getattr(val, "_ct_type", None):
                    schema[key] = val._ct_type
                    if val._ct_type.startswith("key"):
                        schema["_kinds"][key] = val._kinds
                if getattr(val, "choices", None):
                    attrs["%s_validator"%(key,)] = sqlalchemy.orm.validates(key)(choice_validator(val.choices))
        modelsubs[lname] = super(CTMeta, cls).__new__(cls, name, bases, attrs)
        modelsubs[lname].__name__ = lname
        return modelsubs[lname]

sa_dbase = declarative_base(metadata=metadata)

class ModelBase(with_metaclass(CTMeta, sa_dbase)):
    index = Integer(primary_key=True)
    polytype = String()
    key = CompositeKey()
    __mapper_args__ = {
        "polymorphic_on": polytype,
        "polymorphic_identity": "modelbase",
        "with_polymorphic": "*"
    }
    label = "key"
    _data_omit = []

    def __init__(self, *args, **kwargs):
        sa_dbase.__init__(self, *args, **kwargs)
        self._defaults()
        self._init()

    @orm.reconstructor
    def _init(self):
        self._name = "%s(%s)"%(self.polytype, getattr(self, self.label))
        self._orig_fkeys = {}
        for prop in self._schema["_kinds"]:
            self._orig_fkeys[prop] = getattr(self, prop)

    def _defaults(self):
        for prop in self._schema["_kinds"]:
            if getattr(self, prop, None) is None:
                if self._schema[prop].endswith("list"):
                    val = []
                else:
                    val = KeyWrapper()
                setattr(self, prop, val)
        self.key = KeyWrapper()
        for key, val in list(self.__class__.__dict__.items()):
            if getattr(self, key, None) is None and getattr(val, "_default", None) is not None:
                setattr(self, key, val._default)

    def __eq__(self, other):
        return self.id() == (other and hasattr(other, "id") and other.id())

    def __ne__(self, other):
        return not self.__eq__(other)

    def put(self, session=session):
        put_multi([self], session)

    def beforeremove(self, session):
        pass

    def afterremove(self, session):
        pass

    def rm(self, commit=True, session=session):
        self.beforeremove(session)
        session.delete(self)
        if commit:
            session.commit()
        self.afterremove(session)

    def collection(self, entity_model, property_name=None, fetch=True, keys_only=False, data=False):
        if isinstance(entity_model, str):
            entity_model = get_model(entity_model)
        q = entity_model.query(getattr(entity_model, property_name or self.polytype) == self.key)
        if not fetch:
            return q
        if not data:
            return q.fetch(1000, keys_only=keys_only)
        return [d.data() for d in q.fetch(1000)]

    def modeltype(self):
        return self.__tablename__

    def id(self):
        return self.key.urlsafe()

    def _has_complete_key(self):
        return bool(self.id())

    def mydata(self, isexport=False):
        cols = {}
        for key, prop in list(self._schema.items()):
            if not isexport and key in self._data_omit:
                continue
            if not key.startswith("_"):
                val = getattr(self, key)
                if prop.startswith("key"):
                    if type(val) is list:
                        val = [v.urlsafe() for v in val]
                    elif hasattr(val, "urlsafe"):
                        val = val.urlsafe()
                elif prop == "blob" and hasattr(val, "urlsafe"):
                    val = val.urlsafe()
                elif val and prop == "datetime":
                    val = str(val)[:19]
                elif prop in ["string", "text"]:
                    val = val or ""
                cols[key] = val
        return cols

    def _basic(self, d):
        d["key"] = self.id()
        d["index"] = self.index
        d["modelName"] = self.polytype
        d["_label"] = self.label
        d["label"] = d[self.label] or "%s %s"%(self.polytype, self.index)
        return d

    def data(self):
        return self._basic(self.mydata())

    def export(self):
        return self._basic(ModelBase.mydata(self, True))

class TimeStampedBase(ModelBase):
    created = DateTime(auto_now_add=True)
    modified = DateTime(auto_now=True)<|endoftext|>


<commit_before>"""
### Usage: ctinit [projname] [-r] [--plugins=P1|P2|P3] [--cantools_path=PATH] [--web_backend=BACKEND]

### Options:
    -h, --help            show this help message and exit
    -p PLUGINS, --plugins=PLUGINS
                          which plugins would you like to use in your project?
    -c CANTOOLS_PATH, --cantools_path=CANTOOLS_PATH
                          where is cantools? (default: /guessed/path/from/__file__)
    -w WEB_BACKEND, --web_backend=WEB_BACKEND
                          web backend. options: dez, gae. (default: dez)
    -r, --refresh_symlinks
                          add symlinks to project and configure version control
                          path exclusion (if desired)
    -u, --update          update cantools and all managed plugins

NB: it may be necessary to specify --cantools_path. Normally, this is derived from
the __file__ property (the location of the ctinit script, init.py). However, if the
package lives in your Python dist-packages (as with 'easy_install', as well as
'setup.py install'), it does not contain the client-side files necessary for an
end-to-end web application, and these files therefore cannot be symlinked into your
new project. In these cases, indicate --cantools_path (the path to the cloned cantools
repository on your computer), and everything should work fine.

Generally speaking, one should clone the cantools github repository, 'setup.py install'
it (for the 'ct' commands), and then run 'setup.py develop', which will point 'cantools'
at your cloned cantools repo and keep the package up to date as you periodically 'git pull'
the latest version. Similarly, plugins should be kept in 'develop' mode, as they also will
generally have non-python files of consequence.

In most cases, the developer won't have to pay much attention to this stuff, because
initializing or refreshing a project will automatically install any necessary plugins
that aren't already present. Similarly, the --update flag pulls down the latest versions
of cantools and all managed plugins. Thus, plugins are dealt with under the hood without
any need for the developer to know or do anything beyond 'ctinit -r'.
"""

import os, sys
from optparse import OptionParser
from cantools import config
from cantools.util import log, error, cp, sym, mkdir, rm, cmd, read

CTP = __file__.rsplit(os.path.sep, 2)[0]

class Builder(object):
	def __init__(self, pname=None, cantools_path=CTP, web_backend="dez", refresh_symlinks=False):
		if not pname and not refresh_symlinks:
			pname = raw_input("project name? ")
		log("Initializing %s Project: %s"%(web_backend, pname or "(refresh)"))
		self.pname = pname
		self.ctroot = cantools_path
		if not os.path.exists(self.ctroot):
			error("failed to establish cantools root",
				"We tried: %s"%(self.ctroot,),
				"This directory does not contain cantools.",
				"You can download cantools at https://github.com/bubbleboy14/cantools",
				"Please pass the path to your local copy of cantools via the -c flag."
			)
		self.web_backend = web_backend
		self.refresh_symlinks = refresh_symlinks
		self.plugins = {}
		self.install_plugins()
		if not refresh_symlinks:
			self.build_dirs()
			self.make_files()
		self.vcignore()
		self.generate_symlinks()

	def _install(self, plug):
		log("Building Package: %s"%(plug,), important=True)
		curdir = os.getcwd()
		if not os.path.isdir(config.plugin.path):
			mkdir(config.plugin.path)
		os.chdir(config.plugin.path)
		log("cloning repository", important=True)
		cmd("git clone https://github.com/%s/%s.git"%(config.plugin.base, plug))
		os.chdir(plug)
		log("installing plugin", important=True)
		cmd("sudo python setup.py install")
		cmd("sudo python setup.py develop")
		os.chdir("%s/.."%(self.ctroot,))
		log("restoring cantools develop status", important=True)
		cmd("sudo python setup.py develop")
		os.chdir(curdir)
		sys.path.insert(0, os.path.join(config.plugin.path, plug))
		self._getplug(plug)

	def _getplug(self, plugin):
		log("Installing Plugin: %s"%(plugin,), important=True)
		mod = self.plugins[plugin] = __import__(plugin)
		mod.__ct_mod_path__ = mod.__file__.rsplit(os.path.sep, 1)[0]
		init = mod.init
		if hasattr(init, "model"):
			log("adding %s imports to model"%(len(init.model),), 3)
			config.init.update("model",
				"%s\r\n%s"%(config.init.model,
					"\r\n".join(["from %s import %s"%(m,
						", ".join(k)) for (m, k) in init.model.items()])))
		if hasattr(init, "routes"):
			log("adding %s routes to app.yaml"%(len(init.routes),), 3)
			config.init.yaml.update("core",
				"%s\r\n\r\n%s"%(config.init.yaml.core,
					"\r\n\r\n".join(["- url: %s\r\n  %s: %s"%(u,
						s.endswith(".py") and "script" or "static_dir", s) for (u,
						s) in init.routes.items()])))
		if hasattr(init, "jsconfig"):
			log("adding %s config entries to core.config (js)"%(len(init.jsconfig.keys()),), 3)
			config.plugin.config.update(plugin, init.jsconfig)
		if hasattr(init, "requires"):
			log("installing %s ct dependencies"%(len(init.requires),), 3)
			self._getplugs(init.requires)

	def _getplugs(self, plugs):
		for plugin in plugs:
			log("Plugin: %s"%(plugin,), 2)
			try:
				self._getplug(plugin)
			except ImportError:
				log("plugin '%s' not found! attempting install."%(plugin,), important=True)
				self._install(plugin)

	def install_plugins(self):
		pil = len(config.plugin.modules)
		if pil:
			log("Installing %s Plugins"%(pil,), 1)
			self._getplugs(config.plugin.modules)

	def build_dirs(self):
		log("building directories", 1)
		mkdir(self.pname)
		os.chdir(self.pname)
		for d in config.init.dirs:
			mkdir(d)
		if self.plugins:
			jsc = os.path.join(config.js.path, "core")
			log("Plugins Specified - adding %s"%(jsc,), important=True)
			mkdir(jsc)
			for mod in self.plugins.values():
				for d in mod.init.dirs:
					mkdir(d)

	def make_files(self):
		log("generating configuration", 1)
		cp((self.web_backend == "gae") and "%s\r\n%s"%(config.init.yaml.gae,
			config.init.yaml.core)%(self.pname,) or config.init.yaml.core, "app.yaml")
		cfg = config.init.ctcfg%(self.web_backend,)
		if self.plugins:
			cfg = os.linesep.join([cfg, "PLUGIN_MODULES = %s"%("|".join(self.plugins.keys()),)])
		cp(cfg, "ct.cfg")
		log("demo index page", 1)
		cp(config.init.html%(self.pname,), os.path.join("html", "index.html"))
		log("model", 1)
		cp(config.init.model, "model.py")
		if self.plugins:
			jscc = os.path.join(config.js.path, "core", "config.js")
			log("Plugins Specified - building %s"%(jscc,), important=True)
			cp("core.config = %s"%(config.plugin.config.json(),), jscc)
			for plugin, mod in self.plugins.items():
				if hasattr(mod.init, "copies"):
					for dname, fnames in mod.init.copies.items():
						for fname in fnames:
							log("%s [%s]"%(fname, plugin), 1)
							cp(read(os.path.join(mod.__ct_mod_path__, dname, fname)),
								os.path.join(dname, fname))

	def generate_symlinks(self):
		log("creating symlinks", 1)
		if self.refresh_symlinks:
			for d in config.init.dirs:
				if not os.path.isdir(d):
					mkdir(d)
		if self.web_backend == "gae":
			sym(self.ctroot, "cantools")
		ctp = os.path.join(self.ctroot, "CT")
		sym(ctp, os.path.join(config.js.path, "CT"))
		sym(ctp, os.path.join("html-production", "CT"))
		sym(os.path.join(self.ctroot, "css", "ct.css"), os.path.join("css", "ct.css"))
		sym(os.path.join(self.ctroot, "admin"), "_")
		sym(os.path.join(self.ctroot, "admin.py"), "admin.py")
		sym(os.path.join(self.ctroot, "_db.py"), "_db.py")
		sym(os.path.join(self.ctroot, "_pay.py"), "_pay.py")
		for mod in self.plugins.values():
			for dname, fnames in mod.init.syms.items():
				for fname in fnames:
					sym(os.path.join(mod.__ct_mod_path__, dname, fname),
						os.path.join(dname, fname))

	def vcignore(self):
		log("configuring version control path exclusion", 1)
		for plugin, mod in self.plugins.items():
			log("loading rules for plugin: %s"%(plugin,), 2)
			for dname, fnames in mod.init.syms.items():
				for fname in fnames:
					if not config.init.vcignore[dname]:
						config.init.vcignore.update(dname, [])
					config.init.vcignore[dname].append(fname)
		itype = raw_input("would you like to generate exclusion rules for symlinks and dot files (if you select svn, we will add the project to your repository first)? [NO/git/svn] ")
		config.init.vcignore.update(config.js.path, config.init.vcignore.js)
		if itype == "git":
			log("configuring git", 2)
			cfg = config.init.vcignore["."]
			for path in [p for p in config.init.vcignore.keys() if p != "."]:
				for fname in config.init.vcignore[path]:
					cfg.append(os.path.join(path, fname))
			cp("\n".join(cfg), ".gitignore")
		elif itype == "svn":
			log("configuring svn", 2)
			cmd("svn add .")
			for root, files in config.init.vcignore.items():
				cp("\n".join(files), "_tmp")
				cmd("svn propset svn:ignore -F _tmp %s"%(root,))
				rm("_tmp")

def update():
	log("Updating cantools and managed plugins", important=True)
	os.chdir(CTP)
	log("retrieving latest cantools", 1)
	cmd("git pull")
	if os.path.isdir(config.plugin.path):
		dname, dirs, files = os.walk(config.plugin.path).next()
		log("updating %s managed plugins"%(len(dirs),), 1)
		for d in dirs:
			os.chdir(os.path.join(config.plugin.path, d))
			log("retrieving latest %s"%(d,), 2)
			cmd("git pull")
	log("finished updates", 1)

def parse_and_make():
	parser = OptionParser("ctinit [projname] [-r] [--plugins=P1|P2|P3] [--cantools_path=PATH] [--web_backend=BACKEND]")
	parser.add_option("-p", "--plugins", dest="plugins", default="",
		help="which plugins would you like to use in your project?")
	parser.add_option("-c", "--cantools_path", dest="cantools_path", default=CTP,
		help="where is cantools? (default: %s)"%(CTP,))
	parser.add_option("-w", "--web_backend", dest="web_backend", default="dez",
		help="web backend. options: dez, gae. (default: dez)")
	parser.add_option("-r", "--refresh_symlinks", action="store_true",
		dest="refresh_symlinks", default=False, help="add symlinks to project and configure version control path exclusion (if desired)")
	parser.add_option("-u", "--update", action="store_true",
		dest="update", default=False, help="update cantools and all managed plugins")
	options, args = parser.parse_args()
	if options.update:
		update()
	else:
		if options.plugins:
			config.plugin.update("modules", list(set(config.plugin.modules + options.plugins.split("|"))))
		Builder(len(args) and args[0], options.cantools_path,
			options.web_backend, options.refresh_symlinks)
	log("done! goodbye.")

if __name__ == "__main__":
	parse_and_make()<commit_msg>ctinit: switched from using jsconfig attribute on plugin init module to reading more natural js/config.js contents<commit_after>"""
### Usage: ctinit [projname] [-r] [--plugins=P1|P2|P3] [--cantools_path=PATH] [--web_backend=BACKEND]

### Options:
    -h, --help            show this help message and exit
    -p PLUGINS, --plugins=PLUGINS
                          which plugins would you like to use in your project?
    -c CANTOOLS_PATH, --cantools_path=CANTOOLS_PATH
                          where is cantools? (default: /guessed/path/from/__file__)
    -w WEB_BACKEND, --web_backend=WEB_BACKEND
                          web backend. options: dez, gae. (default: dez)
    -r, --refresh_symlinks
                          add symlinks to project and configure version control
                          path exclusion (if desired)
    -u, --update          update cantools and all managed plugins

NB: it may be necessary to specify --cantools_path. Normally, this is derived from
the __file__ property (the location of the ctinit script, init.py). However, if the
package lives in your Python dist-packages (as with 'easy_install', as well as
'setup.py install'), it does not contain the client-side files necessary for an
end-to-end web application, and these files therefore cannot be symlinked into your
new project. In these cases, indicate --cantools_path (the path to the cloned cantools
repository on your computer), and everything should work fine.

Generally speaking, one should clone the cantools github repository, 'setup.py install'
it (for the 'ct' commands), and then run 'setup.py develop', which will point 'cantools'
at your cloned cantools repo and keep the package up to date as you periodically 'git pull'
the latest version. Similarly, plugins should be kept in 'develop' mode, as they also will
generally have non-python files of consequence.

In most cases, the developer won't have to pay much attention to this stuff, because
initializing or refreshing a project will automatically install any necessary plugins
that aren't already present. Similarly, the --update flag pulls down the latest versions
of cantools and all managed plugins. Thus, plugins are dealt with under the hood without
any need for the developer to know or do anything beyond 'ctinit -r'.
"""

import os, sys
from optparse import OptionParser
from cantools import config
from cantools.util import log, error, cp, sym, mkdir, rm, cmd, read

CTP = __file__.rsplit(os.path.sep, 2)[0]

class Builder(object):
	def __init__(self, pname=None, cantools_path=CTP, web_backend="dez", refresh_symlinks=False):
		if not pname and not refresh_symlinks:
			pname = raw_input("project name? ")
		log("Initializing %s Project: %s"%(web_backend, pname or "(refresh)"))
		self.pname = pname
		self.ctroot = cantools_path
		if not os.path.exists(self.ctroot):
			error("failed to establish cantools root",
				"We tried: %s"%(self.ctroot,),
				"This directory does not contain cantools.",
				"You can download cantools at https://github.com/bubbleboy14/cantools",
				"Please pass the path to your local copy of cantools via the -c flag."
			)
		self.web_backend = web_backend
		self.refresh_symlinks = refresh_symlinks
		self.plugins = {}
		self.install_plugins()
		if not refresh_symlinks:
			self.build_dirs()
			self.make_files()
		self.vcignore()
		self.generate_symlinks()

	def _install(self, plug):
		log("Building Package: %s"%(plug,), important=True)
		curdir = os.getcwd()
		if not os.path.isdir(config.plugin.path):
			mkdir(config.plugin.path)
		os.chdir(config.plugin.path)
		log("cloning repository", important=True)
		cmd("git clone https://github.com/%s/%s.git"%(config.plugin.base, plug))
		os.chdir(plug)
		log("installing plugin", important=True)
		cmd("sudo python setup.py install")
		cmd("sudo python setup.py develop")
		os.chdir("%s/.."%(self.ctroot,))
		log("restoring cantools develop status", important=True)
		cmd("sudo python setup.py develop")
		os.chdir(curdir)
		sys.path.insert(0, os.path.join(config.plugin.path, plug))
		self._getplug(plug)

	def _getplug(self, plugin):
		log("Installing Plugin: %s"%(plugin,), important=True)
		mod = self.plugins[plugin] = __import__(plugin)
		mod.__ct_mod_path__ = mod.__file__.rsplit(os.path.sep, 1)[0]
		init = mod.init
		jscc = os.path.join(mod.__ct_mod_path__, "js", "config.js")
		if os.path.isfile(jscc):
			log("adding custom config entries to core.config (js)", 3)
			config.plugin.config.update(plugin, read(jscc, isjson=True))
		if hasattr(init, "model"):
			log("adding %s imports to model"%(len(init.model),), 3)
			config.init.update("model",
				"%s\r\n%s"%(config.init.model,
					"\r\n".join(["from %s import %s"%(m,
						", ".join(k)) for (m, k) in init.model.items()])))
		if hasattr(init, "routes"):
			log("adding %s routes to app.yaml"%(len(init.routes),), 3)
			config.init.yaml.update("core",
				"%s\r\n\r\n%s"%(config.init.yaml.core,
					"\r\n\r\n".join(["- url: %s\r\n  %s: %s"%(u,
						s.endswith(".py") and "script" or "static_dir", s) for (u,
						s) in init.routes.items()])))
		if hasattr(init, "requires"):
			log("installing %s ct dependencies"%(len(init.requires),), 3)
			self._getplugs(init.requires)

	def _getplugs(self, plugs):
		for plugin in plugs:
			log("Plugin: %s"%(plugin,), 2)
			try:
				self._getplug(plugin)
			except ImportError:
				log("plugin '%s' not found! attempting install."%(plugin,), important=True)
				self._install(plugin)

	def install_plugins(self):
		pil = len(config.plugin.modules)
		if pil:
			log("Installing %s Plugins"%(pil,), 1)
			self._getplugs(config.plugin.modules)

	def build_dirs(self):
		log("building directories", 1)
		mkdir(self.pname)
		os.chdir(self.pname)
		for d in config.init.dirs:
			mkdir(d)
		if self.plugins:
			jsc = os.path.join(config.js.path, "core")
			log("Plugins Specified - adding %s"%(jsc,), important=True)
			mkdir(jsc)
			for mod in self.plugins.values():
				for d in mod.init.dirs:
					mkdir(d)

	def make_files(self):
		log("generating configuration", 1)
		cp((self.web_backend == "gae") and "%s\r\n%s"%(config.init.yaml.gae,
			config.init.yaml.core)%(self.pname,) or config.init.yaml.core, "app.yaml")
		cfg = config.init.ctcfg%(self.web_backend,)
		if self.plugins:
			cfg = os.linesep.join([cfg, "PLUGIN_MODULES = %s"%("|".join(self.plugins.keys()),)])
		cp(cfg, "ct.cfg")
		log("demo index page", 1)
		cp(config.init.html%(self.pname,), os.path.join("html", "index.html"))
		log("model", 1)
		cp(config.init.model, "model.py")
		if self.plugins:
			jscc = os.path.join(config.js.path, "core", "config.js")
			log("Plugins Specified - building %s"%(jscc,), important=True)
			cp("core.config = %s"%(config.plugin.config.json(),), jscc)
			for plugin, mod in self.plugins.items():
				if hasattr(mod.init, "copies"):
					for dname, fnames in mod.init.copies.items():
						for fname in fnames:
							log("%s [%s]"%(fname, plugin), 1)
							cp(read(os.path.join(mod.__ct_mod_path__, dname, fname)),
								os.path.join(dname, fname))

	def generate_symlinks(self):
		log("creating symlinks", 1)
		if self.refresh_symlinks:
			for d in config.init.dirs:
				if not os.path.isdir(d):
					mkdir(d)
		if self.web_backend == "gae":
			sym(self.ctroot, "cantools")
		ctp = os.path.join(self.ctroot, "CT")
		sym(ctp, os.path.join(config.js.path, "CT"))
		sym(ctp, os.path.join("html-production", "CT"))
		sym(os.path.join(self.ctroot, "css", "ct.css"), os.path.join("css", "ct.css"))
		sym(os.path.join(self.ctroot, "admin"), "_")
		sym(os.path.join(self.ctroot, "admin.py"), "admin.py")
		sym(os.path.join(self.ctroot, "_db.py"), "_db.py")
		sym(os.path.join(self.ctroot, "_pay.py"), "_pay.py")
		for mod in self.plugins.values():
			for dname, fnames in mod.init.syms.items():
				for fname in fnames:
					sym(os.path.join(mod.__ct_mod_path__, dname, fname),
						os.path.join(dname, fname))

	def vcignore(self):
		log("configuring version control path exclusion", 1)
		for plugin, mod in self.plugins.items():
			log("loading rules for plugin: %s"%(plugin,), 2)
			for dname, fnames in mod.init.syms.items():
				for fname in fnames:
					if not config.init.vcignore[dname]:
						config.init.vcignore.update(dname, [])
					config.init.vcignore[dname].append(fname)
		itype = raw_input("would you like to generate exclusion rules for symlinks and dot files (if you select svn, we will add the project to your repository first)? [NO/git/svn] ")
		config.init.vcignore.update(config.js.path, config.init.vcignore.js)
		if itype == "git":
			log("configuring git", 2)
			cfg = config.init.vcignore["."]
			for path in [p for p in config.init.vcignore.keys() if p != "."]:
				for fname in config.init.vcignore[path]:
					cfg.append(os.path.join(path, fname))
			cp("\n".join(cfg), ".gitignore")
		elif itype == "svn":
			log("configuring svn", 2)
			cmd("svn add .")
			for root, files in config.init.vcignore.items():
				cp("\n".join(files), "_tmp")
				cmd("svn propset svn:ignore -F _tmp %s"%(root,))
				rm("_tmp")

def update():
	log("Updating cantools and managed plugins", important=True)
	os.chdir(CTP)
	log("retrieving latest cantools", 1)
	cmd("git pull")
	if os.path.isdir(config.plugin.path):
		dname, dirs, files = os.walk(config.plugin.path).next()
		log("updating %s managed plugins"%(len(dirs),), 1)
		for d in dirs:
			os.chdir(os.path.join(config.plugin.path, d))
			log("retrieving latest %s"%(d,), 2)
			cmd("git pull")
	log("finished updates", 1)

def parse_and_make():
	parser = OptionParser("ctinit [projname] [-r] [--plugins=P1|P2|P3] [--cantools_path=PATH] [--web_backend=BACKEND]")
	parser.add_option("-p", "--plugins", dest="plugins", default="",
		help="which plugins would you like to use in your project?")
	parser.add_option("-c", "--cantools_path", dest="cantools_path", default=CTP,
		help="where is cantools? (default: %s)"%(CTP,))
	parser.add_option("-w", "--web_backend", dest="web_backend", default="dez",
		help="web backend. options: dez, gae. (default: dez)")
	parser.add_option("-r", "--refresh_symlinks", action="store_true",
		dest="refresh_symlinks", default=False, help="add symlinks to project and configure version control path exclusion (if desired)")
	parser.add_option("-u", "--update", action="store_true",
		dest="update", default=False, help="update cantools and all managed plugins")
	options, args = parser.parse_args()
	if options.update:
		update()
	else:
		if options.plugins:
			config.plugin.update("modules", list(set(config.plugin.modules + options.plugins.split("|"))))
		Builder(len(args) and args[0], options.cantools_path,
			options.web_backend, options.refresh_symlinks)
	log("done! goodbye.")

if __name__ == "__main__":
	parse_and_make()<|endoftext|>


<commit_before>#  Copyright 2008-2009 Nokia Siemens Networks Oyj
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import os

from robot import utils
from robot.errors import DataError
from robot.common import BaseTestSuite, BaseTestCase
from robot.output import LOGGER

from rawdata import RawData, READERS
from metadata import TestCaseFileMetadata, TestSuiteInitFileMetadata, TestCaseMetadata
from keywords import KeywordList
from userkeyword import UserHandlerList

def TestSuiteData(datasources, suitenames=[]):
    datasources = [ utils.normpath(path) for path in datasources ]
    if not datasources:
        raise DataError("No data sources given.")
    elif len(datasources) > 1:
        return MultiSourceSuite(datasources, suitenames)
    elif os.path.isdir(datasources[0]):
        return DirectorySuite(datasources[0], suitenames)
    else:
        return FileSuite(datasources[0])

class _BaseSuite(BaseTestSuite):

    def __init__(self, rawdata, parent=None):
        name, source = self._get_name_and_source(rawdata.source)
        BaseTestSuite.__init__(self, name, source, parent)
        self._metadata = self._get_metadata(rawdata)
        self.doc = self._metadata['Documentation']
        self.suite_setup = self._metadata['SuiteSetup']
        self.suite_teardown = self._metadata['SuiteTeardown']
        self.test_setup = self._metadata['TestSetup']
        self.test_teardown = self._metadata['TestTeardown']
        self.force_tags = self._metadata['ForceTags']
        self.metadata = self._metadata.user_metadata
        self.imports = self._metadata.imports
        self.variables = rawdata.variables
        self.user_keywords = UserHandlerList(rawdata.keywords)

    def _get_name_and_source(self, path):
        source = self._get_source(path)
        return self._get_name(source), source

    def _get_name(self, source):
        return utils.printable_name_from_path(source)

    def _create_subsuites(self, paths, suitenames, error):
        for path in paths:
            try:
                if os.path.isdir(path):
                    DirectorySuite(path, suitenames, parent=self)
                else:
                    FileSuite(path, parent=self)
            except DataError:
                LOGGER.info("Parsing data source '%s' failed: %s"
                            % (path, utils.get_error_message()))
        # The latter check is to get a more informative exception in
        # suite.filter_by_names later if --suite option was used.
        if self.get_test_count() == 0 and len(suitenames) == 0:
            if self.parent is not None:
                self.parent.suites.pop()
            raise DataError(error)

class FileSuite(_BaseSuite):

    def __init__(self, path, parent=None):
        LOGGER.info("Parsing test case file '%s'" % path)
        rawdata = self._get_rawdata(path)
        _BaseSuite.__init__(self, rawdata, parent)
        self._create_testcases(rawdata)
        self.default_tags = self._metadata['DefaultTags']
        self.test_timeout = self._metadata['TestTimeout']

    def _get_metadata(self, rawdata):
        return TestCaseFileMetadata(rawdata)

    def _get_source(self, path):
        return path

    def _get_rawdata(self, path):
        rawdata = RawData(path)
        if rawdata.get_type() == rawdata.TESTCASE:
            return rawdata
        raise DataError("Test case file '%s' contains no test cases."  % path)

    def _create_testcases(self, rawdata):
        for rawtest in rawdata.testcases:
            try:
                TestCase(rawtest, self)
            except:
                rawtest.report_invalid_syntax()

class DirectorySuite(_BaseSuite):

    _ignored_prefixes = ['_', '.']
    _ignored_dirs = ['CVS']

    def __init__(self, path, suitenames, parent=None):
        LOGGER.info("Parsing test suite directory '%s'" % path)
        # If we are included also all our children are
        if self._is_in_incl_suites(os.path.basename(os.path.normpath(path)),
                                   suitenames):
            suitenames = []
        subitems, self.initfile = self._get_suite_items(path, suitenames)
        rawdata = self._get_rawdata(path)
        _BaseSuite.__init__(self, rawdata, parent)
        error = "Test suite directory '%s' contains no test cases." % path
        self._create_subsuites(subitems, suitenames, error)
        self.default_tags = None
        self.test_timeout = None

    def _get_metadata(self, rawdata):
        return TestSuiteInitFileMetadata(rawdata)

    def _get_source(self, path):
        # 'path' points either to directory or __init__ file inside it
        return utils.get_directory(path)

    def _get_suite_items(self, dirpath, suitenames):
        names = self._list_dir(dirpath)
        files = []
        initfile = None
        for name in names:
            path = os.path.join(dirpath, name)
            if self._is_suite_init_file(name, path):
                if initfile is None:
                    initfile = path
                else:
                    LOGGER.error("Ignoring second test suite init file '%s'" % path)
            elif self._is_ignored(name, path, suitenames):
                LOGGER.info("Ignoring file or directory '%s'" % name)
            else:
                files.append(path)
        return files, initfile

    def _list_dir(self, path):
        # Want to make sure path is Unicode because then os.listdir also
        # returns entries as Unicode...
        names = os.listdir(utils.unic(path))
        # ... except on Jython: http://bugs.jython.org/issue1593
        if utils.is_jython:
            from java.lang import String
            names = [ utils.unic(String(n)) for n in names ]
        return sorted(names, key=unicode.lower)

    def _get_rawdata(self, path):
        if self.initfile is None:
            LOGGER.info("No test suite directory init file")
            return RawData(path)
        LOGGER.info("Parsing test suite directory init file '%s'" % self.initfile)
        rawdata = RawData(self.initfile)
        if rawdata.get_type() in [rawdata.INITFILE, rawdata.EMPTY]:
            return rawdata
        LOGGER.error("Test suite directory initialization file '%s' "
                     "contains test cases and is ignored." % self.initfile)
        return RawData(path)

    def _is_ignored(self, name, path, incl_suites):
        if name[0] in self._ignored_prefixes:
            return True
        if os.path.isdir(path):
            return name in self._ignored_dirs
        root, ext = os.path.splitext(name.lower())
        if not READERS.has_key(ext):
            return True
        return not self._is_in_incl_suites(root, incl_suites)

    def _is_in_incl_suites(self, name, incl_suites):
        if incl_suites == []:
            return True
        # Match only to the last part of name given like '--suite parent.child'
        incl_suites = [ incl.split('.')[-1] for incl in incl_suites ]
        name = name.split('__', 1)[-1]  # Strip possible prefix
        return utils.matches_any(name, incl_suites, ignore=['_'])

    def _is_suite_init_file(self, name, path):
        if not os.path.isfile(path):
            return False
        root, ext = os.path.splitext(name.lower())
        return root == '__init__' and READERS.has_key(ext)

class MultiSourceSuite(_BaseSuite):

    def __init__(self, paths, suitenames):
        LOGGER.info("Parsing multiple data sources %s" % utils.seq2str(paths))
        _BaseSuite.__init__(self, RawData(None))
        error = 'Data sources %s contain no test cases.' % (utils.seq2str(paths))
        self._create_subsuites(paths, suitenames, error)

    def _get_metadata(self, rawdata):
        return TestCaseFileMetadata(rawdata)

    def _get_name_and_source(self, path):
        return '', None

class TestCase(BaseTestCase):

    def __init__(self, rawdata, parent):
        BaseTestCase.__init__(self, utils.printable_name(rawdata.name), parent)
        metadata = TestCaseMetadata(rawdata.metadata)
        self.doc = metadata['Documentation']
        self.tags = metadata['Tags']
        self.setup = metadata['Setup']
        self.teardown = metadata['Teardown']
        self.timeout = metadata['Timeout']
        self.keywords = KeywordList(rawdata.keywords)
<commit_msg>Fixed multisource suite<commit_after>#  Copyright 2008-2009 Nokia Siemens Networks Oyj
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import os

from robot import utils
from robot.errors import DataError
from robot.common import BaseTestSuite, BaseTestCase
from robot.output import LOGGER

from rawdata import RawData, READERS
from metadata import TestCaseFileMetadata, TestSuiteInitFileMetadata, TestCaseMetadata
from keywords import KeywordList
from userkeyword import UserHandlerList

def TestSuiteData(datasources, suitenames=[]):
    datasources = [ utils.normpath(path) for path in datasources ]
    if not datasources:
        raise DataError("No data sources given.")
    elif len(datasources) > 1:
        return MultiSourceSuite(datasources, suitenames)
    elif os.path.isdir(datasources[0]):
        return DirectorySuite(datasources[0], suitenames)
    else:
        return FileSuite(datasources[0])

class _BaseSuite(BaseTestSuite):

    def __init__(self, rawdata, parent=None):
        name, source = self._get_name_and_source(rawdata.source)
        BaseTestSuite.__init__(self, name, source, parent)
        metadata = self._get_metadata(rawdata)
        self.doc = metadata['Documentation']
        self.suite_setup = metadata['SuiteSetup']
        self.suite_teardown = metadata['SuiteTeardown']
        self.test_setup = metadata['TestSetup']
        self.test_teardown = metadata['TestTeardown']
        self.force_tags = metadata['ForceTags']
        self.default_tags = self._get_meta_or_none(metadata, 'DefaultTags')
        self.test_timeout = self._get_meta_or_none(metadata, 'TestTimeout')
        self.metadata = metadata.user_metadata
        self.imports = metadata.imports
        self.variables = rawdata.variables
        self.user_keywords = UserHandlerList(rawdata.keywords)

    def _get_meta_or_none(self, metadata, name):
        try:
            return metadata[name]
        except KeyError:
            return None

    def _get_name_and_source(self, path):
        source = self._get_source(path)
        return self._get_name(source), source

    def _get_name(self, source):
        return utils.printable_name_from_path(source)

    def _create_subsuites(self, paths, suitenames, error):
        for path in paths:
            try:
                if os.path.isdir(path):
                    DirectorySuite(path, suitenames, parent=self)
                else:
                    FileSuite(path, parent=self)
            except DataError:
                LOGGER.info("Parsing data source '%s' failed: %s"
                            % (path, utils.get_error_message()))
        # The latter check is to get a more informative exception in
        # suite.filter_by_names later if --suite option was used.
        if self.get_test_count() == 0 and len(suitenames) == 0:
            if self.parent is not None:
                self.parent.suites.pop()
            raise DataError(error)

class FileSuite(_BaseSuite):

    def __init__(self, path, parent=None):
        LOGGER.info("Parsing test case file '%s'" % path)
        rawdata = self._get_rawdata(path)
        _BaseSuite.__init__(self, rawdata, parent)
        self._create_testcases(rawdata)

    def _get_metadata(self, rawdata):
        return TestCaseFileMetadata(rawdata)

    def _get_source(self, path):
        return path

    def _get_rawdata(self, path):
        rawdata = RawData(path)
        if rawdata.get_type() == rawdata.TESTCASE:
            return rawdata
        raise DataError("Test case file '%s' contains no test cases."  % path)

    def _create_testcases(self, rawdata):
        for rawtest in rawdata.testcases:
            try:
                TestCase(rawtest, self)
            except:
                rawtest.report_invalid_syntax()

class DirectorySuite(_BaseSuite):

    _ignored_prefixes = ['_', '.']
    _ignored_dirs = ['CVS']

    def __init__(self, path, suitenames, parent=None):
        LOGGER.info("Parsing test suite directory '%s'" % path)
        # If we are included also all our children are
        if self._is_in_incl_suites(os.path.basename(os.path.normpath(path)),
                                   suitenames):
            suitenames = []
        subitems, self.initfile = self._get_suite_items(path, suitenames)
        rawdata = self._get_rawdata(path)
        _BaseSuite.__init__(self, rawdata, parent)
        error = "Test suite directory '%s' contains no test cases." % path
        self._create_subsuites(subitems, suitenames, error)

    def _get_metadata(self, rawdata):
        return TestSuiteInitFileMetadata(rawdata)

    def _get_source(self, path):
        # 'path' points either to directory or __init__ file inside it
        return utils.get_directory(path)

    def _get_suite_items(self, dirpath, suitenames):
        names = self._list_dir(dirpath)
        files = []
        initfile = None
        for name in names:
            path = os.path.join(dirpath, name)
            if self._is_suite_init_file(name, path):
                if initfile is None:
                    initfile = path
                else:
                    LOGGER.error("Ignoring second test suite init file '%s'" % path)
            elif self._is_ignored(name, path, suitenames):
                LOGGER.info("Ignoring file or directory '%s'" % name)
            else:
                files.append(path)
        return files, initfile

    def _list_dir(self, path):
        # Want to make sure path is Unicode because then os.listdir also
        # returns entries as Unicode...
        names = os.listdir(utils.unic(path))
        # ... except on Jython: http://bugs.jython.org/issue1593
        if utils.is_jython:
            from java.lang import String
            names = [ utils.unic(String(n)) for n in names ]
        return sorted(names, key=unicode.lower)

    def _get_rawdata(self, path):
        if self.initfile is None:
            LOGGER.info("No test suite directory init file")
            return RawData(path)
        LOGGER.info("Parsing test suite directory init file '%s'" % self.initfile)
        rawdata = RawData(self.initfile)
        if rawdata.get_type() in [rawdata.INITFILE, rawdata.EMPTY]:
            return rawdata
        LOGGER.error("Test suite directory initialization file '%s' "
                     "contains test cases and is ignored." % self.initfile)
        return RawData(path)

    def _is_ignored(self, name, path, incl_suites):
        if name[0] in self._ignored_prefixes:
            return True
        if os.path.isdir(path):
            return name in self._ignored_dirs
        root, ext = os.path.splitext(name.lower())
        if not READERS.has_key(ext):
            return True
        return not self._is_in_incl_suites(root, incl_suites)

    def _is_in_incl_suites(self, name, incl_suites):
        if incl_suites == []:
            return True
        # Match only to the last part of name given like '--suite parent.child'
        incl_suites = [ incl.split('.')[-1] for incl in incl_suites ]
        name = name.split('__', 1)[-1]  # Strip possible prefix
        return utils.matches_any(name, incl_suites, ignore=['_'])

    def _is_suite_init_file(self, name, path):
        if not os.path.isfile(path):
            return False
        root, ext = os.path.splitext(name.lower())
        return root == '__init__' and READERS.has_key(ext)

class MultiSourceSuite(_BaseSuite):

    def __init__(self, paths, suitenames):
        LOGGER.info("Parsing multiple data sources %s" % utils.seq2str(paths))
        _BaseSuite.__init__(self, RawData(None))
        error = 'Data sources %s contain no test cases.' % (utils.seq2str(paths))
        self._create_subsuites(paths, suitenames, error)

    def _get_metadata(self, rawdata):
        return TestCaseFileMetadata(rawdata)

    def _get_name_and_source(self, path):
        return '', None

class TestCase(BaseTestCase):

    def __init__(self, rawdata, parent):
        BaseTestCase.__init__(self, utils.printable_name(rawdata.name), parent)
        metadata = TestCaseMetadata(rawdata.metadata)
        self.doc = metadata['Documentation']
        self.tags = metadata['Tags']
        self.setup = metadata['Setup']
        self.teardown = metadata['Teardown']
        self.timeout = metadata['Timeout']
        self.keywords = KeywordList(rawdata.keywords)
<|endoftext|>


<commit_before>"""
### Usage: ctinit [projname] [-ru] [--plugins=P1|P2|P3] [--cantools_path=PATH] [--web_backend=BACKEND]

### Options:
    -h, --help            show this help message and exit
    -p PLUGINS, --plugins=PLUGINS
                          which plugins would you like to use in your project?
    -c CANTOOLS_PATH, --cantools_path=CANTOOLS_PATH
                          where is cantools? (default: /guessed/path/from/__file__)
    -w WEB_BACKEND, --web_backend=WEB_BACKEND
                          web backend. options: dez, gae. (default: dez)
    -r, --refresh_symlinks
                          add symlinks to project and configure version control
                          path exclusion (if desired)
    -u, --update          update cantools and all managed plugins
    -a, --admin           compile admin pages [ctdev only]

NB: it may be necessary to specify --cantools_path. Normally, this is derived from
the __file__ property (the location of the ctinit script, init.py). However, if the
package lives in your Python dist-packages (as with 'easy_install', as well as
'setup.py install'), it does not contain the client-side files necessary for an
end-to-end web application, and these files therefore cannot be symlinked into your
new project. In these cases, indicate --cantools_path (the path to the cloned cantools
repository on your computer), and everything should work fine.

Generally speaking, one should clone the cantools github repository, 'setup.py install'
it (for the 'ct' commands), and then run 'setup.py develop', which will point 'cantools'
at your cloned cantools repo and keep the package up to date as you periodically 'git pull'
the latest version. Similarly, plugins should be kept in 'develop' mode, as they also will
generally have non-python files of consequence.

In most cases, the developer won't have to pay much attention to this stuff, because
initializing or refreshing a project will automatically install any necessary plugins
that aren't already present. Similarly, the --update flag pulls down the latest versions
of cantools and all managed plugins. Thus, plugins are dealt with under the hood without
any need for the developer to know or do anything beyond 'ctinit -r'.
"""

import os, sys
from optparse import OptionParser
from cantools import config, include_plugin, mods_and_repos
from cantools.util import log, error, cp, sym, mkdir, rm, cmd, read
from builder import build_all

CTP = __file__.rsplit(os.path.sep, 2)[0]

class Builder(object):
	def __init__(self, pname=None, cantools_path=CTP, web_backend="dez", refresh_symlinks=False):
		if not pname and not refresh_symlinks:
			pname = raw_input("project name? ")
		log("Initializing %s Project: %s"%(web_backend, pname or "(refresh)"))
		self.pname = pname
		self.ctroot = cantools_path
		if not os.path.exists(self.ctroot):
			error("failed to establish cantools root",
				"We tried: %s"%(self.ctroot,),
				"This directory does not contain cantools.",
				"You can download cantools at https://github.com/bubbleboy14/cantools",
				"Please pass the path to your local copy of cantools via the -c flag."
			)
		self.web_backend = web_backend
		self.refresh_symlinks = refresh_symlinks
		self.plugins = {}
		self.install_plugins()
		if not refresh_symlinks:
			self.build_dirs()
			self.make_files()
		self.vcignore()
		self.generate_symlinks()

	def _install(self, repo):
		log("Building Package: %s"%(repo,), important=True)
		curdir = os.getcwd()
		if not os.path.isdir(config.plugin.path):
			mkdir(config.plugin.path)
		os.chdir(config.plugin.path)
		log("cloning repository", important=True)
		plug = repo.split("/")[1]
		cmd("git clone https://github.com/%s.git"%(repo,))
		os.chdir(plug)
		log("installing plugin", important=True)
		cmd("sudo python setup.py install")
		cmd("sudo python setup.py develop")
		os.chdir("%s/.."%(self.ctroot,))
		log("restoring cantools develop status", important=True)
		cmd("sudo python setup.py develop")
		os.chdir(curdir)
		sys.path.insert(0, os.path.join(config.plugin.path, plug))
		self._getplug(plug)

	def _update(self, cfg, prop, lines):
		cfg.update(prop, "%s\r\n%s"%(cfg[prop], "\r\n".join(lines)))

	def _getplug(self, plugin):
		log("Installing Plugin: %s"%(plugin,), important=True)
		mod = self.plugins[plugin] = __import__(plugin)
		mod.__ct_mod_path__ = mod.__file__.rsplit(os.path.sep, 1)[0]
		init = mod.init
		jscc = os.path.join(mod.__ct_mod_path__, "js", "config.js")
		if os.path.isfile(jscc):
			log("adding custom config entries to core.config (js)", 3)
			config.init.config.update(plugin, read(jscc, isjson=True))
		if hasattr(init, "util"):
			log("adding post instructions to core.util (js)", 3)
			self._update(config.init.util, "post", [init.util])
		if hasattr(init, "model"):
			log("adding %s imports to model"%(len(init.model),), 3)
			self._update(config.init, "model", ["from %s import %s"%(m,
				", ".join(k)) for (m, k) in init.model.items()])
		if hasattr(init, "routes"):
			log("adding %s routes to app.yaml"%(len(init.routes),), 3)
			self._update(config.init.yaml, "core", ["- url: %s\r\n  %s: %s"%(u,
				s.endswith(".py") and "script" or "static_dir", s) for (u,
				s) in init.routes.items()])
		if hasattr(init, "requires"):
			log("installing %s ct dependencies"%(len(init.requires),), 3)
			self._getplugs(*mods_and_repos(init.requires))

	def _getplugs(self, plugs, repos=None):
		for i in range(len(plugs)):
			plugin = plugs[i]
			log("Plugin: %s"%(plugin,), 2)
			try:
				self._getplug(plugin)
			except ImportError:
				log("plugin '%s' not found! attempting install."%(plugin,), important=True)
				self._install((repos or config.plugin.repos)[i])

	def install_plugins(self):
		pil = len(config.plugin.modules)
		if pil:
			log("Installing %s Plugins"%(pil,), 1)
			self._getplugs(config.plugin.modules)

	def build_dirs(self):
		log("building directories", 1)
		mkdir(self.pname)
		os.chdir(self.pname)
		for d in config.init.dirs:
			mkdir(d)
		jsc = os.path.join(config.js.path, "core")
		mkdir(jsc)
		if self.plugins:
			log("Building Directories for %s Plugins"%(len(self.plugins.keys()),), important=True)
			for mod in self.plugins.values():
				if hasattr(mod.init, "dirs"):
					for d in mod.init.dirs:
						mkdir(d)

	def make_files(self):
		log("generating configuration", 1)
		cp((self.web_backend == "gae") and "%s\r\n%s"%(config.init.yaml.gae,
			config.init.yaml.core)%(self.pname,) or config.init.yaml.core, "app.yaml")
		cfg = config.init.ctcfg%(self.web_backend,)
		if self.plugins:
			cfg = os.linesep.join([cfg, "PLUGIN_MODULES = %s"%("|".join(map(lambda r : r.strip("%s/"%(config.plugin.base,)), config.plugin.repos)),)])
		cp(cfg, "ct.cfg")
		log("demo index page", 1)
		cp(config.init.html%(self.pname,), os.path.join("html", "index.html"))
		log("model", 1)
		cp(config.init.model, "model.py")
		jsc = os.path.join(config.js.path, "core.js")
		jscc = os.path.join(config.js.path, "core", "config.js")
		jscu = os.path.join(config.js.path, "core", "util.js")
		log("Building core js files: %s, %s, %s"%(jsc, jscc, jscu), important=True)
		cp(os.linesep.join(config.init.core), jsc)
		cp("core.config = %s;"%(config.init.config.json(),), jscc)
		cp(config.init.util.template%(config.init.util.main.json(), config.init.util.post), jscu)
		for plugin, mod in self.plugins.items():
			if hasattr(mod.init, "copies"):
				for dname, fnames in mod.init.copies.items():
					dp = os.path.join(mod.__ct_mod_path__, dname)
					if fnames == "*":
						log("copying contents of %s/%s to %s"%(plugin, dname, dname), 1)
						cmd("cp -r %s %s"%(os.path.join(dp, "*"), dname))
					else:
						for fname in fnames:
							log("%s [%s]"%(fname, plugin), 1)
							cp(read(os.path.join(dp, fname)),
								os.path.join(dname, fname))

	def generate_symlinks(self):
		log("creating symlinks", 1)
		if self.refresh_symlinks:
			for d in config.init.dirs:
				if not os.path.isdir(d):
					mkdir(d)
		if self.web_backend == "gae":
			sym(self.ctroot, "cantools")
		ctp = os.path.join(self.ctroot, "CT")
		sym(ctp, os.path.join(config.js.path, "CT"))
		sym(os.path.join(self.ctroot, "css", "ct.css"), os.path.join("css", "ct.css"))
		sym(os.path.join(self.ctroot, "admin"), "_")
		sym(os.path.join(self.ctroot, "admin.py"), "admin.py")
		sym(os.path.join(self.ctroot, "_db.py"), "_db.py")
		sym(os.path.join(self.ctroot, "_memcache.py"), "_memcache.py")
		sym(os.path.join(self.ctroot, "_pay.py"), "_pay.py")
		for mod in self.plugins.values():
			if hasattr(mod.init, "syms"):
				for dname, fnames in mod.init.syms.items():
					for fname in fnames:
						sym(os.path.join(mod.__ct_mod_path__, dname, fname),
							os.path.join(dname, fname))

	def vcignore(self):
		log("configuring version control path exclusion", 1)
		for plugin, mod in self.plugins.items():
			if hasattr(mod.init, "syms"):
				log("loading rules for plugin: %s"%(plugin,), 2)
				for dname, fnames in mod.init.syms.items():
					for fname in fnames:
						if not config.init.vcignore[dname]:
							config.init.vcignore.update(dname, [])
						config.init.vcignore[dname].append(fname)
			else:
				log("no symlinks - skipping plugin: %s"%(plugin,), 2)
		itype = raw_input("would you like to generate exclusion rules for symlinks and dot files (if you select svn, we will add the project to your repository first)? [NO/git/svn] ")
		config.init.vcignore.update(config.js.path, config.init.vcignore.js)
		if itype == "git":
			log("configuring git", 2)
			cfg = config.init.vcignore["."]
			for path in [p for p in config.init.vcignore.keys() if p != "."]:
				for fname in config.init.vcignore[path]:
					cfg.append(os.path.join(path, fname))
			cp("\n".join(cfg), ".gitignore")
		elif itype == "svn":
			log("configuring svn", 2)
			cmd("svn add .")
			for root, files in config.init.vcignore.items():
				cp("\n".join(files), "_tmp")
				cmd("svn propset svn:ignore -F _tmp %s"%(root,))
				rm("_tmp")

def update():
	log("Updating cantools and managed plugins", important=True)
	os.chdir(CTP)
	log("retrieving latest cantools", 1)
	cmd("git pull")
	if os.path.isdir(config.plugin.path):
		dname, dirs, files = os.walk(config.plugin.path).next()
		log("updating %s managed plugins"%(len(dirs),), 1)
		for d in dirs:
			os.chdir(os.path.join(config.plugin.path, d))
			log("retrieving latest %s"%(d,), 2)
			cmd("git pull")
	log("finished updates", 1)
	if raw_input("update cantools dependencies? [N/y] ").lower().startswith("y"):
		os.chdir("%s/.."%(CTP,))
		log("updating dependencies", important=True)
		cmd("sudo python setup.py install")
		log("restoring cantools develop status", important=True)
		cmd("sudo python setup.py develop")
	log("goodbye")

def admin():
	log("compiling admin pages -- thanks for developing!!", important=True)
	os.chdir(os.path.join(CTP, "admin"))
	build_all("admin", CTP)
	log("finished compilation")

def parse_and_make():
	parser = OptionParser("ctinit [projname] [-ru] [--plugins=P1|P2|P3] [--cantools_path=PATH] [--web_backend=BACKEND]")
	parser.add_option("-p", "--plugins", dest="plugins", default="",
		help="which plugins would you like to use in your project?")
	parser.add_option("-c", "--cantools_path", dest="cantools_path", default=CTP,
		help="where is cantools? (default: %s)"%(CTP,))
	parser.add_option("-w", "--web_backend", dest="web_backend", default="dez",
		help="web backend. options: dez, gae. (default: dez)")
	parser.add_option("-r", "--refresh_symlinks", action="store_true",
		dest="refresh_symlinks", default=False, help="add symlinks to project and configure version control path exclusion (if desired)")
	parser.add_option("-u", "--update", action="store_true",
		dest="update", default=False, help="update cantools and all managed plugins")
	parser.add_option("-a", "--admin", action="store_true",
		dest="admin", default=False, help="compile admin pages [ctdev only]")
	options, args = parser.parse_args()
	if options.update:
		update()
	elif options.admin:
		admin()
	else:
		if options.plugins:
			for p in options.plugins.split("|"):
				include_plugin(p)
		Builder(len(args) and args[0], options.cantools_path,
			options.web_backend, options.refresh_symlinks)
	log("done! goodbye.")

if __name__ == "__main__":
	parse_and_make()<commit_msg>ctinit Builder.make_files(): fixed default repo stripping<commit_after>"""
### Usage: ctinit [projname] [-ru] [--plugins=P1|P2|P3] [--cantools_path=PATH] [--web_backend=BACKEND]

### Options:
    -h, --help            show this help message and exit
    -p PLUGINS, --plugins=PLUGINS
                          which plugins would you like to use in your project?
    -c CANTOOLS_PATH, --cantools_path=CANTOOLS_PATH
                          where is cantools? (default: /guessed/path/from/__file__)
    -w WEB_BACKEND, --web_backend=WEB_BACKEND
                          web backend. options: dez, gae. (default: dez)
    -r, --refresh_symlinks
                          add symlinks to project and configure version control
                          path exclusion (if desired)
    -u, --update          update cantools and all managed plugins
    -a, --admin           compile admin pages [ctdev only]

NB: it may be necessary to specify --cantools_path. Normally, this is derived from
the __file__ property (the location of the ctinit script, init.py). However, if the
package lives in your Python dist-packages (as with 'easy_install', as well as
'setup.py install'), it does not contain the client-side files necessary for an
end-to-end web application, and these files therefore cannot be symlinked into your
new project. In these cases, indicate --cantools_path (the path to the cloned cantools
repository on your computer), and everything should work fine.

Generally speaking, one should clone the cantools github repository, 'setup.py install'
it (for the 'ct' commands), and then run 'setup.py develop', which will point 'cantools'
at your cloned cantools repo and keep the package up to date as you periodically 'git pull'
the latest version. Similarly, plugins should be kept in 'develop' mode, as they also will
generally have non-python files of consequence.

In most cases, the developer won't have to pay much attention to this stuff, because
initializing or refreshing a project will automatically install any necessary plugins
that aren't already present. Similarly, the --update flag pulls down the latest versions
of cantools and all managed plugins. Thus, plugins are dealt with under the hood without
any need for the developer to know or do anything beyond 'ctinit -r'.
"""

import os, sys
from optparse import OptionParser
from cantools import config, include_plugin, mods_and_repos
from cantools.util import log, error, cp, sym, mkdir, rm, cmd, read
from builder import build_all

CTP = __file__.rsplit(os.path.sep, 2)[0]

class Builder(object):
	def __init__(self, pname=None, cantools_path=CTP, web_backend="dez", refresh_symlinks=False):
		if not pname and not refresh_symlinks:
			pname = raw_input("project name? ")
		log("Initializing %s Project: %s"%(web_backend, pname or "(refresh)"))
		self.pname = pname
		self.ctroot = cantools_path
		if not os.path.exists(self.ctroot):
			error("failed to establish cantools root",
				"We tried: %s"%(self.ctroot,),
				"This directory does not contain cantools.",
				"You can download cantools at https://github.com/bubbleboy14/cantools",
				"Please pass the path to your local copy of cantools via the -c flag."
			)
		self.web_backend = web_backend
		self.refresh_symlinks = refresh_symlinks
		self.plugins = {}
		self.install_plugins()
		if not refresh_symlinks:
			self.build_dirs()
			self.make_files()
		self.vcignore()
		self.generate_symlinks()

	def _install(self, repo):
		log("Building Package: %s"%(repo,), important=True)
		curdir = os.getcwd()
		if not os.path.isdir(config.plugin.path):
			mkdir(config.plugin.path)
		os.chdir(config.plugin.path)
		log("cloning repository", important=True)
		plug = repo.split("/")[1]
		cmd("git clone https://github.com/%s.git"%(repo,))
		os.chdir(plug)
		log("installing plugin", important=True)
		cmd("sudo python setup.py install")
		cmd("sudo python setup.py develop")
		os.chdir("%s/.."%(self.ctroot,))
		log("restoring cantools develop status", important=True)
		cmd("sudo python setup.py develop")
		os.chdir(curdir)
		sys.path.insert(0, os.path.join(config.plugin.path, plug))
		self._getplug(plug)

	def _update(self, cfg, prop, lines):
		cfg.update(prop, "%s\r\n%s"%(cfg[prop], "\r\n".join(lines)))

	def _getplug(self, plugin):
		log("Installing Plugin: %s"%(plugin,), important=True)
		mod = self.plugins[plugin] = __import__(plugin)
		mod.__ct_mod_path__ = mod.__file__.rsplit(os.path.sep, 1)[0]
		init = mod.init
		jscc = os.path.join(mod.__ct_mod_path__, "js", "config.js")
		if os.path.isfile(jscc):
			log("adding custom config entries to core.config (js)", 3)
			config.init.config.update(plugin, read(jscc, isjson=True))
		if hasattr(init, "util"):
			log("adding post instructions to core.util (js)", 3)
			self._update(config.init.util, "post", [init.util])
		if hasattr(init, "model"):
			log("adding %s imports to model"%(len(init.model),), 3)
			self._update(config.init, "model", ["from %s import %s"%(m,
				", ".join(k)) for (m, k) in init.model.items()])
		if hasattr(init, "routes"):
			log("adding %s routes to app.yaml"%(len(init.routes),), 3)
			self._update(config.init.yaml, "core", ["- url: %s\r\n  %s: %s"%(u,
				s.endswith(".py") and "script" or "static_dir", s) for (u,
				s) in init.routes.items()])
		if hasattr(init, "requires"):
			log("installing %s ct dependencies"%(len(init.requires),), 3)
			self._getplugs(*mods_and_repos(init.requires))

	def _getplugs(self, plugs, repos=None):
		for i in range(len(plugs)):
			plugin = plugs[i]
			log("Plugin: %s"%(plugin,), 2)
			try:
				self._getplug(plugin)
			except ImportError:
				log("plugin '%s' not found! attempting install."%(plugin,), important=True)
				self._install((repos or config.plugin.repos)[i])

	def install_plugins(self):
		pil = len(config.plugin.modules)
		if pil:
			log("Installing %s Plugins"%(pil,), 1)
			self._getplugs(config.plugin.modules)

	def build_dirs(self):
		log("building directories", 1)
		mkdir(self.pname)
		os.chdir(self.pname)
		for d in config.init.dirs:
			mkdir(d)
		jsc = os.path.join(config.js.path, "core")
		mkdir(jsc)
		if self.plugins:
			log("Building Directories for %s Plugins"%(len(self.plugins.keys()),), important=True)
			for mod in self.plugins.values():
				if hasattr(mod.init, "dirs"):
					for d in mod.init.dirs:
						mkdir(d)

	def make_files(self):
		log("generating configuration", 1)
		cp((self.web_backend == "gae") and "%s\r\n%s"%(config.init.yaml.gae,
			config.init.yaml.core)%(self.pname,) or config.init.yaml.core, "app.yaml")
		cfg = config.init.ctcfg%(self.web_backend,)
		if self.plugins:
			cfg = os.linesep.join([cfg, "PLUGIN_MODULES = %s"%("|".join(map(lambda r : r.replace("%s/"%(config.plugin.base,), ""), config.plugin.repos)),)])
		cp(cfg, "ct.cfg")
		log("demo index page", 1)
		cp(config.init.html%(self.pname,), os.path.join("html", "index.html"))
		log("model", 1)
		cp(config.init.model, "model.py")
		jsc = os.path.join(config.js.path, "core.js")
		jscc = os.path.join(config.js.path, "core", "config.js")
		jscu = os.path.join(config.js.path, "core", "util.js")
		log("Building core js files: %s, %s, %s"%(jsc, jscc, jscu), important=True)
		cp(os.linesep.join(config.init.core), jsc)
		cp("core.config = %s;"%(config.init.config.json(),), jscc)
		cp(config.init.util.template%(config.init.util.main.json(), config.init.util.post), jscu)
		for plugin, mod in self.plugins.items():
			if hasattr(mod.init, "copies"):
				for dname, fnames in mod.init.copies.items():
					dp = os.path.join(mod.__ct_mod_path__, dname)
					if fnames == "*":
						log("copying contents of %s/%s to %s"%(plugin, dname, dname), 1)
						cmd("cp -r %s %s"%(os.path.join(dp, "*"), dname))
					else:
						for fname in fnames:
							log("%s [%s]"%(fname, plugin), 1)
							cp(read(os.path.join(dp, fname)),
								os.path.join(dname, fname))

	def generate_symlinks(self):
		log("creating symlinks", 1)
		if self.refresh_symlinks:
			for d in config.init.dirs:
				if not os.path.isdir(d):
					mkdir(d)
		if self.web_backend == "gae":
			sym(self.ctroot, "cantools")
		ctp = os.path.join(self.ctroot, "CT")
		sym(ctp, os.path.join(config.js.path, "CT"))
		sym(os.path.join(self.ctroot, "css", "ct.css"), os.path.join("css", "ct.css"))
		sym(os.path.join(self.ctroot, "admin"), "_")
		sym(os.path.join(self.ctroot, "admin.py"), "admin.py")
		sym(os.path.join(self.ctroot, "_db.py"), "_db.py")
		sym(os.path.join(self.ctroot, "_memcache.py"), "_memcache.py")
		sym(os.path.join(self.ctroot, "_pay.py"), "_pay.py")
		for mod in self.plugins.values():
			if hasattr(mod.init, "syms"):
				for dname, fnames in mod.init.syms.items():
					for fname in fnames:
						sym(os.path.join(mod.__ct_mod_path__, dname, fname),
							os.path.join(dname, fname))

	def vcignore(self):
		log("configuring version control path exclusion", 1)
		for plugin, mod in self.plugins.items():
			if hasattr(mod.init, "syms"):
				log("loading rules for plugin: %s"%(plugin,), 2)
				for dname, fnames in mod.init.syms.items():
					for fname in fnames:
						if not config.init.vcignore[dname]:
							config.init.vcignore.update(dname, [])
						config.init.vcignore[dname].append(fname)
			else:
				log("no symlinks - skipping plugin: %s"%(plugin,), 2)
		itype = raw_input("would you like to generate exclusion rules for symlinks and dot files (if you select svn, we will add the project to your repository first)? [NO/git/svn] ")
		config.init.vcignore.update(config.js.path, config.init.vcignore.js)
		if itype == "git":
			log("configuring git", 2)
			cfg = config.init.vcignore["."]
			for path in [p for p in config.init.vcignore.keys() if p != "."]:
				for fname in config.init.vcignore[path]:
					cfg.append(os.path.join(path, fname))
			cp("\n".join(cfg), ".gitignore")
		elif itype == "svn":
			log("configuring svn", 2)
			cmd("svn add .")
			for root, files in config.init.vcignore.items():
				cp("\n".join(files), "_tmp")
				cmd("svn propset svn:ignore -F _tmp %s"%(root,))
				rm("_tmp")

def update():
	log("Updating cantools and managed plugins", important=True)
	os.chdir(CTP)
	log("retrieving latest cantools", 1)
	cmd("git pull")
	if os.path.isdir(config.plugin.path):
		dname, dirs, files = os.walk(config.plugin.path).next()
		log("updating %s managed plugins"%(len(dirs),), 1)
		for d in dirs:
			os.chdir(os.path.join(config.plugin.path, d))
			log("retrieving latest %s"%(d,), 2)
			cmd("git pull")
	log("finished updates", 1)
	if raw_input("update cantools dependencies? [N/y] ").lower().startswith("y"):
		os.chdir("%s/.."%(CTP,))
		log("updating dependencies", important=True)
		cmd("sudo python setup.py install")
		log("restoring cantools develop status", important=True)
		cmd("sudo python setup.py develop")
	log("goodbye")

def admin():
	log("compiling admin pages -- thanks for developing!!", important=True)
	os.chdir(os.path.join(CTP, "admin"))
	build_all("admin", CTP)
	log("finished compilation")

def parse_and_make():
	parser = OptionParser("ctinit [projname] [-ru] [--plugins=P1|P2|P3] [--cantools_path=PATH] [--web_backend=BACKEND]")
	parser.add_option("-p", "--plugins", dest="plugins", default="",
		help="which plugins would you like to use in your project?")
	parser.add_option("-c", "--cantools_path", dest="cantools_path", default=CTP,
		help="where is cantools? (default: %s)"%(CTP,))
	parser.add_option("-w", "--web_backend", dest="web_backend", default="dez",
		help="web backend. options: dez, gae. (default: dez)")
	parser.add_option("-r", "--refresh_symlinks", action="store_true",
		dest="refresh_symlinks", default=False, help="add symlinks to project and configure version control path exclusion (if desired)")
	parser.add_option("-u", "--update", action="store_true",
		dest="update", default=False, help="update cantools and all managed plugins")
	parser.add_option("-a", "--admin", action="store_true",
		dest="admin", default=False, help="compile admin pages [ctdev only]")
	options, args = parser.parse_args()
	if options.update:
		update()
	elif options.admin:
		admin()
	else:
		if options.plugins:
			for p in options.plugins.split("|"):
				include_plugin(p)
		Builder(len(args) and args[0], options.cantools_path,
			options.web_backend, options.refresh_symlinks)
	log("done! goodbye.")

if __name__ == "__main__":
	parse_and_make()<|endoftext|>


<commit_before>#  Copyright 2008-2009 Nokia Siemens Networks Oyj
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import os

from robot import utils
from robot.errors import DataError
from robot.common import BaseTestSuite, BaseTestCase
from robot.output import LOGGER

from rawdata import RawData, READERS
from metadata import TestCaseFileMetadata, TestSuiteInitFileMetadata, TestCaseMetadata
from keywords import KeywordList
from userkeyword import UserHandlerList

def TestSuiteData(datasources, suitenames=[]):
    datasources = [ utils.normpath(path) for path in datasources ]
    if not datasources:
        raise DataError("No data sources given.")
    elif len(datasources) > 1:
        return MultiSourceSuite(datasources, suitenames)
    elif os.path.isdir(datasources[0]):
        return DirectorySuite(datasources[0], suitenames)
    else:
        return FileSuite(datasources[0])

class _BaseSuite(BaseTestSuite):

    def __init__(self, rawdata, parent=None):
        name, source = self._get_name_and_source(rawdata.source)
        BaseTestSuite.__init__(self, name, source, parent)
        metadata = self._get_metadata(rawdata)
        self.doc = metadata['Documentation']
        self.suite_setup = metadata['SuiteSetup']
        self.suite_teardown = metadata['SuiteTeardown']
        self.test_setup = metadata['TestSetup']
        self.test_teardown = metadata['TestTeardown']
        self.default_tags = metadata['DefaultTags']
        self.force_tags = metadata['ForceTags']
        self.test_timeout = metadata['TestTimeout']
        self.metadata = metadata.user_metadata
        self.imports = metadata.imports
        self.variables = rawdata.variables
        self.user_keywords = UserHandlerList(rawdata.keywords)

    def _get_name_and_source(self, path):
        source = self._get_source(path)
        return self._get_name(source), source

    def _get_name(self, source):
        return utils.printable_name_from_path(source)

    def _create_subsuites(self, paths, suitenames, error):
        for path in paths:
            try:
                if os.path.isdir(path):
                    DirectorySuite(path, suitenames, parent=self)
                else:
                    FileSuite(path, parent=self)
            except DataError, err:
                LOGGER.info("Parsing data source '%s' failed: %s" % (path, err))
        # The latter check is to get a more informative exception in
        # suite.filter_by_names later if --suite option was used.
        if self.get_test_count() == 0 and len(suitenames) == 0:
            if self.parent is not None:
                self.parent.suites.pop()
            raise DataError(error)

class FileSuite(_BaseSuite):

    def __init__(self, path, parent=None):
        LOGGER.info("Parsing test case file '%s'" % path)
        rawdata = self._get_rawdata(path)
        _BaseSuite.__init__(self, rawdata, parent)
        self._create_testcases(rawdata)

    def _get_metadata(self, rawdata):
        return TestCaseFileMetadata(rawdata)

    def _get_source(self, path):
        return path

    def _get_rawdata(self, path):
        rawdata = RawData(path)
        if rawdata.get_type() == rawdata.TESTCASE:
            return rawdata
        raise DataError("Test case file '%s' contains no test cases."  % path)

    def _create_testcases(self, rawdata):
        for rawtest in rawdata.testcases:
            try:
                TestCase(rawtest, self)
            except:
                rawtest.report_invalid_syntax()

class DirectorySuite(_BaseSuite):

    _ignored_prefixes = ['_', '.']
    _ignored_dirs = ['CVS']

    def __init__(self, path, suitenames, parent=None):
        LOGGER.info("Parsing test suite directory '%s'" % path)
        # If we are included also all our children are
        if self._is_in_incl_suites(os.path.basename(os.path.normpath(path)),
                                   suitenames):
            suitenames = []
        subitems, self.initfile = self._get_suite_items(path, suitenames)
        rawdata = self._get_rawdata(path)
        _BaseSuite.__init__(self, rawdata, parent)
        error = "Test suite directory '%s' contains no test cases." % path
        self._create_subsuites(subitems, suitenames, error)

    def _get_metadata(self, rawdata):
        return TestSuiteInitFileMetadata(rawdata)

    def _get_source(self, path):
        # 'path' points either to directory or __init__ file inside it
        return utils.get_directory(path)

    def _get_suite_items(self, dirpath, suitenames):
        names = self._list_dir(dirpath)
        files = []
        initfile = None
        for name in names:
            path = os.path.join(dirpath, name)
            if self._is_suite_init_file(name, path):
                if initfile is None:
                    initfile = path
                else:
                    LOGGER.error("Ignoring second test suite init file '%s'" % path)
            elif self._is_ignored(name, path, suitenames):
                LOGGER.info("Ignoring file or directory '%s'" % name)
            else:
                files.append(path)
        return files, initfile

    def _list_dir(self, path):
        names = os.listdir(path)
        if utils.is_jython:
            # http://bugs.jython.org/issue1593
            from java.lang import String
            names = [ utils.unic(String(n)) for n in names ]
        names.sort(lambda x,y: cmp(x.lower(), y.lower()))
        return names

    def _get_rawdata(self, path):
        if self.initfile is None:
            LOGGER.info("No test suite directory init file")
            return RawData(path)
        LOGGER.info("Parsing test suite directory init file '%s'" % self.initfile)
        rawdata = RawData(self.initfile)
        if rawdata.get_type() in [rawdata.INITFILE, rawdata.EMPTY]:
            return rawdata
        LOGGER.error("Test suite directory initialization file '%s' "
                     "contains test cases and is ignored." % self.initfile)
        return RawData(path)

    def _is_ignored(self, name, path, incl_suites):
        if name[0] in self._ignored_prefixes:
            return True
        if os.path.isdir(path):
            return name in self._ignored_dirs
        root, ext = os.path.splitext(name.lower())
        if not READERS.has_key(ext):
            return True
        return not self._is_in_incl_suites(root, incl_suites)

    def _is_in_incl_suites(self, name, incl_suites):
        if incl_suites == []:
            return True
        # Match only to the last part of name given like '--suite parent.child'
        incl_suites = [ incl.split('.')[-1] for incl in incl_suites ]
        name = name.split('__', 1)[-1]  # Strip possible prefix
        return utils.matches_any(name, incl_suites, ignore=['_'])

    def _is_suite_init_file(self, name, path):
        if not os.path.isfile(path):
            return False
        root, ext = os.path.splitext(name.lower())
        return root == '__init__' and READERS.has_key(ext)

class MultiSourceSuite(_BaseSuite):

    def __init__(self, paths, suitenames):
        LOGGER.info("Parsing multiple data sources %s" % utils.seq2str(paths))
        _BaseSuite.__init__(self, RawData(None))
        error = 'Data sources %s contain no test cases.' % (utils.seq2str(paths))
        self._create_subsuites(paths, suitenames, error)

    def _get_metadata(self, rawdata):
        return TestCaseFileMetadata(rawdata)

    def _get_name_and_source(self, path):
        return '', None

class TestCase(BaseTestCase):

    def __init__(self, rawdata, parent):
        BaseTestCase.__init__(self, utils.printable_name(rawdata.name), parent)
        metadata = TestCaseMetadata(rawdata.metadata)
        self.doc = metadata['Documentation']
        self.tags = metadata['Tags']
        self.setup = metadata['Setup']
        self.teardown = metadata['Teardown']
        self.timeout = metadata['Timeout']
        self.keywords = KeywordList(rawdata.keywords)
<commit_msg>can haz nicer sort in 2.5 versions<commit_after>#  Copyright 2008-2009 Nokia Siemens Networks Oyj
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import os

from robot import utils
from robot.errors import DataError
from robot.common import BaseTestSuite, BaseTestCase
from robot.output import LOGGER

from rawdata import RawData, READERS
from metadata import TestCaseFileMetadata, TestSuiteInitFileMetadata, TestCaseMetadata
from keywords import KeywordList
from userkeyword import UserHandlerList

def TestSuiteData(datasources, suitenames=[]):
    datasources = [ utils.normpath(path) for path in datasources ]
    if not datasources:
        raise DataError("No data sources given.")
    elif len(datasources) > 1:
        return MultiSourceSuite(datasources, suitenames)
    elif os.path.isdir(datasources[0]):
        return DirectorySuite(datasources[0], suitenames)
    else:
        return FileSuite(datasources[0])

class _BaseSuite(BaseTestSuite):

    def __init__(self, rawdata, parent=None):
        name, source = self._get_name_and_source(rawdata.source)
        BaseTestSuite.__init__(self, name, source, parent)
        metadata = self._get_metadata(rawdata)
        self.doc = metadata['Documentation']
        self.suite_setup = metadata['SuiteSetup']
        self.suite_teardown = metadata['SuiteTeardown']
        self.test_setup = metadata['TestSetup']
        self.test_teardown = metadata['TestTeardown']
        self.default_tags = metadata['DefaultTags']
        self.force_tags = metadata['ForceTags']
        self.test_timeout = metadata['TestTimeout']
        self.metadata = metadata.user_metadata
        self.imports = metadata.imports
        self.variables = rawdata.variables
        self.user_keywords = UserHandlerList(rawdata.keywords)

    def _get_name_and_source(self, path):
        source = self._get_source(path)
        return self._get_name(source), source

    def _get_name(self, source):
        return utils.printable_name_from_path(source)

    def _create_subsuites(self, paths, suitenames, error):
        for path in paths:
            try:
                if os.path.isdir(path):
                    DirectorySuite(path, suitenames, parent=self)
                else:
                    FileSuite(path, parent=self)
            except DataError, err:
                LOGGER.info("Parsing data source '%s' failed: %s" % (path, err))
        # The latter check is to get a more informative exception in
        # suite.filter_by_names later if --suite option was used.
        if self.get_test_count() == 0 and len(suitenames) == 0:
            if self.parent is not None:
                self.parent.suites.pop()
            raise DataError(error)

class FileSuite(_BaseSuite):

    def __init__(self, path, parent=None):
        LOGGER.info("Parsing test case file '%s'" % path)
        rawdata = self._get_rawdata(path)
        _BaseSuite.__init__(self, rawdata, parent)
        self._create_testcases(rawdata)

    def _get_metadata(self, rawdata):
        return TestCaseFileMetadata(rawdata)

    def _get_source(self, path):
        return path

    def _get_rawdata(self, path):
        rawdata = RawData(path)
        if rawdata.get_type() == rawdata.TESTCASE:
            return rawdata
        raise DataError("Test case file '%s' contains no test cases."  % path)

    def _create_testcases(self, rawdata):
        for rawtest in rawdata.testcases:
            try:
                TestCase(rawtest, self)
            except:
                rawtest.report_invalid_syntax()

class DirectorySuite(_BaseSuite):

    _ignored_prefixes = ['_', '.']
    _ignored_dirs = ['CVS']

    def __init__(self, path, suitenames, parent=None):
        LOGGER.info("Parsing test suite directory '%s'" % path)
        # If we are included also all our children are
        if self._is_in_incl_suites(os.path.basename(os.path.normpath(path)),
                                   suitenames):
            suitenames = []
        subitems, self.initfile = self._get_suite_items(path, suitenames)
        rawdata = self._get_rawdata(path)
        _BaseSuite.__init__(self, rawdata, parent)
        error = "Test suite directory '%s' contains no test cases." % path
        self._create_subsuites(subitems, suitenames, error)

    def _get_metadata(self, rawdata):
        return TestSuiteInitFileMetadata(rawdata)

    def _get_source(self, path):
        # 'path' points either to directory or __init__ file inside it
        return utils.get_directory(path)

    def _get_suite_items(self, dirpath, suitenames):
        names = self._list_dir(dirpath)
        files = []
        initfile = None
        for name in names:
            path = os.path.join(dirpath, name)
            if self._is_suite_init_file(name, path):
                if initfile is None:
                    initfile = path
                else:
                    LOGGER.error("Ignoring second test suite init file '%s'" % path)
            elif self._is_ignored(name, path, suitenames):
                LOGGER.info("Ignoring file or directory '%s'" % name)
            else:
                files.append(path)
        return files, initfile

    def _list_dir(self, path):
        names = os.listdir(path)
        if utils.is_jython:
            # http://bugs.jython.org/issue1593
            from java.lang import String
            names = [ utils.unic(String(n)) for n in names ]
        return sorted(names, key=str.lower)

    def _get_rawdata(self, path):
        if self.initfile is None:
            LOGGER.info("No test suite directory init file")
            return RawData(path)
        LOGGER.info("Parsing test suite directory init file '%s'" % self.initfile)
        rawdata = RawData(self.initfile)
        if rawdata.get_type() in [rawdata.INITFILE, rawdata.EMPTY]:
            return rawdata
        LOGGER.error("Test suite directory initialization file '%s' "
                     "contains test cases and is ignored." % self.initfile)
        return RawData(path)

    def _is_ignored(self, name, path, incl_suites):
        if name[0] in self._ignored_prefixes:
            return True
        if os.path.isdir(path):
            return name in self._ignored_dirs
        root, ext = os.path.splitext(name.lower())
        if not READERS.has_key(ext):
            return True
        return not self._is_in_incl_suites(root, incl_suites)

    def _is_in_incl_suites(self, name, incl_suites):
        if incl_suites == []:
            return True
        # Match only to the last part of name given like '--suite parent.child'
        incl_suites = [ incl.split('.')[-1] for incl in incl_suites ]
        name = name.split('__', 1)[-1]  # Strip possible prefix
        return utils.matches_any(name, incl_suites, ignore=['_'])

    def _is_suite_init_file(self, name, path):
        if not os.path.isfile(path):
            return False
        root, ext = os.path.splitext(name.lower())
        return root == '__init__' and READERS.has_key(ext)

class MultiSourceSuite(_BaseSuite):

    def __init__(self, paths, suitenames):
        LOGGER.info("Parsing multiple data sources %s" % utils.seq2str(paths))
        _BaseSuite.__init__(self, RawData(None))
        error = 'Data sources %s contain no test cases.' % (utils.seq2str(paths))
        self._create_subsuites(paths, suitenames, error)

    def _get_metadata(self, rawdata):
        return TestCaseFileMetadata(rawdata)

    def _get_name_and_source(self, path):
        return '', None

class TestCase(BaseTestCase):

    def __init__(self, rawdata, parent):
        BaseTestCase.__init__(self, utils.printable_name(rawdata.name), parent)
        metadata = TestCaseMetadata(rawdata.metadata)
        self.doc = metadata['Documentation']
        self.tags = metadata['Tags']
        self.setup = metadata['Setup']
        self.teardown = metadata['Teardown']
        self.timeout = metadata['Timeout']
        self.keywords = KeywordList(rawdata.keywords)
<|endoftext|>