示例#1
0
 def __init__(self, dir, permissions=0, create=False):
     self.directory = full_path(dir)
     if create:
         if not os.path.exists(self.directory):
             os.makedirs(self.directory)
     if not os.path.isdir(self.directory):
         raise OSError("{0} is not a directory.")
     elif not os.access(self.directory, os.R_OK|permissions):
         raise OSError("directory {0} cannot be accessed with sufficient permissions")
示例#2
0
 def __init__(self, dir, permissions=0, create=False):
     self.directory = full_path(dir)
     if create:
         if not os.path.exists(self.directory):
             os.makedirs(self.directory)
     if not os.path.isdir(self.directory):
         raise OSError("{0} is not a directory.")
     elif not os.access(self.directory, os.R_OK | permissions):
         raise OSError(
             "directory {0} cannot be accessed with sufficient permissions")
示例#3
0
 def __enter__(self):
     self.return_directory = full_path(os.curdir)
     os.chdir(self.directory)
示例#4
0
 def __new__(cls, **kwargs):
     """
     """
     def get_kwarg(arg, cls, subclass=False):
         gotten = pop_kwarg(kwargs, arg)
         if not subclass:
             if gotten is not None and not isinstance(gotten, cls):
                 if not isinstance(cls, tuple):
                     raise TypeError("#{0} argument given to Computation() "\
                                     "must be an instance of the #{1} class.".format(arg, classname(cls)))
                 else:
                     raise TypeError("#{0} argument given to Computation() "\
                                     "must be one of (#{1}) .".format(arg, ', '.join(classname(cl) for cl in cls)))
         else:
             if gotten is not None and not issubclass(gotten, cls):
                 if not isinstance(cls, tuple):
                     raise TypeError("#{0} argument given to Computation() "\
                                     "must be an subclass of the #{1} class.".format(arg, classname(cls)))
                 else:
                     raise TypeError("#{0} argument given to Computation() "\
                                     "must be subclass of one of (#{1}) .".format(arg, ', '.join(classname(cl) for cl in cls)))
         return gotten
     #--------------------------------------------------------------------------------#
     # Handle molecule, make a ResultGetter
     molecule = get_kwarg('molecule', Molecule)
     res_getter = get_kwarg('result_getter', ComputationResultGetter)
     if res_getter is None:
         res_getter = ComputationResultGetter(**kwargs)
         molecule.result_getters.append(res_getter)
     #--------------------------------------------------------------------------------#
     # Now see what package we're using
     package = get_kwarg('package', (basestring, PackageInterface))
     comp_class = cls
     interface = None
     if isinstance(package, PackageInterface):
         interface = package
     elif isinstance(package, basestring):
         interface = PackageInterface.load_package(
                         package,
                         input_generator=get_kwarg('input_generator', InputGenerator, True),
                         runner=get_kwarg('runner', Runner, True),
                         output_parser=get_kwarg('output_parser', OutputParser, True),
                         details_class=get_kwarg('details_class', ComputationDetails, True),
                         computation_class=get_kwarg('computation_class', cls, True)
                     )
     if interface.computation_class is not None:
         comp_class = cls
     ret_val = object.__new__(comp_class)
     #--------------------------------------------------------------------------------#
     ret_val.molecule = molecule
     res_getter.add_computation(ret_val)
     ret_val.input_generator = interface.input_generator(ret_val)
     ret_val.output_parser = interface.output_parser(ret_val)
     #TODO accept option for directory to put input/output files in
     #TODO accept option for input/output filenames
     #TODO support for runners that don't follow the input/output pattern
     ret_val.runner = interface.runner(input_file='input.dat', output_file='output.dat')
     #--------------------------------------------------------------------------------#
     ret_val.details = get_kwarg('details', interface.details_class)
     ret_val.properties = pop_kwarg(kwargs, 'property')
     if isinstance(ret_val.properties, Iterable):
         ret_val.properties = list(ret_val.properties)
     else:
         ret_val.properties = [ret_val.properties]
     if not all(issubclass(prop, MolecularProperty) or isinstance(prop, MolecularProperty) for prop in ret_val.properties):
         raise TypeError("property argument given to Computation() must be a list of MolecularProperty subclasses or instances.".format(classname(cls)))
     fixed_properties = []
     for prop in ret_val.properties:
         if isinstance(prop, MolecularProperty):
             fixed_properties.append(prop)
             prop.details = ret_val.details
         elif issubclass(prop, MolecularProperty):
             fixed_properties.append(prop(molecule=ret_val.molecule, details=ret_val.details))
     ret_val.properties = fixed_properties
     #--------------------------------------------------------------------------------#
     # Get input_filename and output_filename, if specified.  Make sure that neither
     #   is a path.
     # first get input_filename
     input_filename = pop_kwarg(kwargs, 'input_filename')
     if input_filename:
         if os.path.split(input_filename)[0] != '':
             raise ValueError("File name '{0}' given for argument 'input_filename' of Computation constructor "
                              "must be a single file, not a path.  Use the 'directory' argument to specify "
                              "a directory.".format(input_filename))
         ret_val.runner.input_file = input_filename
     else:
         ret_val.runner.input_file = Runner.default_input_filename
     #----------------------------------------#
     # now get output_filename
     output_filename = pop_kwarg(kwargs, 'output_filename')
     if output_filename:
         if os.path.split(output_filename)[0] != '':
             raise ValueError("File name '{0}' given for argument 'output_filename' of Computation constructor "
                              "must be a single file, not a path.  Use the 'directory' argument to specify "
                              "a directory.".format(output_filename))
         ret_val.runner.output_file = output_filename
     else:
         ret_val.runner.output_file = Runner.default_output_filename
     #--------------------------------------------------------------------------------#
     # Find out the desired directory and make new ones if necessary and allowed.
     ret_val.directory = pop_kwarg(kwargs, 'directory')
     used_template = False
     if ret_val.directory is not None:
         ret_val.directory = full_path(ret_val.directory)
     elif cls.directory_template is not None:
         ret_val.directory = cls.directory_template
         used_template = True
     else:
         ret_val.directory = full_path(os.curdir)
     #----------------------------------------#
     # Do mako-template style replacement, if the user has mako
     try:
         from mako.template import Template
         from mako import exceptions
         # Start with some obvious standard things to add...
         variables = dict(
             mol = ret_val.molecule, molecule = ret_val.molecule,
             calc = ret_val, calculation = ret_val,
             rg = res_getter, result_getter = res_getter,
             details = ret_val.details
         )
         # Get all of the known details, as strings
         det_strs = dict()
         for k, v in ret_val.details._known_details.items():
             det_strs[str(k)] = str(v)
             det_strs[str(k).lower()] = str(v)
             det_strs[str(k).upper()] = str(v)
             if k in Computation.attribute_aliases:
                 for alias in Computation.attribute_aliases[k]:
                     alias = make_safe_identifier(alias)
                     det_strs[str(alias)] = str(v)
                     det_strs[str(alias).lower()] = str(v)
                     det_strs[str(alias).upper()] = str(v)
         variables.update(det_strs)
         # Get any additional keywords specified by the user (advanced feature)
         additional = kwargs.pop('directory_creation_vars', dict())
         variables.update(additional)
         # Now run mako on the template...
         try:
             ret_val.directory = Template(
                 text=ret_val.directory,
                 strict_undefined=True
             ).render(
                 **variables
             )
         except:
             raise ValueError(
                 "invalid MAKO template:\n{}\nMako came back with error:\n{}".format(
                     indent(ret_val.directory),
                     indent(exceptions.text_error_template().render())
                 )
             )
         # and make it into a "url safe string":
         ret_val.directory = urllib.quote_plus(
             ret_val.directory,
             safe='/' + cls.additional_safe_directory_characters
         )
     except ImportError:
         # Can't do mako parsing of path.  Oh well...
         # But if the user specified additional args, they probably thought they did have
         #   mako installed...
         additional = kwargs.pop('directory_creation_vars', None)
         if additional is not None:
             raise
         # and if they have a ${ in the directory name or a <% in the directory name,
         #   they probably also thought that they had mako.
         # (Note: this could be an issue in the unlikely scenario that the user is using
         #   e.g. zsh and specifying environment variables from within Python as ${ }.
         #   If someone is having that problem, they probably have enough intelligence
         #   also to figure out how to get around it.)
         if '${' in ret_val.directory or '<%' in ret_val.directory:
             raise
         # if they're using a class-level template, they also need to have mako installed
         if used_template:
             raise
     #----------------------------------------#
     ret_val.directory = full_path(ret_val.directory)
     #----------------------------------------#
     # Now create the directory if we're allowed to and need to
     create_dirs = kwargs.pop('create_directories', cls.always_create_missing)
     if create_dirs:
         if not os.path.isdir(ret_val.directory):
             if os.path.exists(ret_val.directory):
                 raise OSError(
                     "path '{}' exists and is not a directory".format(
                         ret_val.directory
                     )
                 )
             os.makedirs(ret_val.directory)
     else:
         if not os.path.isdir(ret_val.directory):
             raise OSError(
                 "'{0}' is not a valid directory, and will not be created.  Set the "
                 "'create_directories' argument of computation to True to do directory "
                 "creation automatically.".format(
                     ret_val.directory
                 ))
     #----------------------------------------#
     # now set the input_file and output_file values
     ret_val.runner.input_file = os.path.join(ret_val.directory, ret_val.runner.input_file)
     ret_val.runner.output_file = os.path.join(ret_val.directory, ret_val.runner.output_file)
     ret_val.runner.working_directory = ret_val.directory
     #--------------------------------------------------------------------------------#
     # Pass the remaining kwargs on to the initialization, which may have been customized for the particular package.
     ret_val.__init__(**kwargs)
     return ret_val
示例#5
0
 def __enter__(self):
     self.return_directory = full_path(os.curdir)
     os.chdir(self.directory)