<commit_before>#!/usr/bin/env python2.3
#
# (C) 2004 British Broadcasting Corporation and Kamaelia Contributors(1)
#     All Rights Reserved.
#
# You may only modify and redistribute this under the terms of any of the
# following licenses(2): Mozilla Public License, V1.1, GNU General
# Public License, V2.0, GNU Lesser General Public License, V2.1
#
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
#     http://kamaelia.sourceforge.net/AUTHORS - please extend this file,
#     not this notice.
# (2) Reproduced in the COPYING file, and at:
#     http://kamaelia.sourceforge.net/COPYING
# Under section 3.5 of the MPL, we are using this text since we deem the MPL
# notice inappropriate for this file. As per MPL/GPL/LGPL removal of this
# notice is prohibited.
#
# Please contact us via: kamaelia-list-owner@lists.sourceforge.net
# to discuss alternative licensing.
# -------------------------------------------------------------------------
"""Kamaelia Concurrency Component Framework.

SCHEDULER

You provide the scheduler with microthreads of microprocesses,
and it runs them, clean and simple. This is usually handled by the component
system via returning a newComponent value. An alternative is to call the
component's activate method.

It also has a slow motion mode designed to help with debugging & testing.

"""
import time
import gc as _gc

from util import removeAll
from idGen import strId, numId
from debug import debug
from Microprocess import microprocess
from Axon import AxonObject as _AxonObject
from Ipc import *
import Queue
try:
    from ctypes import *
    libc = cdll.LoadLibrary("/lib/libc.so.6")
    sched_yield = libc.sched_yield
except ImportError:
    def sched_yield(): pass

def _sort(somelist):
   a=[ x for x in somelist]
   a.sort()
   return a

_ACTIVE       = object()        # microprocess is active (is in the runqueue)
_SLEEPING     = object()        # microprocess is paused (is not in the runqueue)
_GOINGTOSLEEP = object()        # microprocess to be paused (should be removed from the runqueue)

class scheduler(microprocess):
   """Scheduler - runs microthreads of control."""
   run = None
   def __init__(self):
      """Creates a scheduler object. If scheduler.run has not been set, sets it.
      Class initialisation ensures that this object/class attribute is initialised - client
      modules always have access to a standalone scheduler.
      Internal attributes:
         * time = time when this object was last active.
         * threads = set of threads to be run, including their state - whether active or sleeping(paused)
      Whilst there can be more than one scheduler active in the general case you will NOT
      want to create a custom scheduler.
      """
      super(scheduler, self).__init__()
      if not scheduler.run:         # If no scheduler already allocated...
         scheduler.run = self       # Make this scheduler the singleton scheduler.

      self.time = time.time()

      self.threads = {}    # current set of threads and their states (whether sleeping, or running)
      self.wakeRequests = Queue.Queue()
      self.pauseRequests = Queue.Queue()

   def _addThread(self, mprocess):
      """A Microprocess adds itself to the runqueue using this method, using
      the mannerism scheduler.run._addThread(). Generally components will *not*
      use this method to activate themselves, see the component class to see
      how you do that.
      """
      self.wakeThread(mprocess, True)

   def wakeThread(self, mprocess, canActivate=False):
      """\
      wakeThread(mprocess[,canActivate]) - request to wake a sleeping mprocess.

      If sleeping or already active, the specified microprocess will be ensured
      to be active on the next cycle through the scheduler.

      If the microprocess is not running yet then it will not be woken, unless
      canActivate = True (default is False).
      """
      self.wakeRequests.put( (mprocess, canActivate) )

   def pauseThread(self, mprocess):
       """\
       pauseThread(mprocess) - request to put a mprocess to sleep.

       If active, or already sleeping, the specified microprocess will be put
       to leep on the next cycle through the scheduler.
       """
       self.pauseRequests.put( mprocess )

   def isThreadPaused(self, mprocess):
       """\
       Returns True if the specified microprocess is sleeping, or the scheduler
       does not know about it.
       """
       return self.threads.get(mprocess, _SLEEPING) == _SLEEPING
       # doesn't include _GOINGTOSLEEP (inference is the thread isn't asleep yet!)

   def listAllThreads(self):
       """Returns a list of all microprocesses (both active and sleeping)"""
       return self.threads.keys()

   def handleMicroprocessShutdownKnockon(self, knockon):
     if isinstance(knockon, shutdownMicroprocess):
        for i in xrange(len(self.threads)):
           if self.threads[i] in knockon.microprocesses():
              self.threads[i] = None

     if isinstance(knockon, reactivate):
         self._addThread(knockon.original)

   def main(self,slowmo=0,canblock=False):
       """\
       main([slowmo][,canblock]) - Scheduler main loop generator

       Each pass through this generator does two things:
       * one pass through all active microprocesses, giving executing them.
       * processing of wake/sleep requests

       slowmo specifies a delay (in seconds) before the main loop is run.
       slowmo defaults to 0.

       If canblock is True, this generator will briefly) block if there are
       no active microprocesses, otherwise it will return immediately (default).

       This generator terminates when there are no microprocesses left to run.
       """
       nextrunqueue = []
       running = True

       while running:
           sched_yield()

           # slowmo
           now = time.time()
           until = now + slowmo
           if canblock:
               time.sleep(until-now)
           else:
               while now < until:
                   yield 1
                   now = time.time()

           self.time = now   # set "time" attribute for benefit for microprocesses

           runqueue = nextrunqueue
           nextrunqueue = []

           # run microprocesses in the runqueue
           for mprocess in runqueue:
               yield 1

               if self.threads[mprocess] == _ACTIVE:
                   try:
                       result = mprocess.next()

                       if isinstance(result, newComponent):
                           for c in result.components():
                               c.activate()
                       if isinstance(result, WaitComplete):
                           newThread = microprocess(result.args[0], reactivate(mprocess))
                           newThread.activate()
                           del self.threads[mprocess]
                           mprocess = None

                       if mprocess:
                           nextrunqueue.append(mprocess)
                   except StopIteration:
                       del self.threads[mprocess]
                       mprocess.stop()
                       knockon = mprocess._closeDownMicroprocess()
                       self.handleMicroprocessShutdownKnockon(knockon)
               else:
                   self.threads[mprocess] = _SLEEPING

           # make sure, even if there weren't any micprocesses active, we yield
           # control at least once
           yield 1

           # process pause requests first - to prevent race conditions, we do
           # wakeup requests second - safer to leave a thread awake than asleep
           while not self.pauseRequests.empty():
               mprocess = self.pauseRequests.get()
               # only sleep if we're actually in the set of threads(!)
               # otherwise it inadvertently gets added!
               if self.threads.has_key(mprocess):
                   self.threads[mprocess] = _GOINGTOSLEEP
               # marked as going to sleep, rather than asleep since mprocess
               # is still in runqueue (more efficient to leave it to be
               # removed when we iterate through the runqueue)

           allsleeping = len(self.threads) > 0 and len(nextrunqueue) == 0

           while (allsleeping and canblock) or not self.wakeRequests.empty():

               # process requests to wake threads
               try:
                    # wait for wakeup requests, blocks but with a
                    # modest timeout so we still regularly yield (in case this
                    # is a microprocess running in another scheduler)
                    mprocess, canActivate = self.wakeRequests.get(True,0.01)
                    try:
                        currentstate = self.threads[mprocess]
                        if currentstate == _SLEEPING:
                            nextrunqueue.append(mprocess)
                        allsleeping = False
                        self.threads[mprocess] = _ACTIVE
                    except KeyError:
                        # not activated, can we?
                        if canActivate:
                            nextrunqueue.append(mprocess)
                            self.threads[mprocess] = _ACTIVE

               except Queue.Empty:
                    # catch timeout
                    pass

           running = len(self.threads)

   def runThreads(self,slowmo=0):
      for i in self.main(slowmo,canblock=True): pass

microprocess.setSchedulerClass(scheduler)
scheduler() # Initialise the class.

if __name__ == '__main__':
   print "This code current has no test code"
   class foo(microprocess):
      def main(self):
         while 1:
            yield 1
   a=foo()
   a.activate()
   print a
   scheduler.run.runThreads()

<commit_msg>Removed sched_yieldfrom scheduler - no longer needed, now scheduler is capable of blocking when the system is idle. Plus the code didn't seem to function under Win32.<commit_after>#!/usr/bin/env python2.3
#
# (C) 2004 British Broadcasting Corporation and Kamaelia Contributors(1)
#     All Rights Reserved.
#
# You may only modify and redistribute this under the terms of any of the
# following licenses(2): Mozilla Public License, V1.1, GNU General
# Public License, V2.0, GNU Lesser General Public License, V2.1
#
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
#     http://kamaelia.sourceforge.net/AUTHORS - please extend this file,
#     not this notice.
# (2) Reproduced in the COPYING file, and at:
#     http://kamaelia.sourceforge.net/COPYING
# Under section 3.5 of the MPL, we are using this text since we deem the MPL
# notice inappropriate for this file. As per MPL/GPL/LGPL removal of this
# notice is prohibited.
#
# Please contact us via: kamaelia-list-owner@lists.sourceforge.net
# to discuss alternative licensing.
# -------------------------------------------------------------------------
"""Kamaelia Concurrency Component Framework.

SCHEDULER

You provide the scheduler with microthreads of microprocesses,
and it runs them, clean and simple. This is usually handled by the component
system via returning a newComponent value. An alternative is to call the
component's activate method.

It also has a slow motion mode designed to help with debugging & testing.

"""
import time
import gc as _gc

