<commit_before>import collections
import gocept.cache.method
import zc.sourcefactory.source
import zeit.cms.content.sources
import zope.interface
import zope.security.proxy

class ITeaserBlockLayout(zope.interface.Interface):
    """Layout of a teaser block."""

    id = zope.schema.ASCIILine(title=u'Id used in xml to identify layout')
    title = zope.schema.TextLine(title=u'Human readable title.')
    image_pattern = zope.schema.ASCIILine(
        title=u'A match for the image to use in this layout.')
    columns = zope.schema.Int(
        title=u'Columns',
        min=1,
        max=2,
        default=1)
    areas = zope.schema.Set(
        title=u'Kinds of areas where this layout is allowed')
    default = zope.schema.Bool(
        title=u"True if this is the default for an area")

class BlockLayout(object):

    zope.interface.implements(ITeaserBlockLayout)

    def __init__(self, id, title, image_pattern=None,
                 areas=None, columns=1, default=False, available=None):
        self.id = id
        self.title = title
        self.image_pattern = image_pattern
        self.areas = frozenset(areas)
        self.columns = columns
        self.default_in_areas = default
        self.available_iface = available

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, BlockLayout) and self.id == other.id

    def is_default(self, block):
        area = zeit.content.cp.interfaces.IArea(block)
        return area.kind in self.default_in_areas

class RegionConfig(object):

    def __init__(self, id, title, kind, areas):
        self.id = id
        self.title = title
        self.kind = kind
        self.areas = areas

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, RegionConfig) and self.id == other.id

class AreaConfig(object):

    def __init__(self, id, title, kind):
        self.id = id
        self.title = title
        self.kind = kind

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, AreaConfig) and self.id == other.id

class LayoutSourceBase(object):

    def getTitle(self, context, value):
        return value.title

    def getToken(self, context, value):
        return value.id

    def isAvailable(self, node, context):
        # Avoid circular import
        from zeit.content.cp.interfaces import ICenterPage
        context = ICenterPage(context, None)
        if context is None:
            return True
        return super(LayoutSourceBase, self).isAvailable(node, context)

class TeaserBlockLayoutSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'block-layout-source'
    attribute = 'id'

    class source_class(zc.sourcefactory.source.FactoredContextualSource):

        def find(self, id):
            return self.factory.find(self.context, id)

    def isAvailable(self, value, context):
        # Avoid circular import
        from zeit.content.cp.interfaces import ICenterPage
        context = ICenterPage(context, None)
        if context is None:
            return True
        if value.available_iface is None:
            return False
        return value.available_iface.providedBy(context)

    def getValues(self, context):
        return [x for x in self._values().values()
                if self.isAvailable(x, context)]

    @gocept.cache.method.Memoize(600, ignore_self=True)
    def _values(self):
        tree = self._get_tree()
        result = collections.OrderedDict()
        for node in tree.iterchildren('*'):
            g = node.get
            areas = g('areas')
            areas = areas.split()
            columns = g('columns', 1)
            if columns:
                columns = int(columns)
            iface = node.get('available', 'zope.interface.Interface')
            try:
                iface = zope.dottedname.resolve.resolve(iface)
            except ImportError:
                iface = None
            id = node.get(self.attribute)
            result[id] = BlockLayout(
                id, self._get_title_for(node),
                g('image_pattern'), areas, columns, g('default', ''), iface)
        return result

    def find(self, context, id):
        value = self._values().get(id)
        if (not value or not self.isAvailable(value, context)
            or not self.filterValue(context, value)):
            return None
        return value

    def _get_title_for(self, node):
        return unicode(node.get('title'))

    def filterValue(self, context, value):
        if context is None:
            return True
        area = zeit.content.cp.interfaces.IArea(context)
        return area.kind in value.areas

TEASERBLOCK_LAYOUTS = TeaserBlockLayoutSource()

class RegionConfigSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'region-config-source'

    def getValues(self, context):
        tree = self._get_tree()
        result = []
        for node in tree.iterchildren('*'):
            if not self.isAvailable(node, context):
                continue
            result.append(RegionConfig(
                node.get('id'),
                self._get_title_for(node),
                node.get('kind'),
                [{'kind': x.get('kind')} for x in node.iterchildren('area')]
            ))
        return result

    def _get_title_for(self, node):
        return unicode(node.get('title'))

REGION_CONFIGS = RegionConfigSource()

class AreaConfigSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'area-config-source'

    def getValues(self, context):
        tree = self._get_tree()
        result = []
        for node in tree.iterchildren('*'):
            if not self.isAvailable(node, context):
                continue
            result.append(AreaConfig(
                node.get('id'),
                self._get_title_for(node),
                node.get('kind')))
        return result

    def _get_title_for(self, node):
        return unicode(node.get('title'))

AREA_CONFIGS = AreaConfigSource()

def get_layout(id):
    return TEASERBLOCK_LAYOUTS(None).find(id)
<commit_msg>Move available check to layout object<commit_after>import collections
import gocept.cache.method
import zc.sourcefactory.source
import zeit.cms.content.sources
import zope.interface
import zope.security.proxy

class ITeaserBlockLayout(zope.interface.Interface):
    """Layout of a teaser block."""

    id = zope.schema.ASCIILine(title=u'Id used in xml to identify layout')
    title = zope.schema.TextLine(title=u'Human readable title.')
    image_pattern = zope.schema.ASCIILine(
        title=u'A match for the image to use in this layout.')
    columns = zope.schema.Int(
        title=u'Columns',
        min=1,
        max=2,
        default=1)
    areas = zope.schema.Set(
        title=u'Kinds of areas where this layout is allowed')
    default = zope.schema.Bool(
        title=u"True if this is the default for an area")

class BlockLayout(object):

    zope.interface.implements(ITeaserBlockLayout)

    def __init__(self, id, title, image_pattern=None,
                 areas=None, columns=1, default=False, available=None):
        self.id = id
        self.title = title
        self.image_pattern = image_pattern
        self.areas = frozenset(areas)
        self.columns = columns
        self.default_in_areas = default
        self.available_iface = available

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, BlockLayout) and self.id == other.id

    def is_default(self, block):
        area = zeit.content.cp.interfaces.IArea(block)
        return area.kind in self.default_in_areas

    def is_allowed(self, context):
        # Avoid circular import
        from zeit.content.cp.interfaces import ICenterPage
        cp = ICenterPage(context, None)
        if cp is None:
            return True
        return self.is_allowed_iface(cp)

    def is_allowed_iface(self, cp):
        if self.available_iface is None:
            return False
        return self.available_iface.providedBy(cp)

class RegionConfig(object):

    def __init__(self, id, title, kind, areas):
        self.id = id
        self.title = title
        self.kind = kind
        self.areas = areas

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, RegionConfig) and self.id == other.id

class AreaConfig(object):

    def __init__(self, id, title, kind):
        self.id = id
        self.title = title
        self.kind = kind

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, AreaConfig) and self.id == other.id

class LayoutSourceBase(object):

    def getTitle(self, context, value):
        return value.title

    def getToken(self, context, value):
        return value.id

    def isAvailable(self, node, context):
        # Avoid circular import
        from zeit.content.cp.interfaces import ICenterPage
        context = ICenterPage(context, None)
        if context is None:
            return True
        return super(LayoutSourceBase, self).isAvailable(node, context)

class TeaserBlockLayoutSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'block-layout-source'
    attribute = 'id'

    class source_class(zc.sourcefactory.source.FactoredContextualSource):

        def find(self, id):
            return self.factory.find(self.context, id)

    def isAvailable(self, value, context):
        return value.is_allowed(context)

    def getValues(self, context):
        return [x for x in self._values().values()
                if self.isAvailable(x, context)]

    @gocept.cache.method.Memoize(600, ignore_self=True)
    def _values(self):
        tree = self._get_tree()
        result = collections.OrderedDict()
        for node in tree.iterchildren('*'):
            g = node.get
            areas = g('areas')
            areas = areas.split()
            columns = g('columns', 1)
            if columns:
                columns = int(columns)
            iface = node.get('available', 'zope.interface.Interface')
            try:
                iface = zope.dottedname.resolve.resolve(iface)
            except ImportError:
                iface = None
            id = node.get(self.attribute)
            result[id] = BlockLayout(
                id, self._get_title_for(node),
                g('image_pattern'), areas, columns, g('default', ''), iface)
        return result

    def find(self, context, id):
        value = self._values().get(id)
        if (not value or not self.isAvailable(value, context)
            or not self.filterValue(context, value)):
            return None
        return value

    def _get_title_for(self, node):
        return unicode(node.get('title'))

    def filterValue(self, context, value):
        if context is None:
            return True
        area = zeit.content.cp.interfaces.IArea(context)
        return area.kind in value.areas

TEASERBLOCK_LAYOUTS = TeaserBlockLayoutSource()

class RegionConfigSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'region-config-source'

    def getValues(self, context):
        tree = self._get_tree()
        result = []
        for node in tree.iterchildren('*'):
            if not self.isAvailable(node, context):
                continue
            result.append(RegionConfig(
                node.get('id'),
                self._get_title_for(node),
                node.get('kind'),
                [{'kind': x.get('kind')} for x in node.iterchildren('area')]
            ))
        return result

    def _get_title_for(self, node):
        return unicode(node.get('title'))

REGION_CONFIGS = RegionConfigSource()

class AreaConfigSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'area-config-source'

    def getValues(self, context):
        tree = self._get_tree()
        result = []
        for node in tree.iterchildren('*'):
            if not self.isAvailable(node, context):
                continue
            result.append(AreaConfig(
                node.get('id'),
                self._get_title_for(node),
                node.get('kind')))
        return result

    def _get_title_for(self, node):
        return unicode(node.get('title'))

AREA_CONFIGS = AreaConfigSource()

def get_layout(id):
    return TEASERBLOCK_LAYOUTS(None).find(id)
<|endoftext|>


<commit_before># Copyright (c) 2015 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.

from UM.Controller import Controller
from UM.PluginRegistry import PluginRegistry
from UM.Mesh.MeshFileHandler import MeshFileHandler
from UM.Settings.MachineSettings import MachineSettings
from UM.Resources import Resources
from UM.Operations.OperationStack import OperationStack
from UM.Event import CallFunctionEvent
from UM.Signal import Signal, SignalEmitter
from UM.Logger import Logger
from UM.Preferences import Preferences
from UM.OutputDevice.OutputDeviceManager import OutputDeviceManager
from UM.Settings.MachineManager import MachineManager

import threading
import argparse
import os
import urllib.parse
import sys

##  Central object responsible for running the main event loop and creating other central objects.
#
#   The Application object is a central object for accessing other important objects. It is also
#   responsible for starting the main event loop. It is passed on to plugins so it can be easily
#   used to access objects required for those plugins.
class Application(SignalEmitter):
    ##  Init method
    #
    #   \param name \type{string} The name of the application.
    #   \param version \type{string} Version, formatted as major.minor.rev
    def __init__(self, name, version,  **kwargs):
        if(Application._instance != None):
            raise ValueError("Duplicate singleton creation")

        # If the constructor is called and there is no instance, set the instance to self.
        # This is done because we can't make constructor private
        Application._instance = self

        self._application_name = name
        self._version = version

        Signal._app = self
        Resources.ApplicationIdentifier = name

        Resources.addSearchPath(os.path.dirname(sys.executable))
        Resources.addSearchPath(os.path.join(Application.getInstallPrefix(), "share", "uranium"))
        Resources.addSearchPath(os.path.join(Application.getInstallPrefix(), "Resources", "uranium"))
        Resources.addSearchPath(os.path.join(Application.getInstallPrefix(), "Resources", self.getApplicationName()))
        if not hasattr(sys, "frozen"):
            Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))

        self._main_thread = threading.current_thread()

        super().__init__(**kwargs) # Call super to make multiple inheritence work.

        self._renderer = None

        PluginRegistry.addType("backend", self.setBackend)
        PluginRegistry.addType("logger", Logger.addLogger)
        PluginRegistry.addType("extension", self.addExtension)

        preferences = Preferences.getInstance()
        preferences.addPreference("general/language", "en")
        try:
            preferences.readFromFile(Resources.getPath(Resources.Preferences, self._application_name + ".cfg"))
        except FileNotFoundError:
            pass

        self._controller = Controller(self)
        self._mesh_file_handler = MeshFileHandler()
        self._extensions = []
        self._backend = None
        self._output_device_manager = OutputDeviceManager()
        self._machine_manager = MachineManager()

        self._required_plugins = []

        self._operation_stack = OperationStack()

        self._plugin_registry = PluginRegistry.getInstance()

        self._plugin_registry.addPluginLocation(os.path.join(Application.getInstallPrefix(), "lib", "uranium"))
        self._plugin_registry.addPluginLocation(os.path.join(os.path.dirname(sys.executable), "plugins"))
        self._plugin_registry.addPluginLocation(os.path.join(Application.getInstallPrefix(), "Resources", "uranium", "plugins"))
        self._plugin_registry.addPluginLocation(os.path.join(Application.getInstallPrefix(), "Resources", self.getApplicationName(), "plugins"))
        # Locally installed plugins
        self._plugin_registry.addPluginLocation(os.path.join(Resources.getStoragePath(Resources.Resources), "plugins"))
        if not hasattr(sys, "frozen"):
            self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins"))

        self._plugin_registry.setApplication(self)

        self._parsed_command_line = None
        self.parseCommandLine()

        self._visible_messages = []
        self._message_lock = threading.Lock()
        self.showMessageSignal.connect(self.showMessage)
        self.hideMessageSignal.connect(self.hideMessage)

    ##  Emitted when the application window was closed and we need to shut down the application
    applicationShuttingDown = Signal()

    showMessageSignal = Signal()

    hideMessageSignal = Signal()

    def hideMessage(self, message):
        raise NotImplementedError

    def showMessage(self, message):
        raise NotImplementedError

    ##  Get the version of the application
    #   \returns version \type{string}
    def getVersion(self):
        return self._version

    ##  Add a message to the visible message list so it will be displayed.
    #   This should only be called by message object itself.
    #   To show a message, simply create it and call its .show() function.
    #   \param message \type{Message} message object
    #   \sa Message::show()
    #def showMessage(self, message):
    #    with self._message_lock:
    #        if message not in self._visible_messages:
    #            self._visible_messages.append(message)
    #            self.visibleMessageAdded.emit(message)

    visibleMessageAdded = Signal()

    ##  Remove a message from the visible message list so it will no longer be displayed.
    #   This should only be called by message object itself.
    #   in principle, this should only be called by the message itself (hide)
    #   \param message \type{Message} message object
    #   \sa Message::hide()
    #def hideMessage(self, message):
    #    with self._message_lock:
    #        if message in self._visible_messages:
    #            self._visible_messages.remove(message)
    #            self.visibleMessageRemoved.emit(message)

    ##  Hide message by ID (as provided by built-in id function)
    #   \param message_id \type{long}
    def hideMessageById(self, message_id):
        found_message = None
        with self._message_lock:
            for message in self._visible_messages:
                if id(message) == message_id:
                    found_message = message
        if found_message is not None:
            self.hideMessageSignal.emit(found_message)

    visibleMessageRemoved = Signal()

    ##  Get list of all visible messages
    #   \returns visible_messages \type{list}
    def getVisibleMessages(self):
        with self._message_lock:
            return self._visible_messages

    ##  Function that needs to be overriden by child classes with a list of plugin it needs.
    def _loadPlugins(self):
        pass

    def getCommandLineOption(self, name, default = None):
        if not self._parsed_command_line:
            self.parseCommandLine()

        return self._parsed_command_line.get(name, default)

    ##  Get name of the application.
    #   \returns application_name \type{string}
    def getApplicationName(self):
        return self._application_name

    ##  Set name of the application.
    #   \param application_name \type{string}
    def setApplicationName(self, application_name):
        self._application_name = application_name

    ##  Application has a list of plugins that it *must* have. If it does not have these, it cannot function.
    #   These plugins can not be disabled in any way.
    #   \returns required_plugins \type{list}
    def getRequiredPlugins(self):
        return self._required_plugins

    ##  Set the plugins that the application *must* have in order to function.
    #   \param plugin_names \type{list} List of strings with the names of the required plugins
    def setRequiredPlugins(self, plugin_names):
        self._required_plugins = plugin_names

    ##  Set the backend of the application (the program that does the heavy lifting).
    #   \param backend \type{Backend}
    def setBackend(self, backend):
        self._backend = backend

    def getMachineManager(self):
        return self._machine_manager

    ##  Get the backend of the application (the program that does the heavy lifting).
    #   \returns Backend \type{Backend}
    def getBackend(self):
        return self._backend

    ##  Get the PluginRegistry of this application.
    #   \returns PluginRegistry \type{PluginRegistry}
    def getPluginRegistry(self):
        return self._plugin_registry

    ##  Get the Controller of this application.
    #   \returns Controller \type{Controller}
    def getController(self):
        return self._controller

    ##  Get the MeshFileHandler of this application.
    #   \returns MeshFileHandler \type{MeshFileHandler}
    def getMeshFileHandler(self):
        return self._mesh_file_handler

    def getOperationStack(self):
        return self._operation_stack

    def getOutputDeviceManager(self):
        return self._output_device_manager

    ##  Run the main eventloop.
    #   This method should be reimplemented by subclasses to start the main event loop.
    #   \exception NotImplementedError
    def run(self):
        raise NotImplementedError("Run must be implemented by application")

    ##  Return an application-specific Renderer object.
    #   \exception NotImplementedError
    def getRenderer(self):
        raise NotImplementedError("getRenderer must be implemented by subclasses.")

    ##  Post a function event onto the event loop.
    #
    #   This takes a CallFunctionEvent object and puts it into the actual event loop.
    #   \exception NotImplementedError
    def functionEvent(self, event):
        raise NotImplementedError("functionEvent must be implemented by subclasses.")

    ##  Get the application"s main thread.
    def getMainThread(self):
        return self._main_thread

    ##  Return the singleton instance of the application object
    @classmethod
    def getInstance(cls):
        # Note: Explicit use of class name to prevent issues with inheritance.
        if Application._instance is None:
            Application._instance = cls()

        return Application._instance

    def parseCommandLine(self):
        parser = argparse.ArgumentParser(prog = self.getApplicationName())
        parser.add_argument("--version", action="version", version="%(prog)s {0}".format(self.getVersion()))
        parser.add_argument("--external-backend",
                            dest="external-backend",
                            action="store_true", default=False,
                            help="Use an externally started backend instead of starting it automatically.")

        self.addCommandLineOptions(parser)

        self._parsed_command_line = vars(parser.parse_args())

    ##  Can be overridden to add additional command line options to the parser.
    #
    #   \param parser \type{argparse.ArgumentParser} The parser that will parse the command line.
    def addCommandLineOptions(self, parser):
        pass

    def addExtension(self, extension):
        self._extensions.append(extension)

    def getExtensions(self):
        return self._extensions

    @staticmethod
    def getInstallPrefix():
        if "python" in os.path.basename(sys.executable):
            return os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), ".."))
        else:
            return os.path.abspath(os.path.join(os.path.dirname(sys.executable), ".."))

    _instance = None
