So I'm building a command-line tutorial program of sorts in Python. Basically it emulates a terminal and walks you through different levels using shell commands. The way the original version worked is I caught anything entered and analyzed it for calls to the tutorial program if there weren't any I passed the command to the computer using os.system().
Unfortunately, since I wrote the tutorial to be of a *nix system, it does not work on Windows, since I included levels using vim and what-not. My plan was to rewrite the program, but rather than making calls to the system, I'd create a virtual filesystem. This includes to objects: directory and file. You can probably figure out what both of the objects are meant to be. The directory object would contain a list of its contents and this would act as the filesystem. I would then implement commands like cd, ls, pwd, and so-on.
The problem I have run in to is that when I return a containing directory or file from a directory object I'm not able to edit it in any way. I'll give you an example of my code.
NOTE: There are likely bugs in the code as I cannot test it very well without fixing this issue Also, the imports aren't necessary to the problems. The first one is a color class that lays out the codes for doing colored output and the second is a file that contains global variables. I've removed the calls to these resources so that it will run on someone else's system
#from ..resources.colors import colors
#from ..resources import variables as var
class Directory:
# Basic constructor
def __init__(self, name="", container=None, contents=[]):
self.name = name
self.container = container
self.contents = contents
# grabs index of contents by name
def index(self, find):
for i in range(len(self.contents)):
if self.contents[i].name == find:
return i
return -1
# Add something to the container
def add(self, dirFile):
# Check for duplicate names
if self.index(dirFile.name) != -1:
return False
self.contents.append(dirFile)
return True
# Retrieve something that's in contents
def get(self, neededName):
ind = self.index(neededName)
if ind >= 0:
return self.contents[ind]
# Returns true if it has at least one sub directory
def has_sub(self):
for content in self.contents:
if type(content) == Directory:
return True
return False
# Iterates through, looks for slashes and goes to subs (recursion, ooooh!)
def get_sub(self, path=""):
if not self.has_sub() or path == "":
return self
pathSplit = path.split("/")
nextDir = self.index(pathSplit[0])
if nextDir >= 0:
return self.contents[nextDir]
pathSplit.pop(0)
path = "/".join(pathSplit)
return self.get_sub(path)
# ============== Shell Commands ==============
# List all contents in directory
def ls(self):
for content in self.contents:
if type(content) == Directory:
#print(colors.fg.blue + content.name + colors.reset + "\t", end="") This is the code wih the colors class
print(content.name + "\t", end="")
else:
print(content.name + "\t", end="")
print()
# Delete file by name:
def rm(self, toDelete):
ind = self.index(toDelete)
if ind >= 0:
self.contents.pop(ind)
return True
else:
return False
# Make new dir
def mkdir(self, name=""):
if name:
self.add(Directory(name))
## Current test
di = Directory("Test")
di.mkdir("one")
di.mkdir("two")
di.get_sub("one").mkdir("test")
di.ls()
di.get_sub("one").ls()
The current output is:
one two test
one two test
But the output should read:
one two
test
For some reason when I call:
di.get_sub("one").mkdir("test")
It changes di rather than the object returned by get_sub()
Any help is much appreaciated. Let me know if there's anything else I should provide.
There are a couple of pointers I think I can give you. The first is, probably most appropriately, to answer your primary question:
It changes di rather than the object returned by get_sub()
This is likely because no matter how things work out, has_sub() will eventually resolve to a subdirectory with no further directories in. This will result in this clause becoming true:
if not self.has_sub() or path == "":
return self
if not self.has_sub
will evaluate true and return di
. It'll always be di
as your recursive routine always calls methods on self
which is di
. I hope that makes sense!
In terms of the second pointer I can give you, maybe I can ask a couple of questions regarding your test-case which might assist with some discover and though processes:
1: di = Directory("Test")
2: di.mkdir("one")
3: di.mkdir("two")
4: di.get_sub("one").mkdir("test")
5: di.ls()
6: di.get_sub("one").ls()
In line one you create Test
, then add in (2) and (3) new (I suppose) subdirectories. However, looking at mkdir in your Directory implementation, these don't actually get created. Perhaps look at os.mkdir and consider whether you need to worry about existing directories. os.path.join might also be your friend here...
Have a good look at what you're returning. If you return self
you're returning the reference to the object you called the method on. If you chain a second method call to that (in your case) it will still be di
that you call it on.
I think you'll have a lot of fun implementing this if you first start looking first looking into os.path as a module then consider some of the additional os functions like mkdir mentioned above. Also consider that os.getcwd() and os.chdir() might be of interest.
I really hope this helps. :-)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.