from util import removeAll
from idGen import strId, numId
from debug import debug
from Microprocess import microprocess
from Axon import AxonObject as _AxonObject
from Ipc import *
import Queue

def _sort(somelist):
   a=[ x for x in somelist]
   a.sort()
   return a

_ACTIVE       = object()        # microprocess is active (is in the runqueue)
_SLEEPING     = object()        # microprocess is paused (is not in the runqueue)
_GOINGTOSLEEP = object()        # microprocess to be paused (should be removed from the runqueue)

class scheduler(microprocess):
   """Scheduler - runs microthreads of control."""
   run = None
   def __init__(self):
      """Creates a scheduler object. If scheduler.run has not been set, sets it.
      Class initialisation ensures that this object/class attribute is initialised - client
      modules always have access to a standalone scheduler.
      Internal attributes:
         * time = time when this object was last active.
         * threads = set of threads to be run, including their state - whether active or sleeping(paused)
      Whilst there can be more than one scheduler active in the general case you will NOT
      want to create a custom scheduler.
      """
      super(scheduler, self).__init__()
      if not scheduler.run:         # If no scheduler already allocated...
         scheduler.run = self       # Make this scheduler the singleton scheduler.

      self.time = time.time()

      self.threads = {}    # current set of threads and their states (whether sleeping, or running)
      self.wakeRequests = Queue.Queue()
      self.pauseRequests = Queue.Queue()

   def _addThread(self, mprocess):
      """A Microprocess adds itself to the runqueue using this method, using
      the mannerism scheduler.run._addThread(). Generally components will *not*
      use this method to activate themselves, see the component class to see
      how you do that.
      """
      self.wakeThread(mprocess, True)

   def wakeThread(self, mprocess, canActivate=False):
      """\
      wakeThread(mprocess[,canActivate]) - request to wake a sleeping mprocess.

      If sleeping or already active, the specified microprocess will be ensured
      to be active on the next cycle through the scheduler.

      If the microprocess is not running yet then it will not be woken, unless
      canActivate = True (default is False).
      """
      self.wakeRequests.put( (mprocess, canActivate) )

   def pauseThread(self, mprocess):
       """\
       pauseThread(mprocess) - request to put a mprocess to sleep.

       If active, or already sleeping, the specified microprocess will be put
       to leep on the next cycle through the scheduler.
       """
       self.pauseRequests.put( mprocess )

   def isThreadPaused(self, mprocess):
       """\
       Returns True if the specified microprocess is sleeping, or the scheduler
       does not know about it.
       """
       return self.threads.get(mprocess, _SLEEPING) == _SLEEPING
       # doesn't include _GOINGTOSLEEP (inference is the thread isn't asleep yet!)

   def listAllThreads(self):
       """Returns a list of all microprocesses (both active and sleeping)"""
       return self.threads.keys()

   def handleMicroprocessShutdownKnockon(self, knockon):
     if isinstance(knockon, shutdownMicroprocess):
        for i in xrange(len(self.threads)):
           if self.threads[i] in knockon.microprocesses():
              self.threads[i] = None

     if isinstance(knockon, reactivate):
         self._addThread(knockon.original)

   def main(self,slowmo=0,canblock=False):
       """\
       main([slowmo][,canblock]) - Scheduler main loop generator

       Each pass through this generator does two things:
       * one pass through all active microprocesses, giving executing them.
       * processing of wake/sleep requests

       slowmo specifies a delay (in seconds) before the main loop is run.
       slowmo defaults to 0.

       If canblock is True, this generator will briefly) block if there are
       no active microprocesses, otherwise it will return immediately (default).

       This generator terminates when there are no microprocesses left to run.
       """
       nextrunqueue = []
       running = True

       while running:

           # slowmo
           now = time.time()
           until = now + slowmo
           if canblock:
               time.sleep(until-now)
           else:
               while now < until:
                   yield 1
                   now = time.time()

           self.time = now   # set "time" attribute for benefit for microprocesses

           runqueue = nextrunqueue
           nextrunqueue = []

           # run microprocesses in the runqueue
           for mprocess in runqueue:
               yield 1

               if self.threads[mprocess] == _ACTIVE:
                   try:
                       result = mprocess.next()

                       if isinstance(result, newComponent):
                           for c in result.components():
                               c.activate()
                       if isinstance(result, WaitComplete):
                           newThread = microprocess(result.args[0], reactivate(mprocess))
                           newThread.activate()
                           del self.threads[mprocess]
                           mprocess = None

                       if mprocess:
                           nextrunqueue.append(mprocess)
                   except StopIteration:
                       del self.threads[mprocess]
                       mprocess.stop()
                       knockon = mprocess._closeDownMicroprocess()
                       self.handleMicroprocessShutdownKnockon(knockon)
               else:
                   self.threads[mprocess] = _SLEEPING

           # make sure, even if there weren't any micprocesses active, we yield
           # control at least once
           yield 1

           # process pause requests first - to prevent race conditions, we do
           # wakeup requests second - safer to leave a thread awake than asleep
           while not self.pauseRequests.empty():
               mprocess = self.pauseRequests.get()
               # only sleep if we're actually in the set of threads(!)
               # otherwise it inadvertently gets added!
               if self.threads.has_key(mprocess):
                   self.threads[mprocess] = _GOINGTOSLEEP
               # marked as going to sleep, rather than asleep since mprocess
               # is still in runqueue (more efficient to leave it to be
               # removed when we iterate through the runqueue)

           allsleeping = len(self.threads) > 0 and len(nextrunqueue) == 0

           while (allsleeping and canblock) or not self.wakeRequests.empty():

               # process requests to wake threads
               try:
                    # wait for wakeup requests, blocks but with a
                    # modest timeout so we still regularly yield (in case this
                    # is a microprocess running in another scheduler)
                    mprocess, canActivate = self.wakeRequests.get(True,0.01)
                    try:
                        currentstate = self.threads[mprocess]
                        if currentstate == _SLEEPING:
                            nextrunqueue.append(mprocess)
                        allsleeping = False
                        self.threads[mprocess] = _ACTIVE
                    except KeyError:
                        # not activated, can we?
                        if canActivate:
                            nextrunqueue.append(mprocess)
                            self.threads[mprocess] = _ACTIVE

               except Queue.Empty:
                    # catch timeout
                    pass

           running = len(self.threads)

   def runThreads(self,slowmo=0):
      for i in self.main(slowmo,canblock=True): pass

microprocess.setSchedulerClass(scheduler)
scheduler() # Initialise the class.

if __name__ == '__main__':
   print "This code current has no test code"
   class foo(microprocess):
      def main(self):
         while 1:
            yield 1
   a=foo()
   a.activate()
   print a
   scheduler.run.runThreads()

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
""" The controller routes all requests to the appropriate task module.
Also contains superclasses for Task and Model.

    :copyright: Copyright (c) 2014 Bivio Software, Inc.  All Rights Reserved.
    :license: Apache, see LICENSE for more details.
"""

from publicprize import biv
import publicprize.config
from beaker.middleware import SessionMiddleware
import flask
from functools import wraps
import flask_mail
import flask_mobility
from flask_sqlalchemy import SQLAlchemy
import flask.sessions
import importlib
import inspect
import os
import re
import sys
import urllib.parse
import werkzeug.exceptions

db = None

def app():
    """Singleton app instance"""
    return _app

def init():
    """Initialize class maps.

    Must be done externally, because of circular import from
    components.
    """
    for name in ['general', 'contest']:
        module_prefix = 'publicprize.' + name + '.'
        importlib.import_module(module_prefix + _MODEL_MODULE)
        importlib.import_module(module_prefix + _TASK_MODULE)

def login_required(func):
    """Method decorator which requires a logged in user."""
    @wraps(func)
    def decorated_function(*args, **kwargs):
        """If user is not logged in, redirects to the appropriate oauth task"""
        if not flask.session.get('user.is_logged_in'):
            uri = flask.g.pub_obj.get_login_uri()
            return flask.redirect(
                uri + '?' + urllib.parse.urlencode({
                    'next': flask.request.url
                })
            )
        return func(*args, **kwargs)
    return decorated_function

def mail():
    """Singleton mail instance."""
    return _mail

class Task(object):
    """Provides the actions for a Model"""

    def __init__(self):
        pass