<commit_msg>Properly pass the application name to MachineManager's ctor<commit_after># Copyright (c) 2015 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.

from UM.Controller import Controller
from UM.PluginRegistry import PluginRegistry
from UM.Mesh.MeshFileHandler import MeshFileHandler
from UM.Settings.MachineSettings import MachineSettings
from UM.Resources import Resources
from UM.Operations.OperationStack import OperationStack
from UM.Event import CallFunctionEvent
from UM.Signal import Signal, SignalEmitter
from UM.Logger import Logger
from UM.Preferences import Preferences
from UM.OutputDevice.OutputDeviceManager import OutputDeviceManager
from UM.Settings.MachineManager import MachineManager

import threading
import argparse
import os
import urllib.parse
import sys

##  Central object responsible for running the main event loop and creating other central objects.
#
#   The Application object is a central object for accessing other important objects. It is also
#   responsible for starting the main event loop. It is passed on to plugins so it can be easily
#   used to access objects required for those plugins.
class Application(SignalEmitter):
    ##  Init method
    #
    #   \param name \type{string} The name of the application.
    #   \param version \type{string} Version, formatted as major.minor.rev
    def __init__(self, name, version,  **kwargs):
        if(Application._instance != None):
            raise ValueError("Duplicate singleton creation")

        # If the constructor is called and there is no instance, set the instance to self.
        # This is done because we can't make constructor private
        Application._instance = self

        self._application_name = name
        self._version = version

        Signal._app = self
        Resources.ApplicationIdentifier = name

        Resources.addSearchPath(os.path.dirname(sys.executable))
        Resources.addSearchPath(os.path.join(Application.getInstallPrefix(), "share", "uranium"))
        Resources.addSearchPath(os.path.join(Application.getInstallPrefix(), "Resources", "uranium"))
        Resources.addSearchPath(os.path.join(Application.getInstallPrefix(), "Resources", self.getApplicationName()))
        if not hasattr(sys, "frozen"):
            Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))

        self._main_thread = threading.current_thread()

        super().__init__(**kwargs) # Call super to make multiple inheritence work.

        self._renderer = None

        PluginRegistry.addType("backend", self.setBackend)
        PluginRegistry.addType("logger", Logger.addLogger)
        PluginRegistry.addType("extension", self.addExtension)

        preferences = Preferences.getInstance()
        preferences.addPreference("general/language", "en")
        try:
            preferences.readFromFile(Resources.getPath(Resources.Preferences, self._application_name + ".cfg"))
        except FileNotFoundError:
            pass

        self._controller = Controller(self)
        self._mesh_file_handler = MeshFileHandler()
        self._extensions = []
        self._backend = None
        self._output_device_manager = OutputDeviceManager()
        self._machine_manager = MachineManager(self._application_name)

        self._required_plugins = []

        self._operation_stack = OperationStack()

        self._plugin_registry = PluginRegistry.getInstance()

        self._plugin_registry.addPluginLocation(os.path.join(Application.getInstallPrefix(), "lib", "uranium"))
        self._plugin_registry.addPluginLocation(os.path.join(os.path.dirname(sys.executable), "plugins"))
        self._plugin_registry.addPluginLocation(os.path.join(Application.getInstallPrefix(), "Resources", "uranium", "plugins"))
        self._plugin_registry.addPluginLocation(os.path.join(Application.getInstallPrefix(), "Resources", self.getApplicationName(), "plugins"))
        # Locally installed plugins
        self._plugin_registry.addPluginLocation(os.path.join(Resources.getStoragePath(Resources.Resources), "plugins"))
        if not hasattr(sys, "frozen"):
            self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins"))

        self._plugin_registry.setApplication(self)

        self._parsed_command_line = None
        self.parseCommandLine()

        self._visible_messages = []
        self._message_lock = threading.Lock()
        self.showMessageSignal.connect(self.showMessage)
        self.hideMessageSignal.connect(self.hideMessage)

    ##  Emitted when the application window was closed and we need to shut down the application
    applicationShuttingDown = Signal()

    showMessageSignal = Signal()

    hideMessageSignal = Signal()

    def hideMessage(self, message):
        raise NotImplementedError

    def showMessage(self, message):
        raise NotImplementedError

    ##  Get the version of the application
    #   \returns version \type{string}
    def getVersion(self):
        return self._version

    ##  Add a message to the visible message list so it will be displayed.
    #   This should only be called by message object itself.
    #   To show a message, simply create it and call its .show() function.
    #   \param message \type{Message} message object
    #   \sa Message::show()
    #def showMessage(self, message):
    #    with self._message_lock:
    #        if message not in self._visible_messages:
    #            self._visible_messages.append(message)
    #            self.visibleMessageAdded.emit(message)

    visibleMessageAdded = Signal()

    ##  Remove a message from the visible message list so it will no longer be displayed.
    #   This should only be called by message object itself.
    #   in principle, this should only be called by the message itself (hide)
    #   \param message \type{Message} message object
    #   \sa Message::hide()
    #def hideMessage(self, message):
    #    with self._message_lock:
    #        if message in self._visible_messages:
    #            self._visible_messages.remove(message)
    #            self.visibleMessageRemoved.emit(message)

    ##  Hide message by ID (as provided by built-in id function)
    #   \param message_id \type{long}
    def hideMessageById(self, message_id):
        found_message = None
        with self._message_lock:
            for message in self._visible_messages:
                if id(message) == message_id:
                    found_message = message
        if found_message is not None:
            self.hideMessageSignal.emit(found_message)

    visibleMessageRemoved = Signal()

    ##  Get list of all visible messages
    #   \returns visible_messages \type{list}
    def getVisibleMessages(self):
        with self._message_lock:
            return self._visible_messages

    ##  Function that needs to be overriden by child classes with a list of plugin it needs.
    def _loadPlugins(self):
        pass

    def getCommandLineOption(self, name, default = None):
        if not self._parsed_command_line:
            self.parseCommandLine()

        return self._parsed_command_line.get(name, default)

    ##  Get name of the application.
    #   \returns application_name \type{string}
    def getApplicationName(self):
        return self._application_name

    ##  Set name of the application.
    #   \param application_name \type{string}
    def setApplicationName(self, application_name):
        self._application_name = application_name

    ##  Application has a list of plugins that it *must* have. If it does not have these, it cannot function.
    #   These plugins can not be disabled in any way.
    #   \returns required_plugins \type{list}
    def getRequiredPlugins(self):
        return self._required_plugins

    ##  Set the plugins that the application *must* have in order to function.
    #   \param plugin_names \type{list} List of strings with the names of the required plugins
    def setRequiredPlugins(self, plugin_names):
        self._required_plugins = plugin_names

    ##  Set the backend of the application (the program that does the heavy lifting).
    #   \param backend \type{Backend}
    def setBackend(self, backend):
        self._backend = backend

    def getMachineManager(self):
        return self._machine_manager

    ##  Get the backend of the application (the program that does the heavy lifting).
    #   \returns Backend \type{Backend}
    def getBackend(self):
        return self._backend

    ##  Get the PluginRegistry of this application.
    #   \returns PluginRegistry \type{PluginRegistry}
    def getPluginRegistry(self):
        return self._plugin_registry

    ##  Get the Controller of this application.
    #   \returns Controller \type{Controller}
    def getController(self):
        return self._controller

    ##  Get the MeshFileHandler of this application.
    #   \returns MeshFileHandler \type{MeshFileHandler}
    def getMeshFileHandler(self):
        return self._mesh_file_handler

    def getOperationStack(self):
        return self._operation_stack

    def getOutputDeviceManager(self):
        return self._output_device_manager

    ##  Run the main eventloop.
    #   This method should be reimplemented by subclasses to start the main event loop.
    #   \exception NotImplementedError
    def run(self):
        raise NotImplementedError("Run must be implemented by application")

    ##  Return an application-specific Renderer object.
    #   \exception NotImplementedError
    def getRenderer(self):
        raise NotImplementedError("getRenderer must be implemented by subclasses.")

    ##  Post a function event onto the event loop.
    #
    #   This takes a CallFunctionEvent object and puts it into the actual event loop.
    #   \exception NotImplementedError
    def functionEvent(self, event):
        raise NotImplementedError("functionEvent must be implemented by subclasses.")

    ##  Get the application"s main thread.
    def getMainThread(self):
        return self._main_thread

    ##  Return the singleton instance of the application object
    @classmethod
    def getInstance(cls):
        # Note: Explicit use of class name to prevent issues with inheritance.
        if Application._instance is None:
            Application._instance = cls()

        return Application._instance

    def parseCommandLine(self):
        parser = argparse.ArgumentParser(prog = self.getApplicationName())
        parser.add_argument("--version", action="version", version="%(prog)s {0}".format(self.getVersion()))
        parser.add_argument("--external-backend",
                            dest="external-backend",
                            action="store_true", default=False,
                            help="Use an externally started backend instead of starting it automatically.")

        self.addCommandLineOptions(parser)

        self._parsed_command_line = vars(parser.parse_args())

    ##  Can be overridden to add additional command line options to the parser.
    #
    #   \param parser \type{argparse.ArgumentParser} The parser that will parse the command line.
    def addCommandLineOptions(self, parser):
        pass

    def addExtension(self, extension):
        self._extensions.append(extension)

    def getExtensions(self):
        return self._extensions

    @staticmethod
    def getInstallPrefix():
        if "python" in os.path.basename(sys.executable):
            return os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), ".."))
        else:
            return os.path.abspath(os.path.join(os.path.dirname(sys.executable), ".."))

    _instance = None
