Source code for foundations.rotatingBackup
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
**rotatingbackup.py**
**Platform:**
Windows, Linux, Mac Os X.
**Description:**
Defines the :class:`RotatingBackup` class.
**Others:**
Code extracted from rotatingbackup.py written by [email protected]
"""
#**********************************************************************************************************************
#*** Future imports.
#**********************************************************************************************************************
from __future__ import unicode_literals
#**********************************************************************************************************************
#*** External imports.
#**********************************************************************************************************************
import os
#**********************************************************************************************************************
#*** Internal imports.
#**********************************************************************************************************************
import foundations.common
import foundations.exceptions
import foundations.io
import foundations.verbose
#**********************************************************************************************************************
#*** Module attributes.
#**********************************************************************************************************************
__author__ = "Thomas Mansencal"
__copyright__ = "Copyright (C) 2008 - 2014 - Thomas Mansencal"
__license__ = "GPL V3.0 - http://www.gnu.org/licenses/"
__maintainer__ = "Thomas Mansencal"
__email__ = "[email protected]"
__status__ = "Production"
__all__ = ["LOGGER", "RotatingBackup"]
LOGGER = foundations.verbose.installLogger()
#**********************************************************************************************************************
#*** Module classes and definitions.
#**********************************************************************************************************************
[docs]class RotatingBackup(object):
"""
Defines a rotating backup system.
"""
def __init__(self, source=None, destination=None, count=3):
"""
Initializes the class.
.. warning::
Backups destination folder should not be the same than the folder containing the source to be backuped!
Usage::
>>> file = "File.txt"
>>> destination = "backup"
>>> backup = RotatingBackup(file, destination)
>>> backup.backup()
True
>>> for i in range(3):
... backup.backup()
...
True
True
True
>>> import os
>>> os.listdir(destination)
['File.txt', 'File.txt.1', 'File.txt.2', 'File.txt.3']
:param source: Backup source.
:type source: unicode
:param destination: Backup destination.
:type destination: unicode
:param count: Backups count.
:type count: int
"""
LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))
# --- Setting class attributes. ---
self.__source = None
self.__source = source
self.__destination = None
self.__destination = destination
self.__count = None
self.__count = count
#******************************************************************************************************************
#*** Attributes properties.
#******************************************************************************************************************
@property
def source(self):
"""
Property for **self.__source** attribute.
:return: self.__source.
:rtype: unicode
"""
return self.__source
@source.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def source(self, value):
"""
Setter for **self.__source** attribute.
:param value: Attribute value.
:type value: unicode
"""
if value is not None:
assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format(
"source", value)
assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("source", value)
self.__source = value
@source.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def source(self):
"""
Deleter for **self.__source** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "source"))
@property
def destination(self):
"""
Property for **self.__destination** attribute.
:return: self.__destination.
:rtype: unicode
"""
return self.__destination
@destination.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def destination(self, value):
"""
Setter for **self.__destination** attribute.
:param value: Attribute value.
:type value: unicode
"""
if value is not None:
assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format(
"destination", value)
self.__destination = value
@destination.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def destination(self):
"""
Deleter for **self.__destination** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "destination"))
@property
def count(self):
"""
Property for **self.__count** attribute.
:return: self.__count.
:rtype: int
"""
return self.__count
@count.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def count(self, value):
"""
Setter for **self.__count** attribute.
:param value: Attribute value.
:type value: int
"""
if value is not None:
assert type(value) is int, "'{0}' attribute: '{1}' type is not 'int'!".format(
"count", value)
assert value > 0, "'{0}' attribute: '{1}' need to be exactly positive!".format("count", value)
self.__count = value
@count.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def count(self):
"""
Deleter for **self.__count** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "count"))
#******************************************************************************************************************
#*** Class methods.
#******************************************************************************************************************
[docs] def backup(self):
"""
Does the rotating backup.
:return: Method success.
:rtype: bool
"""
LOGGER.debug("> Storing '{0}' file backup.".format(self.__source))
foundations.common.pathExists(self.__destination) or foundations.io.setDirectory(self.__destination)
destination = os.path.join(self.__destination, os.path.basename(self.__source))
for i in range(self.__count - 1, 0, -1):
sfn = "{0}.{1}".format(destination, i)
dfn = "{0}.{1}".format(destination, i + 1)
if foundations.common.pathExists(sfn):
if foundations.common.pathExists(dfn):
foundations.io.remove(dfn)
os.renames(sfn, dfn)
foundations.common.pathExists(destination) and os.rename(destination, destination + ".1")
foundations.io.copy(self.__source, destination)
return True