class Model(object):
    """Provides biv support for Models"""

    @classmethod
    def load_biv_obj(cls, biv_id):
        """Load a biv from the db"""
        return cls.query.filter_by(biv_id=biv_id).first_or_404()

    @property
    def task_class(self):
        """Corresponding Task class for this Model"""
        if hasattr(self, '__default_task_class'):
            return self.__default_task_class
        module_name = self.__module__
        module = sys.modules[
            re.sub(_MODEL_MODULE_RE, _TASK_MODULE, module_name)]
        self.__default_task_class = getattr(module, self.__class__.__name__)
        assert inspect.isclass(self.__default_task_class)
        return self.__default_task_class

    def format_absolute_uri(self, action=None):
        """Create an absolute URI for a model action."""
        return flask.url_for(
            '_route',
            path=self.format_uri(action),
            _external=True
        )

    def format_uri(self, action=None, path_info=None, query=None, preserve_next=False, next=None):
        """Creates a URI for this biv_obj appending action and path_info"""
        biv_id = biv.Id(self.biv_id)
        uri = '/' + biv_id.to_biv_uri()
        if action is not None:
            _action_uri_to_function(action, self)
            uri += '/' + action
        if path_info is not None:
            assert action is not None, path_info \
                + ': path_info requires an action'
            uri += '/' + path_info
        # TODO(pjm): 'next' handling needs to be refactored
        if preserve_next and 'next' in flask.request.args:
            if not query:
                query = {}
            query['next'] = flask.request.args['next']
        elif next:
            if not query:
                query = {}
            query['next'] = next
        if query:
            uri += '?' + urllib.parse.urlencode(query)
        return uri

class BeakerSession(flask.sessions.SessionInterface):
    """Session management replacement for standard flask session.
    Stores session info in the application database in the beaker_cache
    table."""
    def __init__(self, app=None):
        if app is not None:
            self.init_app(app)
        else:
            self.app = None

    def init_app(self, app):
        """Register the session manager with flask."""
        app.wsgi_app = SessionMiddleware(
            app.wsgi_app,
            {
                'session.type': 'ext:database',
                'session.url': app.config['SQLALCHEMY_DATABASE_URI'],
                'session.lock_dir': '/tmp/cache/lock',
                # the cookie key
                'session.key': 'pp',
                'session.cookie_expires': False
            }
        )
        app.session_interface = self

    def open_session(self, app, request):
        """Called by flask to create the session"""
        return request.environ.get('beaker.session')

    def save_session(self, app, session, response):
        """Called by flask to save the session"""
        session.save()

_ACTION_METHOD_PREFIX = 'action_'
_DEFAULT_ACTION_NAME = 'index'
_TASK_MODULE = 'task'
_MODEL_MODULE = 'model'
_MODEL_MODULE_RE = r'(?<=\.)' + _MODEL_MODULE + r'$'
_app = flask.Flask(__name__, template_folder='.')
_app.config.from_object(publicprize.config.Config)
BeakerSession(_app)
_mail = flask_mail.Mail(_app)
flask_mobility.Mobility(_app)
db = SQLAlchemy(_app)

def _action_uri_to_function(name, biv_obj):
    """Returns the task function for the uri."""
    name = re.sub(r'\W', '_', name)
    name = _ACTION_METHOD_PREFIX + name
    if not hasattr(biv_obj.task_class, name):
        werkzeug.exceptions.abort(404)
    func = getattr(biv_obj.task_class, name)
    assert inspect.isfunction(func), name + ': no action for ' + biv_obj.biv_id
    return func

def _dispatch_action(name, biv_obj):
    """Returns the task function for the uri. Returns the "index" action if
    there is no uri."""
    if len(name) == 0:
        name = _DEFAULT_ACTION_NAME
    return _action_uri_to_function(name, biv_obj)(biv_obj)

def _parse_path(path):
    """Split the path into the (object, action, path_info) parts."""
    parts = path.split('/', 2)
    biv_uri = parts[0] if len(parts) >= 1 else biv.URI_FOR_NONE
    action = parts[1] if len(parts) >= 2 else _DEFAULT_ACTION_NAME
    path_info = parts[2] if len(parts) >= 3 else None
    return biv.load_obj(biv_uri), action, path_info

def _register_globals():
    """Load globals onto flask's 'g' variable"""
    import publicprize.general.model
    flask.g.pub_obj = publicprize.general.model.General.load_biv_obj(
        publicprize.general.model.PUB_OBJ)

@_app.route("/<path:path>", methods=('GET', 'POST'))
def _route(path):
    """Routes the uri to the appropriate biv_obj"""
    biv_obj, action, path_info = _parse_path(path)
    _register_globals()
    return _dispatch_action(action, biv_obj)

@_app.errorhandler(404)
def _route_404(_):
    """Not found page."""
    return _route(biv.URI_FOR_ERROR + '/' + 'not-found')

@_app.route("/")
def _route_root():
    """Routes to index."""
    return _route('')

@_app.route('/favicon.ico')
def _favicon():
    """Routes to favicon.ico file."""
    return flask.send_from_directory(
        os.path.join(_app.root_path, 'static/img'),
        'favicon.ico', mimetype='image/vnd.microsoft.icon'
    )
<commit_msg>format_absolute_uri() uses https scheme on production<commit_after># -*- coding: utf-8 -*-
""" The controller routes all requests to the appropriate task module.
Also contains superclasses for Task and Model.

    :copyright: Copyright (c) 2014 Bivio Software, Inc.  All Rights Reserved.
    :license: Apache, see LICENSE for more details.
"""

from publicprize import biv
import publicprize.config
from beaker.middleware import SessionMiddleware
import flask
from functools import wraps
import flask_mail
import flask_mobility
from flask_sqlalchemy import SQLAlchemy
import flask.sessions
import importlib
import inspect
import os
import re
import sys
import urllib.parse
import werkzeug.exceptions

db = None

def app():
    """Singleton app instance"""
    return _app

def init():
    """Initialize class maps.

    Must be done externally, because of circular import from
    components.
    """
    for name in ['general', 'contest']:
        module_prefix = 'publicprize.' + name + '.'
        importlib.import_module(module_prefix + _MODEL_MODULE)
        importlib.import_module(module_prefix + _TASK_MODULE)

def login_required(func):
    """Method decorator which requires a logged in user."""
    @wraps(func)
    def decorated_function(*args, **kwargs):
        """If user is not logged in, redirects to the appropriate oauth task"""
        if not flask.session.get('user.is_logged_in'):
            uri = flask.g.pub_obj.get_login_uri()
            return flask.redirect(
                uri + '?' + urllib.parse.urlencode({
                    'next': flask.request.url
                })
            )
        return func(*args, **kwargs)
    return decorated_function

def mail():
    """Singleton mail instance."""
    return _mail

class Task(object):
    """Provides the actions for a Model"""

    def __init__(self):
        pass

class Model(object):
    """Provides biv support for Models"""

    @classmethod
    def load_biv_obj(cls, biv_id):
        """Load a biv from the db"""
        return cls.query.filter_by(biv_id=biv_id).first_or_404()

    @property
    def task_class(self):
        """Corresponding Task class for this Model"""
        if hasattr(self, '__default_task_class'):
            return self.__default_task_class
        module_name = self.__module__
        module = sys.modules[
            re.sub(_MODEL_MODULE_RE, _TASK_MODULE, module_name)]
        self.__default_task_class = getattr(module, self.__class__.__name__)
        assert inspect.isclass(self.__default_task_class)
        return self.__default_task_class

    def format_absolute_uri(self, action=None):
        """Create an absolute URI for a model action."""
        return flask.url_for(
            '_route',
            path=self.format_uri(action),
            _external=True,
            _scheme=(
                'http' if app().config['PUBLICPRIZE']['TEST_MODE']
                else 'https')
        )

    def format_uri(self, action=None, path_info=None, query=None,
                   preserve_next=False, next=None):
        """Creates a URI for this biv_obj appending action and path_info"""
        biv_id = biv.Id(self.biv_id)
        uri = '/' + biv_id.to_biv_uri()
        if action is not None:
            _action_uri_to_function(action, self)
            uri += '/' + action
        if path_info is not None:
            assert action is not None, path_info \
                + ': path_info requires an action'
            uri += '/' + path_info
        # TODO(pjm): 'next' handling needs to be refactored
        if preserve_next and 'next' in flask.request.args:
            if not query:
                query = {}
            query['next'] = flask.request.args['next']
        elif next:
            if not query:
                query = {}
            query['next'] = next
        if query:
            uri += '?' + urllib.parse.urlencode(query)
        return uri