<|endoftext|>


<commit_before>import collections
import gocept.cache.method
import zc.sourcefactory.source
import zeit.cms.content.sources
import zope.interface
import zope.security.proxy

class ITeaserBlockLayout(zope.interface.Interface):
    """Layout of a teaser block."""

    id = zope.schema.ASCIILine(title=u'Id used in xml to identify layout')
    title = zope.schema.TextLine(title=u'Human readable title.')
    image_pattern = zope.schema.ASCIILine(
        title=u'A match for the image to use in this layout.')
    columns = zope.schema.Int(
        title=u'Columns',
        min=1,
        max=2,
        default=1)
    areas = zope.schema.Set(
        title=u'Kinds of areas where this layout is allowed')
    default_in_areas = zope.schema.Bool(
        title=u'Kinds of areas where this layout is the default')
    types = zope.schema.Set(
        title=u'Types of CP where this layout is allowed')

class BlockLayout(object):

    zope.interface.implements(ITeaserBlockLayout)

    def __init__(self, id, title, image_pattern=None,
                 areas=None, columns=1, default=False, available=None,
                 types=None):
        self.id = id
        self.title = title
        self.image_pattern = image_pattern
        self.areas = frozenset(areas)
        self.columns = columns
        self.default_in_areas = default
        self.available_iface = available
        self.types = types.split(' ') if types else None

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, BlockLayout) and self.id == other.id

    def is_default(self, block):
        area = zeit.content.cp.interfaces.IArea(block)
        return area.kind in self.default_in_areas

    def is_allowed(self, context):
        # Avoid circular import
        from zeit.content.cp.interfaces import ICenterPage
        cp = ICenterPage(context, None)
        if cp is None:
            return True
        return self.is_allowed_iface(cp) and self.is_allowed_type(cp)

    def is_allowed_iface(self, cp):
        if self.available_iface is None:
            return False
        return self.available_iface.providedBy(cp)

    def is_allowed_type(self, cp):
        if not self.types:
            return True
        negative_present = False
        match = False
        for typ in self.types:
            if typ.startswith('!'):
                negative_present = True
                typ = typ.replace('!', '', 1)
            if cp.type == typ:
                match = True
        if negative_present:
            return not match
        else:
            return match

