<s> import sys <EOL> import os <EOL> import os . path as op <EOL> from datetime import datetime <EOL> import stat <EOL> from urllib import quote <EOL> FILES_DIR = '<STR_LIT>' <EOL> INFO_DIR = '<STR_LIT:info>' <EOL> INFO_SUFFIX = '<STR_LIT>' <EOL> XDG_DATA_HOME = op . expanduser ( os . environ . get ( '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> HOMETRASH = op . join ( XDG_DATA_HOME , '<STR_LIT>' ) <EOL> uid = os . getuid ( ) <EOL> TOPDIR_TRASH = '<STR_LIT>' <EOL> TOPDIR_FALLBACK = '<STR_LIT>' + str ( uid ) <EOL> def is_parent ( parent , path ) : <EOL> path = op . realpath ( path ) <EOL> parent = op . realpath ( parent ) <EOL> return path . startswith ( parent ) <EOL> def format_date ( date ) : <EOL> return date . strftime ( "<STR_LIT>" ) <EOL> def info_for ( src , topdir ) : <EOL> if topdir is None or not is_parent ( topdir , src ) : <EOL> src = op . abspath ( src ) <EOL> else : <EOL> src = op . relpath ( src , topdir ) <EOL> info = "<STR_LIT>" <EOL> info += "<STR_LIT>" + quote ( src ) + "<STR_LIT:\n>" <EOL> info += "<STR_LIT>" + format_date ( datetime . now ( ) ) + "<STR_LIT:\n>" <EOL> return info <EOL> def check_create ( dir ) : <EOL> if not op . exists ( dir ) : <EOL> os . makedirs ( dir , <NUM_LIT> ) <EOL> def trash_move ( src , dst , topdir = None ) : <EOL> filename = op . basename ( src ) <EOL> filespath = op . join ( dst , FILES_DIR ) <EOL> infopath = op . join ( dst , INFO_DIR ) <EOL> base_name , ext = op . splitext ( filename ) <EOL> counter = <NUM_LIT:0> <EOL> destname = filename <EOL> while op . exists ( op . join ( filespath , destname ) ) or op . exists ( op . join ( infopath , destname + INFO_SUFFIX ) ) : <EOL> counter += <NUM_LIT:1> <EOL> destname = '<STR_LIT>' % ( base_name , counter , ext ) <EOL> check_create ( filespath ) <EOL> check_create ( infopath ) <EOL> os . rename ( src , op . join ( filespath , destname ) ) <EOL> f = open ( op . join ( infopath , destname + INFO_SUFFIX ) , '<STR_LIT:w>' ) <EOL> f . write ( info_for ( src , topdir ) ) <EOL> f . close ( ) <EOL> def find_mount_point ( path ) : <EOL> path = op . realpath ( path ) <EOL> while not op . ismount ( path ) : <EOL> path = op . split ( path ) [ <NUM_LIT:0> ] <EOL> return path <EOL> def find_ext_volume_global_trash ( volume_root ) : <EOL> trash_dir = op . join ( volume_root , TOPDIR_TRASH ) <EOL> if not op . exists ( trash_dir ) : <EOL> return None <EOL> mode = os . lstat ( trash_dir ) . st_mode <EOL> if not op . isdir ( trash_dir ) or op . islink ( trash_dir ) or not ( mode & stat . S_ISVTX ) : <EOL> return None <EOL> trash_dir = op . join ( trash_dir , str ( uid ) ) <EOL> try : <EOL> check_create ( trash_dir ) <EOL> except OSError : <EOL> return None <EOL> return trash_dir <EOL> def find_ext_volume_fallback_trash ( volume_root ) : <EOL> trash_dir = op . join ( volume_root , TOPDIR_FALLBACK ) <EOL> check_create ( trash_dir ) <EOL> return trash_dir <EOL> def find_ext_volume_trash ( volume_root ) : <EOL> trash_dir = find_ext_volume_global_trash ( volume_root ) <EOL> if trash_dir is None : <EOL> trash_dir = find_ext_volume_fallback_trash ( volume_root ) <EOL> return trash_dir <EOL> def get_dev ( path ) : <EOL> return os . lstat ( path ) . st_dev <EOL> def send2trash ( path ) : <EOL> if not op . exists ( path ) : <EOL> raise OSError ( "<STR_LIT>" % path ) <EOL> if not os . access ( path , os . W_OK ) : <EOL> raise OSError ( "<STR_LIT>" % path ) <EOL> path_dev = get_dev ( path ) <EOL> trash_dev = get_dev ( op . expanduser ( '<STR_LIT>' ) ) <EOL> if path_dev == trash_dev : <EOL> topdir = XDG_DATA_HOME <EOL> dest_trash = HOMETRASH <EOL> else : <EOL> topdir = find_mount_point ( path ) <EOL> trash_dev = get_dev ( topdir ) <EOL> if trash_dev != path_dev : <EOL> raise OSError ( "<STR_LIT>" % path ) <EOL> dest_trash = find_ext_volume_trash ( topdir ) <EOL> trash_move ( path , dest_trash , topdir ) </s>