class BeakerSession(flask.sessions.SessionInterface):
    """Session management replacement for standard flask session.
    Stores session info in the application database in the beaker_cache
    table."""
    def __init__(self, app=None):
        if app is not None:
            self.init_app(app)
        else:
            self.app = None

    def init_app(self, app):
        """Register the session manager with flask."""
        app.wsgi_app = SessionMiddleware(
            app.wsgi_app,
            {
                'session.type': 'ext:database',
                'session.url': app.config['SQLALCHEMY_DATABASE_URI'],
                'session.lock_dir': '/tmp/cache/lock',
                # the cookie key
                'session.key': 'pp',
                'session.cookie_expires': False
            }
        )
        app.session_interface = self

    def open_session(self, app, request):
        """Called by flask to create the session"""
        return request.environ.get('beaker.session')

    def save_session(self, app, session, response):
        """Called by flask to save the session"""
        session.save()

_ACTION_METHOD_PREFIX = 'action_'
_DEFAULT_ACTION_NAME = 'index'
_TASK_MODULE = 'task'
_MODEL_MODULE = 'model'
_MODEL_MODULE_RE = r'(?<=\.)' + _MODEL_MODULE + r'$'
_app = flask.Flask(__name__, template_folder='.')
_app.config.from_object(publicprize.config.Config)
BeakerSession(_app)
_mail = flask_mail.Mail(_app)
flask_mobility.Mobility(_app)
db = SQLAlchemy(_app)

def _action_uri_to_function(name, biv_obj):
    """Returns the task function for the uri."""
    name = re.sub(r'\W', '_', name)
    name = _ACTION_METHOD_PREFIX + name
    if not hasattr(biv_obj.task_class, name):
        werkzeug.exceptions.abort(404)
    func = getattr(biv_obj.task_class, name)
    assert inspect.isfunction(func), name + ': no action for ' + biv_obj.biv_id
    return func

def _dispatch_action(name, biv_obj):
    """Returns the task function for the uri. Returns the "index" action if
    there is no uri."""
    if len(name) == 0:
        name = _DEFAULT_ACTION_NAME
    return _action_uri_to_function(name, biv_obj)(biv_obj)

def _parse_path(path):
    """Split the path into the (object, action, path_info) parts."""
    parts = path.split('/', 2)
    biv_uri = parts[0] if len(parts) >= 1 else biv.URI_FOR_NONE
    action = parts[1] if len(parts) >= 2 else _DEFAULT_ACTION_NAME
    path_info = parts[2] if len(parts) >= 3 else None
    return biv.load_obj(biv_uri), action, path_info

def _register_globals():
    """Load globals onto flask's 'g' variable"""
    import publicprize.general.model
    flask.g.pub_obj = publicprize.general.model.General.load_biv_obj(
        publicprize.general.model.PUB_OBJ)

@_app.route("/<path:path>", methods=('GET', 'POST'))
def _route(path):
    """Routes the uri to the appropriate biv_obj"""
    biv_obj, action, path_info = _parse_path(path)
    _register_globals()
    return _dispatch_action(action, biv_obj)

@_app.errorhandler(404)
def _route_404(_):
    """Not found page."""
    return _route(biv.URI_FOR_ERROR + '/' + 'not-found')

@_app.route("/")
def _route_root():
    """Routes to index."""
    return _route('')

@_app.route('/favicon.ico')
def _favicon():
    """Routes to favicon.ico file."""
    return flask.send_from_directory(
        os.path.join(_app.root_path, 'static/img'),
        'favicon.ico', mimetype='image/vnd.microsoft.icon'
    )
<|endoftext|>


<commit_before>##########################################################################
#
#  Copyright 2010 Dr D Studios Pty Limited (ACN 127 184 954) (Dr. D Studios),
#  its affiliates and/or its licensors.
#
#  Copyright (c) 2010-2013, Image Engine Design Inc. All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are
#  met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#
#     * Neither the name of Image Engine Design nor the names of any
#       other contributors to this software may be used to endorse or
#       promote products derived from this software without specific prior
#       written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
#  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import warnings

import hou
import toolutils

import IECore
import IECoreHoudini

class FnParameterisedHolder():

	_nodeType = None

	# create our function set and stash which node we're looking at
	def __init__(self, node=None):
		self.__node = node

	# check this node is still valid
	def nodeValid(self):
		if not self.__node:
			raise "FnParameterisedHolder does not have a node to operate on."
		try:
			p = self.__node.path()
			return True
		except hou.ObjectWasDeleted:
			return False

	# return the node we're currently wrapping
	def node(self):

		return self.__node if self.nodeValid() else None

	@staticmethod
	# nodeType: type of node to create (str)
	# name: desired node name (str)
	# className: class path to op stub (str)
	# version: op version, or None for latest (int)
	# envVarName: environment variable to use as a search path for ops (str)
	# parent: parent node, or None to create a new /obj geo. Ignored if contextArgs is used in UI mode (hou.Node)
	# contextArgs:	args related to the creation context, as would come from UI menu interactions (dict)
	#		If empty or not in UI mode, will create a top level OBJ to house the new holder
	def _doCreate( nodeType, name, className, version=None, envVarName=None, parent=None, contextArgs={} ) :

		if hou.isUIAvailable() and contextArgs.get( "toolname", "" ) :
			holder = toolutils.genericTool( contextArgs, nodeType, nodename = name )
		else :
			parent = parent if parent else hou.node( "/obj" ).createNode( "geo", node_name=name, run_init_scripts=False )
			holder = parent.createNode( nodeType, node_name=name )

		IECoreHoudini.FnParameterisedHolder( holder ).setParameterised( className, version, envVarName )

		if contextArgs.get( "shiftclick", False ) :
			converter = holder.parent().createNode( "ieCortexConverter", node_name = holder.name()+"Converter" )
			outputNode = hou.node( contextArgs.get( "outputnodename", "" ) )
			toolutils.connectInputsAndOutputs( converter, False, holder, outputNode, 0, 0 )
			x, y = holder.position()
			converter.setPosition( [x,y-1] )

		return holder

	# do we have a valid parameterised instance?
	def hasParameterised( self ) :

		return IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).hasParameterised() if self.nodeValid() else False

	# this sets a parameterised object on our node and then updates the parameters
	def setParameterised( self, classNameOrParameterised, classVersion=None, envVarName=None, updateGui=True ) :

		if not self.nodeValid() :
			return

		if isinstance( classNameOrParameterised, str ) :
			if classVersion is None or classVersion < 0 :
				classVersions = IECore.ClassLoader.defaultLoader( envVarName ).versions( classNameOrParameterised )
				classVersion = classVersions[-1] if classVersions else 0
			IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).setParameterised( classNameOrParameterised, classVersion, envVarName )
		else :
			IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).setParameterised( classNameOrParameterised )

		parameterised = self.getParameterised()

		if updateGui and parameterised :
			self.updateParameters( parameterised )

	# this returns the parameterised object our node is working with
	def getParameterised( self ) :

		return IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).getParameterised() if self.hasParameterised() else None

	def setParameterisedValues( self, time = None ) :

		time = hou.time() if time is None else time
		IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).setParameterisedValues( time )

	# get our list of class names based on matchString
	def classNames( self ) :

		if not self.nodeValid() :
			return []

		matchString = self.__node.parm( "__classMatchString" ).eval()
		searchPathEnvVar = self.__node.parm( "__classSearchPathEnvVar" ).eval()
		return IECore.ClassLoader.defaultLoader( searchPathEnvVar ).classNames( matchString )

	# takes a snapshot of the parameter values & expressions on our node so
	# that if we change the procedural/op we can restore the parameters afterwards.
	def cacheParameters(self):
		cached_parameters = {}
		for p in self.__node.parmTuplesInFolder(['Parameters']):
			if p.isSpare():
				data = {}
				data['value'] = p.eval()
				expressions = []
				for i in range(len(p)):
					try:
						expr = p[i].expression()
						lang = p[i].expressionLanguage()
						expressions.append( ( expr, lang ) )
					except:
						expressions.append( ( None, None ) )
				data['expressions'] = expressions
				cached_parameters[p.name()] = data
		return cached_parameters

	# resores parameter values/expressions from those cached by cacheParameters
	def restoreCachedParameters(self, cached):
		for p in self.__node.parmTuplesInFolder(['Parameters']):
			if p.name() in cached:
				cached_data = cached[p.name()]
				p.set( cached_data['value'] )
				for i in range(len(p)):
					if cached_data['expressions'][i][0]:
						expr = cached_data['expressions'][i][0]
						lang = cached_data['expressions'][i][1]
						p[i].setExpression( expr, lang )

	# return the spare parameters under the "Parameters" tab
	def spareParameters( self, tuples=True ) :

		result = []

		for p in self.__node.spareParms() :
			if "Parameters" in p.containingFolders() :
				result.append( p.tuple() if tuples else p )

		return result

	# this method removes all spare parameters from the "Parameters" folder
	def removeParameters( self ) :

		if not self.nodeValid() :
			return

		spareParms = self.spareParameters()
		while spareParms :
			self.__node.removeSpareParmTuple( spareParms[0] )
			# this is needed to account for parms removed by a containing folder
			spareParms = self.spareParameters()

	# add/remove parameters on our node so we correctly reflect our Procedural
	def updateParameters( self, parameterised ) :
		if not self.nodeValid():
			return

		# cache parameters & then remove them
		cached_parameters = self.cacheParameters()
		self.removeParameters()
		if not parameterised:
			return

		# get a list of our parm templates by calling createParm on our top-level CompoundParameter
		# and add them as spare parameter
		parms = IECoreHoudini.ParmTemplates.createParm( parameterised.parameters(), top_level=True )
		parm_names = []
		for p in parms:
			parm_names.append( p['name'] )
			parm = self.__node.addSpareParmTuple( p['tuple'], in_folder=p['folder'], create_missing_folders=True )
			parm.set( p['initialValue'] )

		# restore our cached parameters
		self.restoreCachedParameters( cached_parameters )

		# update the nodes parameter evaluation expression
		# this creates cook dependencies on the parameters
		expr = ""
		for p in parm_names:
			expr += "if parmTuple('%s'):\n\t%s = evalParmTuple('%s')\n" % ( p, p, p )
		expr += "return 1"
		if len(parm_names)==0:
			expr = "1"
		eval_parm = self.__node.parm( "__evaluateParameters" )
		eval_parm.lock(False)
		eval_parm.setExpression( expr, language=hou.exprLanguage.Python, replace_expression=True )
		eval_parm.lock(True)