class RegionConfig(object):

    def __init__(self, id, title, kind, areas):
        self.id = id
        self.title = title
        self.kind = kind
        self.areas = areas

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, RegionConfig) and self.id == other.id

class AreaConfig(object):

    def __init__(self, id, title, kind):
        self.id = id
        self.title = title
        self.kind = kind

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, AreaConfig) and self.id == other.id

class LayoutSourceBase(object):

    def getTitle(self, context, value):
        return value.title

    def getToken(self, context, value):
        return value.id

    def isAvailable(self, node, context):
        # Avoid circular import
        from zeit.content.cp.interfaces import ICenterPage
        context = ICenterPage(context, None)
        if context is None:
            return True
        return super(LayoutSourceBase, self).isAvailable(node, context)

class TeaserBlockLayoutSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'block-layout-source'
    attribute = 'id'

    class source_class(zc.sourcefactory.source.FactoredContextualSource):

        def find(self, id):
            return self.factory.find(self.context, id)

    def isAvailable(self, value, context):
        return value.is_allowed(context)

    def getValues(self, context):
        return [x for x in self._values().values()
                if self.isAvailable(x, context)]

    @gocept.cache.method.Memoize(600, ignore_self=True)
    def _values(self):
        tree = self._get_tree()
        result = collections.OrderedDict()
        for node in tree.iterchildren('*'):
            g = node.get
            areas = g('areas')
            areas = areas.split()
            columns = g('columns', 1)
            if columns:
                columns = int(columns)
            iface = node.get('available', 'zope.interface.Interface')
            try:
                iface = zope.dottedname.resolve.resolve(iface)
            except ImportError:
                iface = None
            id = node.get(self.attribute)
            result[id] = BlockLayout(
                id, self._get_title_for(node),
                g('image_pattern'), areas, columns, g('default', ''), iface,
                g('types', None))
        return result

    def find(self, context, id):
        value = self._values().get(id)
        if (not value or not self.isAvailable(value, context)
            or not self.filterValue(context, value)):
            return None
        return value

    def _get_title_for(self, node):
        return unicode(node.get('title'))

    def filterValue(self, context, value):
        if context is None:
            return True
        area = zeit.content.cp.interfaces.IArea(context)
        return area.kind in value.areas

TEASERBLOCK_LAYOUTS = TeaserBlockLayoutSource()

class RegionConfigSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'region-config-source'

    def getValues(self, context):
        tree = self._get_tree()
        result = []
        for node in tree.iterchildren('*'):
            if not self.isAvailable(node, context):
                continue
            result.append(RegionConfig(
                node.get('id'),
                self._get_title_for(node),
                node.get('kind'),
                [{'kind': x.get('kind')} for x in node.iterchildren('area')]
            ))
        return result

    def _get_title_for(self, node):
        return unicode(node.get('title'))

REGION_CONFIGS = RegionConfigSource()

class AreaConfigSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'area-config-source'

    def getValues(self, context):
        tree = self._get_tree()
        result = []
        for node in tree.iterchildren('*'):
            if not self.isAvailable(node, context):
                continue
            result.append(AreaConfig(
                node.get('id'),
                self._get_title_for(node),
                node.get('kind')))
        return result

    def _get_title_for(self, node):
        return unicode(node.get('title'))

AREA_CONFIGS = AreaConfigSource()

def get_layout(id):
    return TEASERBLOCK_LAYOUTS(None).find(id)
<commit_msg>Extract available iface mechanics<commit_after>import collections
import gocept.cache.method
import zc.sourcefactory.source
import zeit.cms.content.sources
import zope.interface
import zope.security.proxy

class ITeaserBlockLayout(zope.interface.Interface):
    """Layout of a teaser block."""

    id = zope.schema.ASCIILine(title=u'Id used in xml to identify layout')
    title = zope.schema.TextLine(title=u'Human readable title.')
    image_pattern = zope.schema.ASCIILine(
        title=u'A match for the image to use in this layout.')
    columns = zope.schema.Int(
        title=u'Columns',
        min=1,
        max=2,
        default=1)
    areas = zope.schema.Set(
        title=u'Kinds of areas where this layout is allowed')
    default_in_areas = zope.schema.Bool(
        title=u'Kinds of areas where this layout is the default')
    types = zope.schema.Set(
        title=u'Types of CP where this layout is allowed')

class BlockLayout(object):

    zope.interface.implements(ITeaserBlockLayout)

    def __init__(self, id, title, image_pattern=None,
                 areas=None, columns=1, default=False, available=None,
                 types=None):
        self.id = id
        self.title = title
        self.image_pattern = image_pattern
        self.areas = frozenset(areas)
        self.columns = columns
        self.default_in_areas = default
        if available is None:
            available = 'zope.interface.Interface'
        try:
            available = zope.dottedname.resolve.resolve(available)
        except ImportError:
            available = None
        self.available_iface = available
        self.types = types.split(' ') if types else None

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, BlockLayout) and self.id == other.id

    def is_default(self, block):
        area = zeit.content.cp.interfaces.IArea(block)
        return area.kind in self.default_in_areas

    def is_allowed(self, context):
        # Avoid circular import
        from zeit.content.cp.interfaces import ICenterPage
        cp = ICenterPage(context, None)
        if cp is None:
            return True
        return self.is_allowed_iface(cp) and self.is_allowed_type(cp)

    def is_allowed_iface(self, cp):
        if self.available_iface is None:
            return False
        return self.available_iface.providedBy(cp)

    def is_allowed_type(self, cp):
        if not self.types:
            return True
        negative_present = False
        match = False
        for typ in self.types:
            if typ.startswith('!'):
                negative_present = True
                typ = typ.replace('!', '', 1)
            if cp.type == typ:
                match = True
        if negative_present:
            return not match
        else:
            return match

class RegionConfig(object):

    def __init__(self, id, title, kind, areas):
        self.id = id
        self.title = title
        self.kind = kind
        self.areas = areas

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, RegionConfig) and self.id == other.id

class AreaConfig(object):

    def __init__(self, id, title, kind):
        self.id = id
        self.title = title
        self.kind = kind

    def __eq__(self, other):
        return zope.security.proxy.isinstance(
            other, AreaConfig) and self.id == other.id

class LayoutSourceBase(object):

    def getTitle(self, context, value):
        return value.title

    def getToken(self, context, value):
        return value.id

    def isAvailable(self, node, context):
        # Avoid circular import
        from zeit.content.cp.interfaces import ICenterPage
        context = ICenterPage(context, None)
        if context is None:
            return True
        return super(LayoutSourceBase, self).isAvailable(node, context)

class TeaserBlockLayoutSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'block-layout-source'
    attribute = 'id'

    class source_class(zc.sourcefactory.source.FactoredContextualSource):

        def find(self, id):
            return self.factory.find(self.context, id)

    def isAvailable(self, value, context):
        return value.is_allowed(context)

    def getValues(self, context):
        return [x for x in self._values().values()
                if self.isAvailable(x, context)]

    @gocept.cache.method.Memoize(600, ignore_self=True)
    def _values(self):
        tree = self._get_tree()
        result = collections.OrderedDict()
        for node in tree.iterchildren('*'):
            g = node.get
            areas = g('areas')
            areas = areas.split()
            columns = g('columns', 1)
            if columns:
                columns = int(columns)
            id = node.get(self.attribute)
            result[id] = BlockLayout(
                id, self._get_title_for(node),
                g('image_pattern'), areas, columns, g('default', ''),
                node.get('available', None), g('types', None))
        return result

    def find(self, context, id):
        value = self._values().get(id)
        if (not value or not self.isAvailable(value, context)
            or not self.filterValue(context, value)):
            return None
        return value

    def _get_title_for(self, node):
        return unicode(node.get('title'))

    def filterValue(self, context, value):
        if context is None:
            return True
        area = zeit.content.cp.interfaces.IArea(context)
        return area.kind in value.areas

