PKʽJG SScleaner/__init__.py"""Clean your repositories with a cool interactive shell""" __version__ = "0.3.1" PKJrcleaner/cli.pyfrom clize import run from .shell import launch_shell def cleaner(directory="."): launch_shell(directory) def run_cleaner(): run(cleaner) if __name__ == "__main__": run(cleaner) PKJ $$cleaner/filesystem.pyimport os import shutil def listdir_with_prefix(start): if not os.path.isdir(start): raise ValueError("Must be a directory") if not start.endswith('/'): start += '/' for subentry in os.listdir(start): with_prefix = start + subentry if os.path.isdir(with_prefix): with_prefix += '/' yield with_prefix def remove(entry): if os.path.isdir(entry): shutil.rmtree(entry) else: os.remove(entry) def move(entry, destination): shutil.move(entry, destination) def traversal(directory): for entry in listdir_with_prefix(directory): enter = yield entry if not os.path.isdir(entry): continue while enter: yield from traversal(entry) enter = yield entry PKJ&&ttcleaner/shell.pyfrom cmd import Cmd from enum import Enum import grp import os import pwd import shlex import shutil import stat import sys from .filesystem import traversal, remove, move ERROR_IGNORE = (KeyboardInterrupt,) ERROR_PRINT = (Exception,) def parsed_arguments_method(method): def new_method(self, line): return method(self, *shlex.split(line)) return new_method def filename_argument(argument): return os.path.expanduser(argument) def filemode_argument(argument): return int(argument, base=8) def launch_shell(directory): shell = FileActionShell() try: shell.launch(directory) except ERROR_IGNORE: pass except ERROR_PRINT as e: print("FATAL ERROR: {}".format(e)) class IterationCommand(Enum): keep = 0 next = 1 quit = 2 class DirectoryTraversalShell(Cmd): def launch(self, directory): self.traversal_argument = None self.file_iterator = traversal(directory) if not self.iter_file(): return self.set_prompt() self.cmdloop() def iter_file(self): try: self.file = self.file_iterator.send(self.traversal_argument) except StopIteration: return False return True def set_prompt(self): self.prompt = "{} > ".format(self.file) def postcmd(self, iter_cmd, line): if iter_cmd is None: iter_cmd = IterationCommand.next if (iter_cmd == IterationCommand.quit or (iter_cmd == IterationCommand.next and not self.iter_file())): return True # exits self.set_prompt() self.traversal_argument = None class FileActionShell(DirectoryTraversalShell): info_template = "{mode} | {user}:{group}" def default(self, line): return self.error("Unknow Syntax: {}", line) def error(self, error_msg=None, *args, **kwargs): if not error_msg: error_msg = "Unknow Error" error_msg = "*** " + error_msg.format(*args, **kwargs) print(error_msg, file=sys.stderr) return IterationCommand.keep def do_EOF(self, _): return IterationCommand.quit def emptyline(self): return IterationCommand.next def do_pass(self, _): return IterationCommand.next def do_enter(self, _): if not os.path.isdir(self.file): return self.error("enter command must be used on a directory") self.traversal_argument = True def do_quit(self, line): return IterationCommand.quit @parsed_arguments_method def do_info(self): stat_info = os.stat(self.file) file_info = {} file_info["mode"] = stat.filemode(stat_info.st_mode) file_info["user"] = pwd.getpwuid(stat_info.st_uid).pw_name file_info["group"] = grp.getgrgid(stat_info.st_gid).gr_name print(self.info_template.format(**file_info)) return IterationCommand.keep @parsed_arguments_method def do_rm(self): remove(self.file) @parsed_arguments_method def do_mv(self, filename): destination = filename_argument(filename) move(self.file, destination) @parsed_arguments_method def do_chmod(self, mode): mode = filemode_argument(mode) os.chmod(self.file, mode) return IterationCommand.keep @parsed_arguments_method def do_chown(self, user_group_string): user_group = user_group_string.split(':', 1) if len(user_group) == 1: user, group = user_group[0], None else: user, group = user_group shutil.chown(self.file, user, group) return IterationCommand.keep @parsed_arguments_method def do_ls(self): if not os.path.isdir(self.file): return self.error("ls command must be used on a directory") for entry in os.listdir(self.file): print(entry) return IterationCommand.keep PK!H{,5(cleaner-0.3.1.dist-info/entry_points.txtN+I/N.,()JIMK-RUs2J|..PK0Jrv>>cleaner-0.3.1.dist-info/LICENSEThe MIT License (MIT) Copyright (c) 2017 Alexandre Bonnetain Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK!HuNRRcleaner-0.3.1.dist-info/WHEEL1 0 RZq+D-Dv;_[*7Fp 6ՆKŵ|4|cBQaL2PK!HD6UOw cleaner-0.3.1.dist-info/METADATAVMoF_$ʩԵ18E$ Wz?ݥdE{g( lq潙ar}PήMPh؇Nx茑_ ǡw *:0N$iP6ET[Р3leMMmXV5=m™C4J&U6^\wq~ -=¯Z*D1D#^L7Rsğw<==C]^e?-CPBBawpݶmwwSxtBd?xAN2PUBP!SnZmj|SXGk+a`@odnYnh撪,ErYc1dB\~ħ (&JdRxh!Rr`(y[2=q e9յlр !roR/spr/zң%q NQ"~h4 (P3T$pN b3Y᝴q_""ePC}uxHpqgC$ReD|TZՊ)H俺!Bzz|L.>;] Tʶtq=Nџ uZ+wTj 5m-O(!P2%3|OOU8;8gpϑUv ,T,'s3Сi2i'{v @6. #K=:j+ag+TdN% oۡV'Wr^XkeP@UǓOCkR(0ύ+iPsz_kﺖީ&Nj/bAd8l ,R;[)F& y;,<״fAQ!J25bKz|z K!6=6>OWQZPdhK:]ES:Sy\>/ѸSGWv܄ħTU-zG)`< p$?uhK}lS}9d@q5% HQٓ8=Necleaner-0.3.1.dist-info/RECORDuK0@[  O~APPB@z=i-'nԭ[`xNSDMu0C!]u5]ä;γߤ\mQT`.(eP<iĹ߁hXHf楔a(aE>3m:]͒h*$to*>:GefV|aC 1~s& Bלv6[;+PT=79ւzJ5 s# nhFkkñezg; eцө6yM8zTkpv7OS!n&f yE`hPKʽJG SScleaner/__init__.pyPKJrcleaner/cli.pyPKJ $$ucleaner/filesystem.pyPKJ&&ttcleaner/shell.pyPK!H{,5(ncleaner-0.3.1.dist-info/entry_points.txtPK0Jrv>>cleaner-0.3.1.dist-info/LICENSEPK!HuNRR[cleaner-0.3.1.dist-info/WHEELPK!HD6UOw cleaner-0.3.1.dist-info/METADATAPK!H>eucleaner-0.3.1.dist-info/RECORDPK c