<commit_msg>Updated toolutil connecting nodes to H16.5<commit_after>##########################################################################
#
#  Copyright 2010 Dr D Studios Pty Limited (ACN 127 184 954) (Dr. D Studios),
#  its affiliates and/or its licensors.
#
#  Copyright (c) 2010-2013, Image Engine Design Inc. All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are
#  met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#
#     * Neither the name of Image Engine Design nor the names of any
#       other contributors to this software may be used to endorse or
#       promote products derived from this software without specific prior
#       written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
#  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import warnings

import hou
import toolutils

import IECore
import IECoreHoudini

class FnParameterisedHolder():

	_nodeType = None

	# create our function set and stash which node we're looking at
	def __init__(self, node=None):
		self.__node = node

	# check this node is still valid
	def nodeValid(self):
		if not self.__node:
			raise "FnParameterisedHolder does not have a node to operate on."
		try:
			p = self.__node.path()
			return True
		except hou.ObjectWasDeleted:
			return False

	# return the node we're currently wrapping
	def node(self):

		return self.__node if self.nodeValid() else None

	@staticmethod
	# nodeType: type of node to create (str)
	# name: desired node name (str)
	# className: class path to op stub (str)
	# version: op version, or None for latest (int)
	# envVarName: environment variable to use as a search path for ops (str)
	# parent: parent node, or None to create a new /obj geo. Ignored if contextArgs is used in UI mode (hou.Node)
	# contextArgs:	args related to the creation context, as would come from UI menu interactions (dict)
	#		If empty or not in UI mode, will create a top level OBJ to house the new holder
	def _doCreate( nodeType, name, className, version=None, envVarName=None, parent=None, contextArgs={} ) :

		if hou.isUIAvailable() and contextArgs.get( "toolname", "" ) :
			holder = toolutils.genericTool( contextArgs, nodeType, nodename = name )
		else :
			parent = parent if parent else hou.node( "/obj" ).createNode( "geo", node_name=name, run_init_scripts=False )
			holder = parent.createNode( nodeType, node_name=name )

		IECoreHoudini.FnParameterisedHolder( holder ).setParameterised( className, version, envVarName )

		if contextArgs.get( "shiftclick", False ) :
			converter = holder.parent().createNode( "ieCortexConverter", node_name = holder.name()+"Converter" )
			outputNode = hou.node( contextArgs.get( "outputnodename", "" ) )
			if hasattr(toolutils, "connectMultiInputsAndOutputs"):
				toolutils.connectMultiInputsAndOutputs( converter, False, [( holder, 0, 0 )] if holder else None, [( outputNode, 0, 0 )] if outputNode else None )
			else:
				toolutils.connectInputsAndOutputs( converter, False, holder, outputNode, 0, 0 )
			x, y = holder.position()
			converter.setPosition( [x,y-1] )

		return holder

	# do we have a valid parameterised instance?
	def hasParameterised( self ) :

		return IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).hasParameterised() if self.nodeValid() else False

	# this sets a parameterised object on our node and then updates the parameters
	def setParameterised( self, classNameOrParameterised, classVersion=None, envVarName=None, updateGui=True ) :

		if not self.nodeValid() :
			return

		if isinstance( classNameOrParameterised, str ) :
			if classVersion is None or classVersion < 0 :
				classVersions = IECore.ClassLoader.defaultLoader( envVarName ).versions( classNameOrParameterised )
				classVersion = classVersions[-1] if classVersions else 0
			IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).setParameterised( classNameOrParameterised, classVersion, envVarName )
		else :
			IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).setParameterised( classNameOrParameterised )

		parameterised = self.getParameterised()

		if updateGui and parameterised :
			self.updateParameters( parameterised )

	# this returns the parameterised object our node is working with
	def getParameterised( self ) :

		return IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).getParameterised() if self.hasParameterised() else None

	def setParameterisedValues( self, time = None ) :

		time = hou.time() if time is None else time
		IECoreHoudini._IECoreHoudini._FnParameterisedHolder( self.node() ).setParameterisedValues( time )

	# get our list of class names based on matchString
	def classNames( self ) :

		if not self.nodeValid() :
			return []

		matchString = self.__node.parm( "__classMatchString" ).eval()
		searchPathEnvVar = self.__node.parm( "__classSearchPathEnvVar" ).eval()
		return IECore.ClassLoader.defaultLoader( searchPathEnvVar ).classNames( matchString )

	# takes a snapshot of the parameter values & expressions on our node so
	# that if we change the procedural/op we can restore the parameters afterwards.
	def cacheParameters(self):
		cached_parameters = {}
		for p in self.__node.parmTuplesInFolder(['Parameters']):
			if p.isSpare():
				data = {}
				data['value'] = p.eval()
				expressions = []
				for i in range(len(p)):
					try:
						expr = p[i].expression()
						lang = p[i].expressionLanguage()
						expressions.append( ( expr, lang ) )
					except:
						expressions.append( ( None, None ) )
				data['expressions'] = expressions
				cached_parameters[p.name()] = data
		return cached_parameters

	# resores parameter values/expressions from those cached by cacheParameters
	def restoreCachedParameters(self, cached):
		for p in self.__node.parmTuplesInFolder(['Parameters']):
			if p.name() in cached:
				cached_data = cached[p.name()]
				p.set( cached_data['value'] )
				for i in range(len(p)):
					if cached_data['expressions'][i][0]:
						expr = cached_data['expressions'][i][0]
						lang = cached_data['expressions'][i][1]
						p[i].setExpression( expr, lang )

	# return the spare parameters under the "Parameters" tab
	def spareParameters( self, tuples=True ) :

		result = []

		for p in self.__node.spareParms() :
			if "Parameters" in p.containingFolders() :
				result.append( p.tuple() if tuples else p )

		return result

	# this method removes all spare parameters from the "Parameters" folder
	def removeParameters( self ) :

		if not self.nodeValid() :
			return

		spareParms = self.spareParameters()
		while spareParms :
			self.__node.removeSpareParmTuple( spareParms[0] )
			# this is needed to account for parms removed by a containing folder
			spareParms = self.spareParameters()

	# add/remove parameters on our node so we correctly reflect our Procedural
	def updateParameters( self, parameterised ) :
		if not self.nodeValid():
			return

		# cache parameters & then remove them
		cached_parameters = self.cacheParameters()
		self.removeParameters()
		if not parameterised:
			return

		# get a list of our parm templates by calling createParm on our top-level CompoundParameter
		# and add them as spare parameter
		parms = IECoreHoudini.ParmTemplates.createParm( parameterised.parameters(), top_level=True )
		parm_names = []
		for p in parms:
			parm_names.append( p['name'] )
			parm = self.__node.addSpareParmTuple( p['tuple'], in_folder=p['folder'], create_missing_folders=True )
			parm.set( p['initialValue'] )

		# restore our cached parameters
		self.restoreCachedParameters( cached_parameters )

		# update the nodes parameter evaluation expression
		# this creates cook dependencies on the parameters
		expr = ""
		for p in parm_names:
			expr += "if parmTuple('%s'):\n\t%s = evalParmTuple('%s')\n" % ( p, p, p )
		expr += "return 1"
		if len(parm_names)==0:
			expr = "1"
		eval_parm = self.__node.parm( "__evaluateParameters" )
		eval_parm.lock(False)
		eval_parm.setExpression( expr, language=hou.exprLanguage.Python, replace_expression=True )
		eval_parm.lock(True)
<|endoftext|>


