def test_next_backup_filename(): """Test generating the next backup file name""" assert next_backup_filename('foo', ['a', 'b']) == 'foo~' assert next_backup_filename('foo', ['a', 'b', 'foo']) == 'foo~' assert next_backup_filename('foo', ['a', 'b', 'foo~']) == 'foo1~' assert next_backup_filename('foo', ['a', 'b', 'foo', 'foo~']) == 'foo1~' assert next_backup_filename('foo', ['a', 'b', 'foo~', 'foo1~']) == 'foo2~' assert next_backup_filename('foo', ['a', 'b', 'foo~', 'foo1~', 'foo3~']) == 'foo4~' assert next_backup_filename('foo', ['a', 'b', 'foo', 'foo1~', 'foo3~']) == 'foo~'
def _create_from_template(self, src_filename, dest_filename, **kwargs): """ Render the destination file from the source template file Scans the templates directory and create any corresponding files relative to the root directory. If the file is a .template, then renders the file, else simply copy it. Template files are just string templates which will be formatted with the following named arguments: name, package, author, author_email, and description. Note, be sure to escape curly brackets ('{', '}') with double curly brackets ('{{', '}}'). :param src_filename: the template file :param dest_filename: the rendered file """ info("creating {dest} from {src}".format(dest=dest_filename, src=src_filename)) with open(src_filename) as in_file: template = in_file.read() new_filename = None try: # we just want the unique temp file name, we will delete it in the finally block tf = tempfile.NamedTemporaryFile(delete=False) new_filename = tf.name tf.close() rendered = template.format(**kwargs) with open(new_filename, 'w') as out_file: try: out_file.write(rendered) # catching all exceptions # pylint: disable=W0703 except Exception as ex: error(ex) # if there is a dest_filename, then handle backing it up if os.path.isfile(dest_filename): # new_filename contains the just rendered template # dest_filename contains the original content # if new_filename contents equal dest_filename contents, then we are done if md5sum(new_filename)[0] == md5sum(dest_filename)[0]: return # new_filename content and dest_filename content differ # so if there is a backup file and if the backup file contents diff from the dest_filename contents, # then we rename the dest_filename to then incremented backup_filename (one past the highest # existing value) backup_filename = next_backup_filename(name=dest_filename) os.rename(dest_filename, backup_filename) # next we remove the dest_filename then move new_filename to dest_filename if os.path.isfile(dest_filename): os.remove(dest_filename) shutil.copyfile(new_filename, dest_filename) except Exception as ex: error("Error rendering template ({file}) - {err}\n{trace}".format(file=src_filename, err=str(ex), trace=traceback.format_exc())) error("kwargs:\n{kwargs}".format(kwargs=pformat(kwargs))) finally: if new_filename is not None: if os.path.isfile(new_filename): os.remove(new_filename)