X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=common%2Fpython%2Frift%2Fdownloader%2Fbase.py;fp=common%2Fpython%2Frift%2Fdownloader%2Fbase.py;h=c87839f604f7f8f982a98129a33dbfbb45feedc5;hb=6364d016e7f819903ff29a2ce160cb4cea61bf8f;hp=0000000000000000000000000000000000000000;hpb=c33673480c15d6e64402b547563640b2025a3cd6;p=osm%2FSO.git diff --git a/common/python/rift/downloader/base.py b/common/python/rift/downloader/base.py new file mode 100644 index 00000000..c87839f6 --- /dev/null +++ b/common/python/rift/downloader/base.py @@ -0,0 +1,180 @@ +# +# Copyright 2016 RIFT.IO Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Author(s): Varun Prasad +# Creation Date: 09/25/2016 +# + +import abc +import enum +import os +import uuid +import time + + +class InvalidDestinationError(Exception): + pass + + +class DownloaderProtocol: + """Listener of this class can implement the following method to get a + callback + """ + def on_download_started(self, job): + """Called when the download starts + + Args: + job (DownloadJob): Yang Model + + """ + pass + + def on_download_progress(self, job): + """Called after each chunk is downloaded + + Args: + job (DownloadJob): Yang Model + + """ + pass + + def on_download_succeeded(self, job): + """Called when the download is completed successfully + + Args: + job (DownloadJob): Yang Model + + """ + pass + + def on_download_failed(self, job): + """Called when the download fails + + Args: + job (DownloadJob): Yang Model + + """ + pass + + def on_download_cancelled(self, job): + """Called when the download is canceled + + Args: + job (DownloadJob): Yang Model + + """ + pass + + def on_download_finished(self, job): + """Called when the download finishes regardless of the status of the + download (success, failed or canceled) + + Args: + job (DownloadJob): Yang Model + + """ + pass + + +class DownloadStatus(enum.Enum): + STARTED = 1 + IN_PROGRESS = 2 + COMPLETED = 3 + FAILED = 4 + CANCELLED = 5 + + +class DownloadMeta: + """Model data used by the downloader. + """ + def __init__(self, url, dest_file): + self.url = url + self.filepath = dest_file + self.download_id = str(uuid.uuid4()) + self.bytes_total = 0 + self.progress_percent = 0 + self.bytes_downloaded = 0 + self.bytes_per_second = 0 + + + self.start_time = 0 + self.stop_time = 0 + self.detail = "" + + @property + def filename(self): + return os.path.basename(self.filepath) + + def start_download(self): + self.start_time = time.time() + + def end_download(self): + self.end_time = time.time() + + def set_state(self, state): + self.status = state + + def update_with_data(self, downloaded_chunk): + self.bytes_downloaded += len(downloaded_chunk) + + if self.bytes_total != 0: + self.progress_percent = \ + int((self.bytes_downloaded / self.bytes_total) * 100) + + # compute bps + seconds_elapsed = time.time() - self.start_time + self.bytes_per_second = self.bytes_downloaded // seconds_elapsed + + def update_data_with_head(self, headers): + """Update the model from the header of HEAD request + + Args: + headers (dict): headers from HEAD response + """ + if 'Content-Length' in headers: + self.bytes_total = int(headers['Content-Length']) + + def as_dict(self): + return self.__dict__ + + +class AbstractDownloader: + + def __init__(self): + self._delegate = None + + @property + def delegate(self): + return self._delegate + + @delegate.setter + def delegate(self, delegate): + self._delegate = delegate + + @abc.abstractproperty + def download_id(self): + pass + + @abc.abstractmethod + def cancel_download(self): + pass + + @abc.abstractmethod + def close(self): + pass + + @abc.abstractmethod + def download(self): + pass