<commit_before>"""
fs.mountfs
==========

Contains MountFS class which is a virtual Filesystem which can have other Filesystems linked as branched directories, much like a symlink in Linux

"""

from fs.base import *
from fs.objecttree import ObjectTree
from fs import _thread_synchronize_default

class DirMount(object):
    def __init__(self, path, fs):
        self.path = path
        self.fs = fs

    def __str__(self):
        return "Mount point: %s"%self.path

class FileMount(object):
    def __init__(self, path, open_callable, info_callable=None):
        self.open_callable = open_callable
        def no_info_callable(path):
            return {}
        self.info_callable = info_callable or no_info_callable

class MountFS(FS):
    """A filesystem that delegates to other filesystems."""

    DirMount = DirMount
    FileMount = FileMount

    def __init__(self, thread_synchronize=_thread_synchronize_default):
        super(MountFS, self).__init__(thread_synchronize=thread_synchronize)
        self.mount_tree = ObjectTree()

    def __str__(self):
        return "<MountFS>"

    __repr__ = __str__

    def __unicode__(self):
        return unicode(self.__str__())

    def _delegate(self, path):
        path = normpath(path)
        head_path, object, tail_path = self.mount_tree.partialget(path)

        if type(object) is MountFS.DirMount:
            dirmount = object
            return dirmount.fs, head_path, tail_path

        if object is None:
            return None, None, None

        return self, head_path, tail_path

    def getsyspath(self, path, allow_none=False):
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is self:
            if allow_none:
                return None
            else:
                raise NoSysPathError(path=path)
        return fs.getsyspath(delegate_path, allow_none=allow_none)

    @synchronize
    def desc(self, path):
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is self:
            if fs.isdir(path):
                return "Mount dir"
            else:
                return "Mounted file"
        return "Mounted dir, maps to path %s on %s" % (delegate_path, str(fs))

    @synchronize
    def isdir(self, path):
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            return False
        if fs is self:
            object = self.mount_tree.get(path, None)
            return isinstance(object, dict)
        else:
            return fs.isdir(delegate_path)

    @synchronize
    def isfile(self, path):
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            return False
        if fs is self:
            object = self.mount_tree.get(path, None)
            return type(object) is MountFS.FileMount
        else:
            return fs.isfile(delegate_path)

    @synchronize
    def listdir(self, path="/", wildcard=None, full=False, absolute=False, dirs_only=False, files_only=False):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None:
            raise ResourceNotFoundError(path)

        if fs is self:
            if files_only:
                return []

            paths = self.mount_tree[path].keys()
            return self._listdir_helper(path,
                                        paths,
                                        wildcard,
                                        full,
                                        absolute,
                                        dirs_only,
                                        files_only)
        else:
            paths = fs.listdir(delegate_path,
                               wildcard=wildcard,
                               full=False,
                               absolute=False,
                               dirs_only=dirs_only,
                               files_only=files_only)
            if full or absolute:
                if full:
                    path = abspath(normpath(path))
                else:
                    path = relpath(normpath(path))
                paths = [pathjoin(path, p) for p in paths]

            return paths

    @synchronize
    def makedir(self, path, recursive=False, allow_recreate=False):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is self:
            raise UnsupportedError("make directory", msg="Can only makedir for mounted paths" )
        if not delegate_path:
            return True
        return fs.makedir(delegate_path, recursive=recursive, allow_recreate=allow_recreate)

    @synchronize
    def open(self, path, mode="r", **kwargs):
        path = normpath(path)
        object = self.mount_tree.get(path, None)
        if type(object) is MountFS.FileMount:
            callable = object.open_callable
            return callable(path, mode, **kwargs)

        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None:
            raise ResourceNotFoundError(path)

        return fs.open(delegate_path, mode, **kwargs)

    @synchronize
    def setcontents(self, path, contents):
        path = normpath(path)
        object = self.mount_tree.get(path, None)
        if type(object) is MountFS.FileMount:
            return super(MountFS,self).setcontents(path,contents)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ParentDirectoryMissingError(path)
        return fs.setcontents(delegate_path,contents)

    @synchronize
    def exists(self, path):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            return False
        if fs is self:
            return path in self.mount_tree
        return fs.exists(delegate_path)

    @synchronize
    def remove(self, path):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            raise UnsupportedError("remove file", msg="Can only remove paths within a mounted dir")
        return fs.remove(delegate_path)

    @synchronize
    def removedir(self, path, recursive=False, force=False):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None or fs is self:
            raise ResourceInvalidError(path, msg="Can not removedir for an un-mounted path")

        if not force and not fs.isdirempty(delegate_path):
            raise DirectoryNotEmptyError("Directory is not empty: %(path)s")

        return fs.removedir(delegate_path, recursive, force)

    @synchronize
    def rename(self, src, dst):
        fs1, mount_path1, delegate_path1 = self._delegate(src)
        fs2, mount_path2, delegate_path2 = self._delegate(dst)

        if fs1 is not fs2:
            raise OperationFailedError("rename resource", path=src)

        if fs1 is not self:
            return fs1.rename(delegate_path1, delegate_path2)

        path_src = normpath(src)
        path_dst = normpath(dst)

        object = self.mount_tree.get(path_src, None)
        object2 = self.mount_tree.get(path_dst, None)

        if object1 is None:
            raise ResourceNotFoundError(src)

        # TODO!
        raise UnsupportedError("rename resource", path=src)

    @synchronize
    def mountdir(self, path, fs):
        """Mounts a host FS object on a given path.

        :param path: A path within the MountFS
        :param fs: A filesystem object to mount

        """
        path = normpath(path)
        self.mount_tree[path] = MountFS.DirMount(path, fs)
    mount = mountdir

    @synchronize
    def mountfile(self, path, open_callable=None, info_callable=None):
        """Mounts a single file path. """
        path = normpath(path)
        self.mount_tree[path] = MountFS.FileMount(path, callable, info_callable)

    @synchronize
    def unmount(self, path):
        """Unmounds a path.

        :param path: Path to unmount

        """
        path = normpath(path)
        del self.mount_tree[path]

    @synchronize
    def getinfo(self, path):
        path = normpath(path)

        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None:
            raise ResourceNotFoundError(path)

        if fs is self:
            if self.isfile(path):
                return self.mount_tree[path].info_callable(path)
            return {}
        return fs.getinfo(delegate_path)

    @synchronize
    def getsize(self, path):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None:
            raise ResourceNotFoundError(path)

        if fs is self:
            object = self.mount_tree.get(path, None)

            if object is None or isinstance(object, dict):
                raise ResourceNotFoundError(path)

            size = self.mount_tree[path].info_callable(path).get("size", None)
            return size

        return fs.getinfo(delegate_path).get("size", None)

    @synchronize
    def getxattr(self,path,name,default=None):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            return default
        return fs.getxattr(delegate_path,name,default)

    @synchronize
    def setxattr(self,path,name,value):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            raise UnsupportedError("setxattr")
        return fs.setxattr(delegate_path,name,value)

    @synchronize
    def delxattr(self,path,name):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            return True
        return fs.delxattr(delegate_path,name)

    @synchronize
    def listxattrs(self,path):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            return []
        return fs.listxattrs(delegate_path)
<commit_msg>MountFS:  fast-path copy/move/copydir/movedir if src and dst are in same FS<commit_after>"""
fs.mountfs
==========

Contains MountFS class which is a virtual Filesystem which can have other Filesystems linked as branched directories, much like a symlink in Linux

"""

from fs.base import *
from fs.objecttree import ObjectTree
from fs import _thread_synchronize_default

class DirMount(object):
    def __init__(self, path, fs):
        self.path = path
        self.fs = fs

    def __str__(self):
        return "Mount point: %s"%self.path

class FileMount(object):
    def __init__(self, path, open_callable, info_callable=None):
        self.open_callable = open_callable
        def no_info_callable(path):
            return {}
        self.info_callable = info_callable or no_info_callable