TEASERBLOCK_LAYOUTS = TeaserBlockLayoutSource()

class RegionConfigSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'region-config-source'

    def getValues(self, context):
        tree = self._get_tree()
        result = []
        for node in tree.iterchildren('*'):
            if not self.isAvailable(node, context):
                continue
            result.append(RegionConfig(
                node.get('id'),
                self._get_title_for(node),
                node.get('kind'),
                [{'kind': x.get('kind')} for x in node.iterchildren('area')]
            ))
        return result

    def _get_title_for(self, node):
        return unicode(node.get('title'))

REGION_CONFIGS = RegionConfigSource()

class AreaConfigSource(
        LayoutSourceBase, zeit.cms.content.sources.XMLSource):

    product_configuration = 'zeit.content.cp'
    config_url = 'area-config-source'

    def getValues(self, context):
        tree = self._get_tree()
        result = []
        for node in tree.iterchildren('*'):
            if not self.isAvailable(node, context):
                continue
            result.append(AreaConfig(
                node.get('id'),
                self._get_title_for(node),
                node.get('kind')))
        return result

    def _get_title_for(self, node):
        return unicode(node.get('title'))

AREA_CONFIGS = AreaConfigSource()

def get_layout(id):
    return TEASERBLOCK_LAYOUTS(None).find(id)
<|endoftext|>


<commit_before># coding: utf8
# Copyright (c) 2010 gocept gmbh & co. kg
# See also LICENSE.txt

from zeit.cms.i18n import MessageFactory as _
import zope.interface
import zope.schema

class ITokens(zope.interface.Interface):
    """Provde access to count tokens (Zählmarke)"""

    def claim():
        """Get a (public token, private token) tuple.

        Raises ValueError when there are no tokens.

        """

    def load(csv_file):
        """Load tokens from csv file (file like object)."""

    def add(public_token, private_token):
        """Add tokens."""

    def order(amount):
        """Order new tokens (from the VGWort web service)."""

class IToken(zope.interface.Interface):

    public_token = zope.schema.TextLine(
        title=_('Public VGWort token'),
        required=False)

    private_token = zope.schema.TextLine(
        title=_('Private VGWort token'),
        required=False)

class IRegistrationInfo(zope.interface.Interface):

    registered_on = zope.schema.Datetime(
        title=_(
            'Timestamp when the content object was registered with VGWort'),
        required=False)

    register_error = zope.schema.Text(
        title=_('Error message that occured during registration'),
        required=False)

class IGenerallyReportableContent(zope.interface.Interface):
    """Marker for types which are generally reportable to vgwort.

    This marker is used to determine types which content types contain content
    which is in general reportable to vgwort (meldefähig). There are more
    constraints which are not supported yet (≥1800 characters etc.)

    """

class IPixelService(zope.interface.Interface):

    def order_pixels(amount):
        """orders ``amount`` new tokens."""

class IMessageService(zope.interface.Interface):

    def new_document(content):
        """notify VGWort about a published document.

        We do not validate the properties of the content object ourselves (are
        the fields we need filled out, are the length constraints satisfied,
        etc.), but leave that to the web service and report its errors instead.
        """

class WebServiceError(Exception):
    """A VGWort web service was unable to process a request because of semantic
    problems.
    """

class TechnicalError(Exception):
    """A VGWort web service had a technical error.
    The request should be retried again later on.
    """

class IReportableContentSource(zope.interface.Interface):
    pass
<commit_msg>Re #7216: updated interface<commit_after># coding: utf8
# Copyright (c) 2010 gocept gmbh & co. kg
# See also LICENSE.txt

from zeit.cms.i18n import MessageFactory as _
import zope.interface
import zope.schema

class ITokens(zope.interface.Interface):
    """Provde access to count tokens (Zählmarke)"""

    def claim():
        """Get a (public token, private token) tuple.

        Raises ValueError when there are no tokens.

        """

    def load(csv_file):
        """Load tokens from csv file (file like object)."""

    def add(public_token, private_token):
        """Add tokens."""

    def order(amount):
        """Order new tokens (from the VGWort web service)."""

class IToken(zope.interface.Interface):

    public_token = zope.schema.TextLine(
        title=_('Public VGWort token'),
        required=False)

    private_token = zope.schema.TextLine(
        title=_('Private VGWort token'),
        required=False)

class IRegistrationInfo(zope.interface.Interface):

    registered_on = zope.schema.Datetime(
        title=_(
            'Timestamp when the content object was registered with VGWort'),
        required=False)

    register_error = zope.schema.Text(
        title=_('Error message that occured during registration'),
        required=False)

class IGenerallyReportableContent(zope.interface.Interface):
    """Marker for types which are generally reportable to vgwort.

    This marker is used to determine types which content types contain content
    which is in general reportable to vgwort (meldefähig). There are more
    constraints which are not supported yet (≥1800 characters etc.)

    """

class IPixelService(zope.interface.Interface):

    def order_pixels(amount):
        """orders ``amount`` new tokens."""

class IMessageService(zope.interface.Interface):

    def new_document(content):
        """notify VGWort about a published document.

        We do not validate the properties of the content object ourselves (are
        the fields we need filled out, are the length constraints satisfied,
        etc.), but leave that to the web service and report its errors instead.
        """

class WebServiceError(Exception):
    """A VGWort web service was unable to process a request because of semantic
    problems.
    """

class TechnicalError(Exception):
    """A VGWort web service had a technical error.
    The request should be retried again later on.
    """

class IReportableContentSource(zope.interface.Interface):

    def __iter__():
        """returns content objects that are eligble for reporting to VGWort
        but have not been reported yet.
        """

    def mark_done(content):
        """marks the content object as reported to VGWort."""

    def mark_error(content, message):
        """store that the object encountered a semantic error while reporting
        to VGWort.
        """
<|endoftext|>


<commit_before># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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 time
import datetime

from mongoengine import LongField

__all__ = [
    'ComplexDateTimeField'
]

SECOND_TO_MICROSECONDS = 1000000

