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")
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")
def __enter__(self): self.return_directory = full_path(os.curdir) os.chdir(self.directory)
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