class MountFS(FS):
    """A filesystem that delegates to other filesystems."""

    DirMount = DirMount
    FileMount = FileMount

    def __init__(self, thread_synchronize=_thread_synchronize_default):
        super(MountFS, self).__init__(thread_synchronize=thread_synchronize)
        self.mount_tree = ObjectTree()

    def __str__(self):
        return "<MountFS>"

    __repr__ = __str__

    def __unicode__(self):
        return unicode(self.__str__())

    def _delegate(self, path):
        path = normpath(path)
        head_path, object, tail_path = self.mount_tree.partialget(path)

        if type(object) is MountFS.DirMount:
            dirmount = object
            return dirmount.fs, head_path, tail_path

        if object is None:
            return None, None, None

        return self, head_path, tail_path

    def getsyspath(self, path, allow_none=False):
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is self:
            if allow_none:
                return None
            else:
                raise NoSysPathError(path=path)
        return fs.getsyspath(delegate_path, allow_none=allow_none)

    @synchronize
    def desc(self, path):
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is self:
            if fs.isdir(path):
                return "Mount dir"
            else:
                return "Mounted file"
        return "Mounted dir, maps to path %s on %s" % (delegate_path, str(fs))

    @synchronize
    def isdir(self, path):
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            return False
        if fs is self:
            object = self.mount_tree.get(path, None)
            return isinstance(object, dict)
        else:
            return fs.isdir(delegate_path)

    @synchronize
    def isfile(self, path):
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            return False
        if fs is self:
            object = self.mount_tree.get(path, None)
            return type(object) is MountFS.FileMount
        else:
            return fs.isfile(delegate_path)

    @synchronize
    def listdir(self, path="/", wildcard=None, full=False, absolute=False, dirs_only=False, files_only=False):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None:
            raise ResourceNotFoundError(path)

        if fs is self:
            if files_only:
                return []

            paths = self.mount_tree[path].keys()
            return self._listdir_helper(path,
                                        paths,
                                        wildcard,
                                        full,
                                        absolute,
                                        dirs_only,
                                        files_only)
        else:
            paths = fs.listdir(delegate_path,
                               wildcard=wildcard,
                               full=False,
                               absolute=False,
                               dirs_only=dirs_only,
                               files_only=files_only)
            if full or absolute:
                if full:
                    path = abspath(normpath(path))
                else:
                    path = relpath(normpath(path))
                paths = [pathjoin(path, p) for p in paths]

            return paths

    @synchronize
    def makedir(self, path, recursive=False, allow_recreate=False):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is self:
            raise UnsupportedError("make directory", msg="Can only makedir for mounted paths" )
        if not delegate_path:
            return True
        return fs.makedir(delegate_path, recursive=recursive, allow_recreate=allow_recreate)

    @synchronize
    def open(self, path, mode="r", **kwargs):
        path = normpath(path)
        object = self.mount_tree.get(path, None)
        if type(object) is MountFS.FileMount:
            callable = object.open_callable
            return callable(path, mode, **kwargs)

        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None:
            raise ResourceNotFoundError(path)

        return fs.open(delegate_path, mode, **kwargs)

    @synchronize
    def setcontents(self, path, contents):
        path = normpath(path)
        object = self.mount_tree.get(path, None)
        if type(object) is MountFS.FileMount:
            return super(MountFS,self).setcontents(path,contents)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ParentDirectoryMissingError(path)
        return fs.setcontents(delegate_path,contents)

    @synchronize
    def exists(self, path):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            return False
        if fs is self:
            return path in self.mount_tree
        return fs.exists(delegate_path)

    @synchronize
    def remove(self, path):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            raise UnsupportedError("remove file", msg="Can only remove paths within a mounted dir")
        return fs.remove(delegate_path)

    @synchronize
    def removedir(self, path, recursive=False, force=False):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None or fs is self:
            raise ResourceInvalidError(path, msg="Can not removedir for an un-mounted path")

        if not force and not fs.isdirempty(delegate_path):
            raise DirectoryNotEmptyError("Directory is not empty: %(path)s")

        return fs.removedir(delegate_path, recursive, force)

    @synchronize
    def rename(self, src, dst):
        fs1, mount_path1, delegate_path1 = self._delegate(src)
        fs2, mount_path2, delegate_path2 = self._delegate(dst)

        if fs1 is not fs2:
            raise OperationFailedError("rename resource", path=src)

        if fs1 is not self:
            return fs1.rename(delegate_path1, delegate_path2)

        path_src = normpath(src)
        path_dst = normpath(dst)

        object = self.mount_tree.get(path_src, None)
        object2 = self.mount_tree.get(path_dst, None)

        if object1 is None:
            raise ResourceNotFoundError(src)

        # TODO!
        raise UnsupportedError("rename resource", path=src)

    @synchronize
    def move(self,src,dst,**kwds):
        fs1, mount_path1, delegate_path1 = self._delegate(src)
        fs2, mount_path2, delegate_path2 = self._delegate(dst)
        if fs1 is fs2 and fs1 is not self:
            fs1.move(delegate_path1,delegate_path2,**kwds)
        else:
            super(MountFS,self).move(src,dst,**kwds)

    @synchronize
    def movedir(self,src,dst,**kwds):
        fs1, mount_path1, delegate_path1 = self._delegate(src)
        fs2, mount_path2, delegate_path2 = self._delegate(dst)
        if fs1 is fs2 and fs1 is not self:
            fs1.movedir(delegate_path1,delegate_path2,**kwds)
        else:
            super(MountFS,self).movedir(src,dst,**kwds)

    @synchronize
    def copy(self,src,dst,**kwds):
        fs1, mount_path1, delegate_path1 = self._delegate(src)
        fs2, mount_path2, delegate_path2 = self._delegate(dst)
        if fs1 is fs2 and fs1 is not self:
            fs1.copy(delegate_path1,delegate_path2,**kwds)
        else:
            super(MountFS,self).copy(src,dst,**kwds)

    @synchronize
    def copydir(self,src,dst,**kwds):
        fs1, mount_path1, delegate_path1 = self._delegate(src)
        fs2, mount_path2, delegate_path2 = self._delegate(dst)
        if fs1 is fs2 and fs1 is not self:
            fs1.copydir(delegate_path1,delegate_path2,**kwds)
        else:
            super(MountFS,self).copydir(src,dst,**kwds)

    @synchronize
    def mountdir(self, path, fs):
        """Mounts a host FS object on a given path.

        :param path: A path within the MountFS
        :param fs: A filesystem object to mount

        """
        path = normpath(path)
        self.mount_tree[path] = MountFS.DirMount(path, fs)
    mount = mountdir

    @synchronize
    def mountfile(self, path, open_callable=None, info_callable=None):
        """Mounts a single file path. """
        path = normpath(path)
        self.mount_tree[path] = MountFS.FileMount(path, callable, info_callable)

    @synchronize
    def unmount(self, path):
        """Unmounds a path.

        :param path: Path to unmount

        """
        path = normpath(path)
        del self.mount_tree[path]

    @synchronize
    def getinfo(self, path):
        path = normpath(path)

        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None:
            raise ResourceNotFoundError(path)

        if fs is self:
            if self.isfile(path):
                return self.mount_tree[path].info_callable(path)
            return {}
        return fs.getinfo(delegate_path)

    @synchronize
    def getsize(self, path):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)

        if fs is None:
            raise ResourceNotFoundError(path)

        if fs is self:
            object = self.mount_tree.get(path, None)

            if object is None or isinstance(object, dict):
                raise ResourceNotFoundError(path)

            size = self.mount_tree[path].info_callable(path).get("size", None)
            return size

        return fs.getinfo(delegate_path).get("size", None)

    @synchronize
    def getxattr(self,path,name,default=None):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            return default
        return fs.getxattr(delegate_path,name,default)

    @synchronize
    def setxattr(self,path,name,value):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            raise UnsupportedError("setxattr")
        return fs.setxattr(delegate_path,name,value)

    @synchronize
    def delxattr(self,path,name):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            return True
        return fs.delxattr(delegate_path,name)

    @synchronize
    def listxattrs(self,path):
        path = normpath(path)
        fs, mount_path, delegate_path = self._delegate(path)
        if fs is None:
            raise ResourceNotFoundError(path)
        if fs is self:
            return []
        return fs.listxattrs(delegate_path)
<|endoftext|>


<commit_before>from panoptes_client.panoptes import PanoptesObject, LinkResolver
from panoptes_client.subject import Subject
from panoptes_client.subject_set import SubjectSet

class Workflow(PanoptesObject):
    _api_slug = 'workflows'
    _link_slug = 'workflows'
    _edit_attributes = []

    def retire_subjects(self, subjects, reason='other'):
        if type(subjects) not in (list, tuple, set):
            subjects = [ subjects ]
        subjects = [ s.id if isinstance(s, Subject) else s for s in subjects ]

        return Workflow.post(
            '{}/retired_subjects'.format(self.id),
            json={
                'subject_ids': subjects,
                'retirement_reason': reason
            }
        )

    def add_subject_sets(self, subject_sets, batch_size=100):
        _subject_sets = self._build_subject_set_list(subject_sets)

        for _subject_sets_batch in [
            _subject_sets[i:i+batch_size]
            for i in xrange(0, len(_subject_sets), batch_size)
        ]:
            self.post(
                '{}/links/subject_sets'.format(self.id),
                json={'subject_sets': _subject_sets_batch}
            )

    def remove_subject_sets(self, subject_sets):
        _subject_sets = self._build_subject_set_list(subject_sets)
        _subject_set_ids = ",".join(_subject_sets)

        self.delete(
            '{}/links/subject_sets/{}'.format(self.id, _subject_set_ids)
        )

    def _build_subject_set_list(self, subject_sets):
        if not type(subject_sets) in (tuple, list, set):
            subject_sets = [subject_sets]

        _subject_sets = []
        for subject_set in subject_sets:
            if not (
                isinstance(subject_set, SubjectSet)
                or isinstance(subject_set, (int, str, unicode,))
            ):
                raise TypeError

            if isinstance(subject_set, SubjectSet):
                _subject_set_id = subject_set.id
            else:
                _subject_set_id = str(subject_set)

            _subject_sets.append(_subject_set_id)

        return _subject_sets

