filey/filey/preamble/filesystem.py

380 lines
12 KiB
Python

"""
Implementation of a rudimentary file system
TODO:
grab the
"""
import os, sys, shutil, pathlib
from dataclasses import dataclass
import filetype as ft
from send2trash import send2trash
from sl4ng import show, delevel, gather, nameSpacer
def trim(path,edge=os.sep):
out = path[:]
while out.startswith(edge):
out = out[1:]
while out.endswith(edge):
out = out[:-1]
print(out)
return out
class size(int):
def __repr__(self):
return f'{round(self*10**-3):,} kb'
class _path(str):
@dataclass
class address:
"""
A systemic pointer to the location of the data associated with a file system object
"""
# def init(self,path:str):
# assert os.path.exists(self.path), f'"{path}" is not a valid address on this system'
# self.path = path
path:str
# if path:
# assert os.path.exists(self.path), f'"{path}" is not a valid address on this system'
@property
def exists(self):
return os.path.exists(self.path)
@property
def isdir(self):
return os.path.isdir(self.path)
@property
def isfile(self):
return os.path.isfile(self.path)
@property
def obj(self):
if self.isdir:
return directory(self.path)
elif self.isfile:
return file(self.path)
else:
raise ValueError(f'"{self.path}" is not a valid address on this system')
if exists:
# del isfile,isdir
( , )
class directory:
def __init__(self,path:str):
assert address(path).isdir, f'"{path}" is not a directory'
self.path = trim(path)
self._ind = -1
cntnt = (address(os.path.join(path,i)) for i in os.listdir(path))
for i in cntnt:
name = os.path.split(i.path)[1]
if i.isdir:
setattr(self,name,i.path)
elif i.isfile:
setattr(self,os.path.splitext(name)[0],i.path)
@property
def children(self):
return tuple(addy.obj for i in os.listdir(self.path) if (addy:=address(os.path.join(str(self),i))).isdir)
@property
def files(self):
return tuple(addy.obj for i in os.listdir(self.path) if (addy:=address(os.path.join(self.path,i))).isfile)
@property
def content(self):
return tuple(address(os.path.join(self.path,i).obj for i in os.listdir(self.path)))
@property
def leaves(self):
return tuple(self.gather())
@property
def leaves(self):
return tuple(set(i.container() for i in self.gather()))
@property
def name(self):
return os.path.split(self.path)[1]
@property
def ancestors(self):
level = []
p = self.path[:]
while p != delevel(p):
p = delevel(p)
level.append(p)
return tuple(directory(i) for i in level)[::-1]
@property
def depth(self):
return len(self.ancestors)
@property
def root(self):
return self.ancestors[0]#.split(':')[0]
@property
def size(self):
# return size(sum(os.stat(file).st_size for file in self.gather()))
return size(sum(file.size for file in self.leaves))
@property
def mime(self):
# return tuple(set(match.MIME if (match:=ft.guess(file)) else 'UNKNOWN' for file in self.gather()))
return tuple(set(file.mime for file in self.gather()))
@property
def kind(self):
return tuple(set(m.split('/')[0] for m in self.mime))
@property
def ext(self):
return tuple(set(f.ext for f in self.gather()))
@property
def siblings(self):
return tuple(i for i in self.container() if isinstance(i,type(self)))
@property
def peers(self):
return self.container().content
@property
def stat(self):
"""
return os.stat(str(self))
"""
return os.stat(str(self))
def touch(self):
p = str(self)
pathlib.Path(p).touch()
self = address(p).obj
return self
def delete(self,recycle=True):
send2trash(self.path) if recycle else os.remove(self.path)
del self
def rename(self,new,relative=False):
new = new if not relative else os.path.join(delevel(self.path),new)
os.makedirs(delevel(new),exist_ok=True)
os.rename(self.path,new)
self = address(new).obj
return self
def clone(self,new=None,relative=False,touch=False):
if new:
if relative:
new = nameSpacer(os.path.join(delevel(self.path),new))
else:
new = nameSpacer(os.path.join(delevel(self.path),self.name))
os.makedirs(delevel(new),exist_ok=True)
shutil.copy2(self.path,new) #if touch else shutil.copy2(self.path,new)
out = address(new).obj
return out.touch() if touch else out
def container(self,steps=1,path=False):
return delevel(self.path,steps) if path else directory(delevel(self.path,steps))
def heritage(self):
print(f'\nheritage({self.name.title()})')
ancs = list(self.ancestors)
ancs.append(self.path)
for i,anc in enumerate(ancs):
print('\t'+('','.'*i)[i>0]+i*' '+[i for i in str(anc).split(os.sep) if i][-1])
def show(self, indentation:int=1, enum:bool=False, start:int=1, indentor:str='\t'):
assert indentation>0, f'"{indentation}" is not a viable indentation level'
print((indentation-1)*'\t'+self.name)
show(self.content,indentation,enum,start,indentor)
def gather(self,names:bool=False,walk:bool=True,ext:str=None,paths=False):
if paths:
yield from gather(str(self),names,walk,ext)
else:
for path in gather(str(self),names,walk,ext):
yield file(path)
def add(self,new):
if (obj:=address(new).obj):
return obj.move(self)
else:
raise ValueError(f'"{new}" does is neither a file or directory')
def moveContent(self,other):
# assert address(trim(str(other))).isdir, f'"{other}" is not a viable directory here'
assert address((str(other))).isdir, f'"{other}" is not a viable directory here'
for f in self.gather():
# rest = f.path[len(self.path)+1:]
ending = trim(f.path[len(self.path)+1:])
new = os.path.join(trim(str(other)),ending)
# os.makedirs(delevel(new))
print(self)
print(f)
print(ending)
print(new)
print()
def isroot(self):
return not self.depth
def __bool__(self):
return len(os.listdir(self.path))>0
def __str__(self):
return self.path
def __repr__(self):
return str(self)
def __iter__(self):
return self
def __len__(self):
return len(self.content)
def __next__(self):
if self._ind<len(self)-1:
self._ind += 1
return self.content[self._ind]
self._ind = -1
raise StopIteration
def __getitem__(self,item):
if item in self.content:
return address(os.path.join(self.path,item)).obj
raise ValueError(f'The folder "{self.name}" does not contain anything called "{item}"')
move = rename
extension = ext
copy = clone
class file:
def __init__(self,path:str):
assert address(path).isfile, f'"{path}" is not a file'
self.path = trim(path)
@property
def name(self):
return os.path.split(self.path)[1]
@property
def title(self):
return os.path.splitext(self.name)[0]
@property
def ancestors(self):
level = []
p = self.path[:]
while p != delevel(p):
p = delevel(p)
level.append(p)
return tuple(directory(i) for i in level)[::-1]
@property
def depth(self):
return len(self.ancestors)
@property
def root(self):
return self.ancestors[0]#.split(':')[0]
@property
def size(self):
return size(os.stat(str(self)).st_size)
@property
def mime(self):
return match.MIME if (match:=ft.guess(str(self))) else 'UNKNOWN'
@property
def kind(self):
return self.mime.split('/')[0] if (match:=ft.guess(str(self))) else 'UNKNOWN'
@property
def ext(self):
return os.path.splitext(self.name)[1]
@property
def siblings(self):
return tuple(i for i in self.container() if isinstance(i,type(self)))
@property
def peers(self):
return self.container().content
@property
def stat(self):
"""
return os.stat(str(self))
"""
return os.stat(str(self))
def touch(self):
p = str(self)
pathlib.Path(p).touch()
self = address(p).obj
return self
def delete(self,recycle=True):
send2trash(self.path) if recycle else os.remove(self.path)
del self
def rename(self,new,relative=False):
new = new if not relative else os.path.join(delevel(self.path),new)
os.makedirs(delevel(new),exist_ok=True)
os.rename(self.path,new)
self = address(new).obj
return self
def clone(self,new=None,relative=False,touch=False):
if new:
if relative:
new = nameSpacer(os.path.join(delevel(self.path),new))
else:
new = nameSpacer(os.path.join(delevel(self.path),self.name))
os.makedirs(delevel(new),exist_ok=True)
shutil.copy2(self.path,new) #if touch else shutil.copy2(self.path,new)
out = address(new).obj
return out.touch() if touch else out
def container(self,steps=1,path=False):
return delevel(self.path,steps) if path else directory(delevel(self.path,steps))
def heritage(self):
print(f'\nheritage({self.name.title()})')
ancs = list(self.ancestors)
ancs.append(self.path)
for i,anc in enumerate(ancs):
print('\t'+('','.'*i)[i>0]+i*' '+[i for i in str(anc).split(os.sep) if i][-1])
def __str__(self):
return self.path
def __repr__(self):
return str(self)
move = rename
extension = ext
copy = clone
if __name__ == '__main__':
dp = r'c:\users\kenneth\videos'
# print(directory(dp))
# show(directory(dp).fils,)
fp = r'c:\users\kenneth\pyo_rec.wav'
# print(os.path.isfile(fp))
# print(file(fp))
fp = r'C:\Users\Kenneth\Music\Collection\slowthai\The Bottom _ North Nights\02 North Nights.mp3'
dp = delevel(fp,1)
d = address(dp).obj
print(d)
# d.show(1)
f = address(fp).obj
print(f)
system = (d,f)
print(system)
print([i.name for i in system])
print([i.depth for i in system])
print([i.ancestors for i in system])
print([i.heritage() for i in system])
print([i.root for i in system])
print([i.size for i in system])
[print(i.size) for i in system]
[print(i.kind) for i in system]
[print(i.ext) for i in system]
[print(i.stat) for i in system]
print(d.leaves)
# d.moveContent(r'c:\users\kenneth\downloads\\')
# print(f.clone(touch=True))
# print(f.clone())
# print(f.move(nameSpacer(str(f))))
# os.startfile(f.container().path)
# help(f)
# for i in d:
# ob = d[i]
# print(ob,ob.kind,ob.ext)
# if isinstance(ob,directory):
# for o in ob.children:
# o2 = ob[o]
# print('\t',o2,o2.kind,o2.ext)
# for p in d.gather():
# print(p.size,p.mime,p.ext,sys.getrefcount(p))
# f = file(p)
# if 'matroska' in f.mime:
# print(f.container())
# print(f.name)
# print(f.size)
# for i in d:print(i)
# print(os.stat(dp).st_size)
# print(os.stat(fp).st_size)
# print(dict(d))
# d.heritage()
# os.rename('Few Nolder','randombumbashit')
# print(os.listdir('randombumbashit'))