|  | @@ -1,43 +1,192 @@
 | 
	
		
			
				|  |  |  import pathlib
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  from .image import image
 | 
	
		
			
				|  |  | +from .product import product
 | 
	
		
			
				|  |  |  from .exception import directory_image_exception
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class directory_image:
 | 
	
		
			
				|  |  | +    """
 | 
	
		
			
				|  |  | +    This is image directory manager. It could store new images for product,
 | 
	
		
			
				|  |  | +    move it, when product name had been changed, and also remove images.
 | 
	
		
			
				|  |  | +    """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      def __init__(self, target: pathlib.Path, thumbnail: int = 400) -> None:
 | 
	
		
			
				|  |  | +        """ 
 | 
	
		
			
				|  |  | +        This initialize new manager.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters;
 | 
	
		
			
				|  |  | +            target (pathlib.Path): Directory to store images in
 | 
	
		
			
				|  |  | +            thumbnail (int): Dimension of the thumbnails
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          self.__target = target
 | 
	
		
			
				|  |  |          self.__thumbnail_size = thumbnail
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if not self.__target.is_dir():
 | 
	
		
			
				|  |  | -            content = "Directory for image hosting: \""
 | 
	
		
			
				|  |  | -            content = content + str(target) + "\"."
 | 
	
		
			
				|  |  | +            self.__target.mkdir()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            raise directory_image_exception(content)
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  |      @property
 | 
	
		
			
				|  |  |      def thumbnail_size(self) -> int:
 | 
	
		
			
				|  |  | +        """ Diameter of the thumbnails. """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          return self.__thumbnail_size
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    def server_path() -> str:
 | 
	
		
			
				|  |  | +        """ This return where bind covers on server. """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return "/covers"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      @property
 | 
	
		
			
				|  |  |      def target(self) -> pathlib.Path:
 | 
	
		
			
				|  |  | +        """ Target directory of the manager. """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          return self.__target
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    def __name_full(self, image_id: int) -> str:
 | 
	
		
			
				|  |  | -        return "full_" + str(image_id) + "_.png"
 | 
	
		
			
				|  |  | +    def __name(self, target: product) -> str:
 | 
	
		
			
				|  |  | +        """ 
 | 
	
		
			
				|  |  | +        Base name of the image.
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        Parameters: 
 | 
	
		
			
				|  |  | +            target (product): Target product to generate name of
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns:
 | 
	
		
			
				|  |  | +            (str): Base part of the name
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return target.name.encode("UTF-8").hex()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    def __name_thumbnail(self, image_id: int) -> str:
 | 
	
		
			
				|  |  | -        return "thumbnail_" + str(image_id) + "_.webp"
 | 
	
		
			
				|  |  | +    def get_full_name(self, target: product) -> str:
 | 
	
		
			
				|  |  | +        """ 
 | 
	
		
			
				|  |  | +        Name of the full size image.
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        Parameters: 
 | 
	
		
			
				|  |  | +            target (product): Target product to generate name of
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    def __full_path(self, image_id: int) -> pathlib.Path:
 | 
	
		
			
				|  |  | -        return self.target / pathlib.Path(self.__full_name(image_id))
 | 
	
		
			
				|  |  | +        Returns:
 | 
	
		
			
				|  |  | +            (str): Name of the full size file
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    def __thumbnail_path(self, image_id: int) -> pathlib.Path:
 | 
	
		
			
				|  |  | -        return self.target / pathlib.Path(self.__thumbnail_name(image_id))
 | 
	
		
			
				|  |  | +        return self.__name(target) + ".full.png"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    def store(self, coded: str, image_id: int) -> None:
 | 
	
		
			
				|  |  | -        full = self.__full_path(image_id)
 | 
	
		
			
				|  |  | -        thumbnail = self.__full_path(image_id)
 | 
	
		
			
				|  |  | +    def get_thumbnail_name(self, target: product) -> str:
 | 
	
		
			
				|  |  | +        """ 
 | 
	
		
			
				|  |  | +        Name of the thumbnail.
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  | -        image(coded, self.thumbnail_size) \
 | 
	
		
			
				|  |  | +        Parameters: 
 | 
	
		
			
				|  |  | +            target (product): Target product to generate name of
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns:
 | 
	
		
			
				|  |  | +            (str): Name of the thumnail file
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return self.__name(target) + ".thumbnail.webp"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __full_path(self, target: product) -> pathlib.Path:
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        Path of the full size image.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters:
 | 
	
		
			
				|  |  | +            target (product): Target product to generate path from
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns:
 | 
	
		
			
				|  |  | +            (pathlib.Parh): Path of the image
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return self.target / pathlib.Path(self.get_full_name(target))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __thumbnail_path(self, target: product) -> pathlib.Path:
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        Path of the thumbnail image.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters:
 | 
	
		
			
				|  |  | +            target (product): Target product to generate path from
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns:
 | 
	
		
			
				|  |  | +            (pathlib.Parh): Path of the thumbnail
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return self.target / pathlib.Path(self.get_thumbnail_name(target))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def save(self, content: image, target: product) -> None:
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        This save new image for new product.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters:
 | 
	
		
			
				|  |  | +            coded (str): Base64 coded received image
 | 
	
		
			
				|  |  | +            target (product): Target product to save image for
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        full = self.__full_path(target)
 | 
	
		
			
				|  |  | +        thumbnail = self.__thumbnail_path(target)
 | 
	
		
			
				|  |  | +       
 | 
	
		
			
				|  |  | +        if full.is_file() or thumbnail.is_file(): 
 | 
	
		
			
				|  |  | +            content = "Images for product \"" + target.name + "\" "
 | 
	
		
			
				|  |  | +            content = content + "already exists."
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            raise directory_image_exception(content)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        content \
 | 
	
		
			
				|  |  |          .save_full(full) \
 | 
	
		
			
				|  |  | -        .save_thumbnail(thumbnail)
 | 
	
		
			
				|  |  | +        .save_thumbnail(thumbnail, self.thumbnail_size)
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    def drop(self, target: product) -> None:
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        This drop images for given product.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters:
 | 
	
		
			
				|  |  | +            target (product): Target product to remove images for
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        full = self.__full_path(target)
 | 
	
		
			
				|  |  | +        thumbnail = self.__thumbnail_path(target)
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        if not full.is_file() or not thumbnail.is_file():
 | 
	
		
			
				|  |  | +            content = "Can not remove images for \"" + target.name + "\" "
 | 
	
		
			
				|  |  | +            content = content + "it not exiets."
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            raise directory_image_exception(content)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        full.unlink()
 | 
	
		
			
				|  |  | +        thumbnail.unlink()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def update(self, old: product, new: product) -> None:
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        This update names of the images for product. Name of the images is
 | 
	
		
			
				|  |  | +        connected with name of the product, and when name of the product 
 | 
	
		
			
				|  |  | +        had been changed, also images must be updated.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters:
 | 
	
		
			
				|  |  | +            old (product): Product before update
 | 
	
		
			
				|  |  | +            new (product): Product after update
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        same_name = (
 | 
	
		
			
				|  |  | +            self.get_thumbnail_name(old) == self.get_thumbnail_name(new) and \
 | 
	
		
			
				|  |  | +            self.get_full_name(old) == self.get_full_name(new)
 | 
	
		
			
				|  |  | +        )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if same_name:
 | 
	
		
			
				|  |  | +            return
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        old_full = self.__full_path(old)
 | 
	
		
			
				|  |  | +        old_thumbnail = self.__thumbnail_path(old)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if not old_full.is_file() or not old_thumbnail.is_file():
 | 
	
		
			
				|  |  | +            content = "Can not move file for \"" + old.name + "\" "
 | 
	
		
			
				|  |  | +            content = content + "because not exists."
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            raise directory_image_exception(content)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        new_full = self.__full_path(new)
 | 
	
		
			
				|  |  | +        new_thumbnail = self.__thumbnail_path(new)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if new_full.is_file() or new_thumbnail.is_file(): 
 | 
	
		
			
				|  |  | +            content = "Can not move, because images for \"" + new.name + "\" "
 | 
	
		
			
				|  |  | +            content = content + "already exists."
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            raise directory_image_exception(content)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        old_full.rename(new_full)
 | 
	
		
			
				|  |  | +        old_thumbnail.rename(new_thumbnail)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 |