LinkResolver.register(Workflow)
<commit_msg>Added editable attributes to workflow.py allowing editing of workflow objects<commit_after>from panoptes_client.panoptes import PanoptesObject, LinkResolver
from panoptes_client.subject import Subject
from panoptes_client.subject_set import SubjectSet

class Workflow(PanoptesObject):
    _api_slug = 'workflows'
    _link_slug = 'workflows'
    _edit_attributes = ['tasks', 'first_task', 'configuration']

    def retire_subjects(self, subjects, reason='other'):
        if type(subjects) not in (list, tuple, set):
            subjects = [ subjects ]
        subjects = [ s.id if isinstance(s, Subject) else s for s in subjects ]

        return Workflow.post(
            '{}/retired_subjects'.format(self.id),
            json={
                'subject_ids': subjects,
                'retirement_reason': reason
            }
        )

    def add_subject_sets(self, subject_sets, batch_size=100):
        _subject_sets = self._build_subject_set_list(subject_sets)

        for _subject_sets_batch in [
            _subject_sets[i:i+batch_size]
            for i in xrange(0, len(_subject_sets), batch_size)
        ]:
            self.post(
                '{}/links/subject_sets'.format(self.id),
                json={'subject_sets': _subject_sets_batch}
            )

    def remove_subject_sets(self, subject_sets):
        _subject_sets = self._build_subject_set_list(subject_sets)
        _subject_set_ids = ",".join(_subject_sets)

        self.delete(
            '{}/links/subject_sets/{}'.format(self.id, _subject_set_ids)
        )

    def _build_subject_set_list(self, subject_sets):
        if not type(subject_sets) in (tuple, list, set):
            subject_sets = [subject_sets]

        _subject_sets = []
        for subject_set in subject_sets:
            if not (
                isinstance(subject_set, SubjectSet)
                or isinstance(subject_set, (int, str, unicode,))
            ):
                raise TypeError

            if isinstance(subject_set, SubjectSet):
                _subject_set_id = subject_set.id
            else:
                _subject_set_id = str(subject_set)

            _subject_sets.append(_subject_set_id)

        return _subject_sets

LinkResolver.register(Workflow)
<|endoftext|>


<commit_before>#!/usr/bin/env python3

import os
import subprocess
from uuid import uuid4

ACCRE_JOB_TEMPLATE = """\
#!/bin/bash

#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=1
#SBATCH --mem=1G
#SBATCH --time=02:00:00
#SBATCH --job-name=pcreo

module load Anaconda3

PARAM_S=<|PARAM_S|>
PARAM_D=<|PARAM_D|>
PARAM_N=<|PARAM_N|>

mkdir /gpfs23/scratch/zhangdk/pcreo_runs/output_data_${SLURM_JOBID}
cd /gpfs23/scratch/zhangdk/pcreo_runs/output_data_${SLURM_JOBID}
/home/zhangdk/pcreo/compile.py ./pcreo_sphere_exe /home/zhangdk/pcreo/src/pcreo_sphere.f90 \
PCREO_DOUBLE_PREC PCREO_PARAM_S=${PARAM_S}_rk PCREO_PARAM_D=${PARAM_D} PCREO_PARAM_N=${PARAM_N}
./pcreo_sphere_exe
rm ./pcreo_sphere_exe
/home/zhangdk/pcreo/out2in.py
/home/zhangdk/pcreo/compile.py ./pcreo_sphere_exe /home/zhangdk/pcreo/src/pcreo_sphere.f90 \
PCREO_QUAD_PREC PCREO_PARAM_S=${PARAM_S}_rk PCREO_PARAM_D=${PARAM_D} PCREO_PARAM_N=${PARAM_N}
./pcreo_sphere_exe
rm ./pcreo_sphere_exe
/home/zhangdk/pcreo/out2in.py
/home/zhangdk/pcreo/compile.py ./pcreo_sphere_exe /home/zhangdk/pcreo/src/pcreo_sphere.f90 \
PCREO_QUAD_PREC PCREO_GRAD_DESC PCREO_PARAM_S=${PARAM_S}_rk PCREO_PARAM_D=${PARAM_D} PCREO_PARAM_N=${PARAM_N}
./pcreo_sphere_exe
rm ./pcreo_sphere_exe
/home/zhangdk/pcreo/out2in.py
/home/zhangdk/pcreo/compile.py ./pcreo_sphere_exe /home/zhangdk/pcreo/src/pcreo_sphere.f90 \
PCREO_QUAD_PREC PCREO_GRAD_DESC PCREO_PARAM_S=${PARAM_S}_rk PCREO_PARAM_D=${PARAM_D} PCREO_PARAM_N=${PARAM_N}
./pcreo_sphere_exe
rm ./pcreo_sphere_exe
/home/zhangdk/pcreo/out2in.py
echo "PCreo job successfully completed"
"""

def submit_job(s, d, n):
    s = float(s)
    d = int(d)
    n = int(n)
    script_name = str(uuid4()) + '.sh'
    with open(script_name, 'w+') as script_file:
        script_file.write(ACCRE_JOB_TEMPLATE.replace(
            '<|PARAM_S|>', str(s)).replace(
            '<|PARAM_D|>', str(d)).replace(
            '<|PARAM_N|>', str(n)))
    subprocess.run(['sbatch', script_name])
    os.remove(script_name)

for _ in range(20):
    submit_job(2.0, 3, 100)
<commit_msg>Add period<commit_after>#!/usr/bin/env python3

import os
import subprocess
from uuid import uuid4

ACCRE_JOB_TEMPLATE = """\
#!/bin/bash

#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=1
#SBATCH --mem=1G
#SBATCH --time=02:00:00
#SBATCH --job-name=pcreo

module load Anaconda3

PARAM_S=<|PARAM_S|>
PARAM_D=<|PARAM_D|>
PARAM_N=<|PARAM_N|>

mkdir /gpfs23/scratch/zhangdk/pcreo_runs/output_data_${SLURM_JOBID}
cd /gpfs23/scratch/zhangdk/pcreo_runs/output_data_${SLURM_JOBID}
/home/zhangdk/pcreo/compile.py ./pcreo_sphere_exe /home/zhangdk/pcreo/src/pcreo_sphere.f90 \
PCREO_DOUBLE_PREC PCREO_PARAM_S=${PARAM_S}_rk PCREO_PARAM_D=${PARAM_D} PCREO_PARAM_N=${PARAM_N}
./pcreo_sphere_exe
rm ./pcreo_sphere_exe
/home/zhangdk/pcreo/out2in.py
/home/zhangdk/pcreo/compile.py ./pcreo_sphere_exe /home/zhangdk/pcreo/src/pcreo_sphere.f90 \
PCREO_QUAD_PREC PCREO_PARAM_S=${PARAM_S}_rk PCREO_PARAM_D=${PARAM_D} PCREO_PARAM_N=${PARAM_N}
./pcreo_sphere_exe
rm ./pcreo_sphere_exe
/home/zhangdk/pcreo/out2in.py
/home/zhangdk/pcreo/compile.py ./pcreo_sphere_exe /home/zhangdk/pcreo/src/pcreo_sphere.f90 \
PCREO_QUAD_PREC PCREO_GRAD_DESC PCREO_PARAM_S=${PARAM_S}_rk PCREO_PARAM_D=${PARAM_D} PCREO_PARAM_N=${PARAM_N}
./pcreo_sphere_exe
rm ./pcreo_sphere_exe
/home/zhangdk/pcreo/out2in.py
/home/zhangdk/pcreo/compile.py ./pcreo_sphere_exe /home/zhangdk/pcreo/src/pcreo_sphere.f90 \
PCREO_QUAD_PREC PCREO_GRAD_DESC PCREO_PARAM_S=${PARAM_S}_rk PCREO_PARAM_D=${PARAM_D} PCREO_PARAM_N=${PARAM_N}
./pcreo_sphere_exe
rm ./pcreo_sphere_exe
/home/zhangdk/pcreo/out2in.py
echo "PCreo job successfully completed."
"""

def submit_job(s, d, n):
    s = float(s)
    d = int(d)
    n = int(n)
    script_name = str(uuid4()) + '.sh'
    with open(script_name, 'w+') as script_file:
        script_file.write(ACCRE_JOB_TEMPLATE.replace(
            '<|PARAM_S|>', str(s)).replace(
            '<|PARAM_D|>', str(d)).replace(
            '<|PARAM_N|>', str(n)))
    subprocess.run(['sbatch', script_name])
    os.remove(script_name)

for _ in range(20):
    submit_job(2.0, 3, 100)
<|endoftext|>