class ComplexDateTimeField(LongField):
    """
    Date time field which handles microseconds exactly and internally stores
    the timestamp as number of microseconds since the unix epoch.

    Note: We need to do that because mongoengine serializes this field as comma
    delimited string which breaks sorting.
    """

    def _convert_from_datetime(self, val):
        """
        Convert a `datetime` object to number of microseconds since epoch representation
        (which will be stored in MongoDB). This is the reverse function of
        `_convert_from_db`.
        """
        result = self._datetime_to_microseconds_since_epoch(value=val)
        return result

    def _convert_from_db(self, value):
        result = self._microseconds_since_epoch_to_datetime(data=value)
        return result

    def _microseconds_since_epoch_to_datetime(self, data):
        """
        Convert a number representation to a `datetime` object (the object you
        will manipulate). This is the reverse function of
        `_convert_from_datetime`.

        :param data: Number of microseconds since the epoch.
        :type data: ``int``
        """
        result = datetime.datetime.fromtimestamp(data//SECOND_TO_MICROSECONDS)
        microseconds_reminder = (data % SECOND_TO_MICROSECONDS)
        result.replace(microsecond=microseconds_reminder)
        return result

    def _datetime_to_microseconds_since_epoch(self, value):
        seconds = time.mktime(value.timetuple())
        microseconds_reminder = value.time().microsecond
        result = (int(seconds * SECOND_TO_MICROSECONDS) + microseconds_reminder)
        return result

    def __get__(self, instance, owner):
        data = super(ComplexDateTimeField, self).__get__(instance, owner)
        if data is None:
            return datetime.datetime.now()
        if isinstance(data, datetime.datetime):
            return data
        return self._convert_from_db(data)

    def __set__(self, instance, value):
        value = self._convert_from_datetime(value) if value else value
        return super(ComplexDateTimeField, self).__set__(instance, value)

    def validate(self, value):
        value = self.to_python(value)
        if not isinstance(value, datetime.datetime):
            self.error('Only datetime objects may used in a '
                       'ComplexDateTimeField')

    def to_python(self, value):
        original_value = value
        try:
            return self._convert_from_db(value)
        except:
            return original_value

    def to_mongo(self, value):
        value = self.to_python(value)
        return self._convert_from_datetime(value)

    def prepare_query_value(self, op, value):
        return self._convert_from_datetime(value)
<commit_msg>Lint fix.<commit_after># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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 time
import datetime

from mongoengine import LongField

__all__ = [
    'ComplexDateTimeField'
]

SECOND_TO_MICROSECONDS = 1000000

class ComplexDateTimeField(LongField):
    """
    Date time field which handles microseconds exactly and internally stores
    the timestamp as number of microseconds since the unix epoch.

    Note: We need to do that because mongoengine serializes this field as comma
    delimited string which breaks sorting.
    """

    def _convert_from_datetime(self, val):
        """
        Convert a `datetime` object to number of microseconds since epoch representation
        (which will be stored in MongoDB). This is the reverse function of
        `_convert_from_db`.
        """
        result = self._datetime_to_microseconds_since_epoch(value=val)
        return result

    def _convert_from_db(self, value):
        result = self._microseconds_since_epoch_to_datetime(data=value)
        return result

    def _microseconds_since_epoch_to_datetime(self, data):
        """
        Convert a number representation to a `datetime` object (the object you
        will manipulate). This is the reverse function of
        `_convert_from_datetime`.

        :param data: Number of microseconds since the epoch.
        :type data: ``int``
        """
        result = datetime.datetime.fromtimestamp(data // SECOND_TO_MICROSECONDS)
        microseconds_reminder = (data % SECOND_TO_MICROSECONDS)
        result.replace(microsecond=microseconds_reminder)
        return result

    def _datetime_to_microseconds_since_epoch(self, value):
        seconds = time.mktime(value.timetuple())
        microseconds_reminder = value.time().microsecond
        result = (int(seconds * SECOND_TO_MICROSECONDS) + microseconds_reminder)
        return result

    def __get__(self, instance, owner):
        data = super(ComplexDateTimeField, self).__get__(instance, owner)
        if data is None:
            return datetime.datetime.now()
        if isinstance(data, datetime.datetime):
            return data
        return self._convert_from_db(data)

    def __set__(self, instance, value):
        value = self._convert_from_datetime(value) if value else value
        return super(ComplexDateTimeField, self).__set__(instance, value)

    def validate(self, value):
        value = self.to_python(value)
        if not isinstance(value, datetime.datetime):
            self.error('Only datetime objects may used in a '
                       'ComplexDateTimeField')

    def to_python(self, value):
        original_value = value
        try:
            return self._convert_from_db(value)
        except:
            return original_value

    def to_mongo(self, value):
        value = self.to_python(value)
        return self._convert_from_datetime(value)

    def prepare_query_value(self, op, value):
        return self._convert_from_datetime(value)
<|endoftext|>


<commit_before># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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 time
import datetime

from mongoengine import LongField

__all__ = [
    'ComplexDateTimeField'
]

SECOND_TO_MICROSECONDS = 1000000

class ComplexDateTimeField(LongField):
    """
    Date time field which handles microseconds exactly and internally stores
    the timestamp as number of microseconds since the unix epoch.

    Note: We need to do that because mongoengine serializes this field as comma
    delimited string which breaks sorting.
    """

    def _convert_from_datetime(self, val):
        """
        Convert a `datetime` object to number of microseconds since epoch representation
        (which will be stored in MongoDB). This is the reverse function of
        `_convert_from_db`.
        """
        result = self._datetime_to_microseconds_since_epoch(value=val)
        return result

    def _convert_from_db(self, value):
        result = self._microseconds_since_epoch_to_datetime(data=value)
        return result

    def _microseconds_since_epoch_to_datetime(self, data):
        """
        Convert a number representation to a `datetime` object (the object you
        will manipulate). This is the reverse function of
        `_convert_from_datetime`.

        :param data: Number of microseconds since the epoch.
        :type data: ``int``
        """
        result = datetime.datetime.fromtimestamp(data // SECOND_TO_MICROSECONDS)
        microseconds_reminder = (data % SECOND_TO_MICROSECONDS)
        result = result.replace(microsecond=microseconds_reminder)
        return result

    def _datetime_to_microseconds_since_epoch(self, value):
        seconds = time.mktime(value.timetuple())
        microseconds_reminder = value.time().microsecond
        result = (int(seconds * SECOND_TO_MICROSECONDS) + microseconds_reminder)
        return result

    def __get__(self, instance, owner):
        data = super(ComplexDateTimeField, self).__get__(instance, owner)
        if data is None:
            return None
        if isinstance(data, datetime.datetime):
            return data
        return self._convert_from_db(data)

    def __set__(self, instance, value):
        value = self._convert_from_datetime(value) if value else value
        return super(ComplexDateTimeField, self).__set__(instance, value)

    def validate(self, value):
        value = self.to_python(value)
        if not isinstance(value, datetime.datetime):
            self.error('Only datetime objects may used in a '
                       'ComplexDateTimeField')

    def to_python(self, value):
        original_value = value
        try:
            return self._convert_from_db(value)
        except:
            return original_value

    def to_mongo(self, value):
        value = self.to_python(value)
        return self._convert_from_datetime(value)

    def prepare_query_value(self, op, value):
        return self._convert_from_datetime(value)
<commit_msg>Fix a bug with ComplexDateTimeField - make sure we are always operating with UTC.<commit_after># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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 time
import datetime
import calendar

from mongoengine import LongField

__all__ = [
    'ComplexDateTimeField'
]

SECOND_TO_MICROSECONDS = 1000000

class ComplexDateTimeField(LongField):
    """
    Date time field which handles microseconds exactly and internally stores
    the timestamp as number of microseconds since the unix epoch.

    Note: We need to do that because mongoengine serializes this field as comma
    delimited string which breaks sorting.
    """

    def _convert_from_datetime(self, val):
        """
        Convert a `datetime` object to number of microseconds since epoch representation
        (which will be stored in MongoDB). This is the reverse function of
        `_convert_from_db`.
        """
        result = self._datetime_to_microseconds_since_epoch(value=val)
        return result

    def _convert_from_db(self, value):
        result = self._microseconds_since_epoch_to_datetime(data=value)
        return result

    def _microseconds_since_epoch_to_datetime(self, data):
        """
        Convert a number representation to a `datetime` object (the object you
        will manipulate). This is the reverse function of
        `_convert_from_datetime`.

        :param data: Number of microseconds since the epoch.
        :type data: ``int``
        """
        result = datetime.datetime.utcfromtimestamp(data // SECOND_TO_MICROSECONDS)
        microseconds_reminder = (data % SECOND_TO_MICROSECONDS)
        result = result.replace(microsecond=microseconds_reminder)
        return result

    def _datetime_to_microseconds_since_epoch(self, value):
        seconds = calendar.timegm(value.timetuple())
        microseconds_reminder = value.time().microsecond
        result = (int(seconds * SECOND_TO_MICROSECONDS) + microseconds_reminder)
        return result

    def __get__(self, instance, owner):
        data = super(ComplexDateTimeField, self).__get__(instance, owner)
        if data is None:
            return None
        if isinstance(data, datetime.datetime):
            return data
        return self._convert_from_db(data)

    def __set__(self, instance, value):
        value = self._convert_from_datetime(value) if value else value
        return super(ComplexDateTimeField, self).__set__(instance, value)

    def validate(self, value):
        value = self.to_python(value)
        if not isinstance(value, datetime.datetime):
            self.error('Only datetime objects may used in a '
                       'ComplexDateTimeField')

    def to_python(self, value):
        original_value = value
        try:
            return self._convert_from_db(value)
        except:
            return original_value

    def to_mongo(self, value):
        value = self.to_python(value)
        return self._convert_from_datetime(value)

    def prepare_query_value(self, op, value):
        return self._convert_from_datetime(value)
<|endoftext|>


<commit_before># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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 time
import datetime

from mongoengine import LongField

__all__ = [
    'ComplexDateTimeField'
]

SECOND_TO_MICROSECONDS = 1000000

class ComplexDateTimeField(LongField):
    """
    Date time field which handles microseconds exactly and internally stores
    the timestamp as number of microseconds since the unix epoch.

    Note: We need to do that because mongoengine serializes this field as comma
    delimited string which breaks sorting.
    """

    def _convert_from_datetime(self, val):
        """
        Convert a `datetime` object to number of microseconds since epoch representation
        (which will be stored in MongoDB). This is the reverse function of
        `_convert_from_db`.
        """
        result = self._datetime_to_microseconds_since_epoch(value=val)
        return result

    def _convert_from_db(self, value):
        result = self._microseconds_since_epoch_to_datetime(data=value)
        return result

    def _microseconds_since_epoch_to_datetime(self, data):
        """
        Convert a number representation to a `datetime` object (the object you
        will manipulate). This is the reverse function of
        `_convert_from_datetime`.

        :param data: Number of microseconds since the epoch.
        :type data: ``int``
        """
        result = datetime.datetime.fromtimestamp(data // SECOND_TO_MICROSECONDS)
        microseconds_reminder = (data % SECOND_TO_MICROSECONDS)
        result = result.replace(microsecond=microseconds_reminder)
        return result

    def _datetime_to_microseconds_since_epoch(self, value):
        seconds = time.mktime(value.timetuple())
        microseconds_reminder = value.time().microsecond
        result = (int(seconds * SECOND_TO_MICROSECONDS) + microseconds_reminder)
        return result

    def __get__(self, instance, owner):
        data = super(ComplexDateTimeField, self).__get__(instance, owner)
        if data is None:
            return datetime.datetime.now()
        if isinstance(data, datetime.datetime):
            return data
        return self._convert_from_db(data)

    def __set__(self, instance, value):
        value = self._convert_from_datetime(value) if value else value
        return super(ComplexDateTimeField, self).__set__(instance, value)

    def validate(self, value):
        value = self.to_python(value)
        if not isinstance(value, datetime.datetime):
            self.error('Only datetime objects may used in a '
                       'ComplexDateTimeField')

    def to_python(self, value):
        original_value = value
        try:
            return self._convert_from_db(value)
        except:
            return original_value

    def to_mongo(self, value):
        value = self.to_python(value)
        return self._convert_from_datetime(value)

    def prepare_query_value(self, op, value):
        return self._convert_from_datetime(value)
<commit_msg>Avoid extra timestamp<commit_after># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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 time
import datetime

from mongoengine import LongField

__all__ = [
    'ComplexDateTimeField'
]

SECOND_TO_MICROSECONDS = 1000000

class ComplexDateTimeField(LongField):
    """
    Date time field which handles microseconds exactly and internally stores
    the timestamp as number of microseconds since the unix epoch.

    Note: We need to do that because mongoengine serializes this field as comma
    delimited string which breaks sorting.
    """

    def _convert_from_datetime(self, val):
        """
        Convert a `datetime` object to number of microseconds since epoch representation
        (which will be stored in MongoDB). This is the reverse function of
        `_convert_from_db`.
        """
        result = self._datetime_to_microseconds_since_epoch(value=val)
        return result

    def _convert_from_db(self, value):
        result = self._microseconds_since_epoch_to_datetime(data=value)
        return result

    def _microseconds_since_epoch_to_datetime(self, data):
        """
        Convert a number representation to a `datetime` object (the object you
        will manipulate). This is the reverse function of
        `_convert_from_datetime`.

        :param data: Number of microseconds since the epoch.
        :type data: ``int``
        """
        result = datetime.datetime.fromtimestamp(data // SECOND_TO_MICROSECONDS)
        microseconds_reminder = (data % SECOND_TO_MICROSECONDS)
        result = result.replace(microsecond=microseconds_reminder)
        return result

    def _datetime_to_microseconds_since_epoch(self, value):
        seconds = time.mktime(value.timetuple())
        microseconds_reminder = value.time().microsecond
        result = (int(seconds * SECOND_TO_MICROSECONDS) + microseconds_reminder)
        return result

    def __get__(self, instance, owner):
        data = super(ComplexDateTimeField, self).__get__(instance, owner)
        if data is None:
            return None
        if isinstance(data, datetime.datetime):
            return data
        return self._convert_from_db(data)

    def __set__(self, instance, value):
        value = self._convert_from_datetime(value) if value else value
        return super(ComplexDateTimeField, self).__set__(instance, value)

    def validate(self, value):
        value = self.to_python(value)
        if not isinstance(value, datetime.datetime):
            self.error('Only datetime objects may used in a '
                       'ComplexDateTimeField')

    def to_python(self, value):
        original_value = value
        try:
            return self._convert_from_db(value)
        except:
            return original_value

    def to_mongo(self, value):
        value = self.to_python(value)
        return self._convert_from_datetime(value)

    def prepare_query_value(self, op, value):
        return self._convert_from_datetime(value)
<|endoftext|>


<commit_before><commit_msg>Turned off automatic server startup<commit_after><|endoftext|>


<commit_before>import shutil
from os.path import isfile, join, getmtime
from os import listdir

# Locations of the PDF expert directory and the full PDF repository
pdfExpertPath = "/Users/bcjenkin/Dropbox/PDF Expert/"
citationPath = "/Users/bcjenkin/Dropbox/Work/Research/Citations/"

# Files in each directory
pdfFiles = [ f for f in listdir(pdfExpertPath) if isfile(join(pdfExpertPath,f)) ]
citationFiles = [ f for f in listdir(citationPath) if isfile(join(citationPath,f)) ]

# Identify files that have been modified in the PDF experct directory and copy
for file in pdfFiles:
    if file in citationFiles:
        if getmtime(pdfExpertPath+file) > getmtime(citationPath+file):
            shutil.copyfile(pdfExpertPath+file,citationPath+file)<commit_msg>update<commit_after>import shutil
from os.path import isfile, join, getmtime
from os import listdir

# Locations of the PDF expert directory and the full PDF repository
pdfExpertPath = "/Users/bcjenkin/Dropbox/PDF Expert/"
citationPath = "/Users/bcjenkin/Google Drive/Work/Research/Citations/"

# Files in each directory
pdfFiles = [ f for f in listdir(pdfExpertPath) if isfile(join(pdfExpertPath,f)) ]
citationFiles = [ f for f in listdir(citationPath) if isfile(join(citationPath,f)) ]

# Identify files that have been modified in the PDF experct directory and copy
for file in pdfFiles:
    if file in citationFiles:
        if getmtime(pdfExpertPath+file) > getmtime(citationPath+file):
            shutil.copyfile(pdfExpertPath+file,citationPath+file)<|endoftext|>