[scripting] ReadDir problems - iteration, value returned (Python)

DO 11.10, Win 7 64-bit, python.org 3.4.2 64-bit, pywin32 219 64-bit

I have a couple of problems with ReadDir:

  • FolderEnum returned is not iterable with standard Python syntax (for var in some_FolderEnum_object:)
  • calling Next() on FolderEnum returns str objects (strings), not Item objects (which breaks my use case... :cry:)

See button below listing all items in all folders in the current directory.

  • commented out (with #) code should work, and it does nothing
  • in the last line ".name" should be necessary for the code to work (as Item is not printable), while actually it has to be removed

[code]@script python

def OnClick(ClickData):
dir_col = ClickData.func.sourcetab.dirs
for n in dir_col:
dir_iter = DOpus.FSUtil.ReadDir(n.realpath, False)
#for f in dir_iter:
# DOpus.Output(f.name)
while not dir_iter.complete:
DOpus.Output(dir_iter.Next().name)[/code]

ReadDir isn't a collection so it won't be iterable like that (similarly For Each in VBScript won't work either). Iteration is done via the Next method (there wouldn't even be a Next method if it was a collection).

I don't know about the string vs object thing; Next definitely returns an Item object, and the default value of that object is a string (the item name), but if python can't see it as an object that's a python issue.

I guess there is something special about it after all, as I have generally no problems with Item (like in the ClickData.func.sourcetab.dirs above).
Are there any more places like this (iterable with Next()) I could check?

There's nothing special about Next, it's just a method that returns an object. What actually happens if you call .name?

This is what I see - class 'str' is reported.

DOpus.Output(dir_iter.Next().name) ^ Traceback (most recent call last): File "<Script Block >", line 4, in OnClick DOpus.Output(dir_iter.Next().name) AttributeError: 'str' object has no attribute 'name' (0x80020009)

When iterating ClickData.func.sourcetab.dirs I get objects <class 'win32com.client.CDispatch'>

What if you do item = dir_iter.Next() and then print what type item is?

Hi,

Below is a test script and its output. Apparently two Items returned (for directory and for file) seem to be different entities. Fe. I cannot serialize the correctly working one (which seems OK to me).

[code]@script python

import pickle

def OnClick(ClickData):
dir_col = ClickData.func.sourcetab.dirs
for dir in dir_col:
dir_iter = DOpus.FSUtil.ReadDir(dir.realpath, False)
while not dir_iter.complete:
test_item = dir_iter.Next()
#File Item info
DOpus.Output('Info on file Item - the problematic one')
DOpus.Output('Type: ' + str(type(test_item)))
DOpus.Output('Len: ' + str(len(test_item)))
DOpus.Output('Dump: ' + str(pickle.dumps(test_item)))
#Dir Item info
DOpus.Output('Info on directory Item - this working OK')
DOpus.Output('Type: ' + str(type(dir)))
try:
DOpus.Output('Len: ' + str(len(dir)))
except Exception as e:
DOpus.Output('Len: ' + str(e))
try:
DOpus.Output('Dump: ' + str(pickle.dumps(dir)))
except Exception as e:
DOpus.Output('Dump: ' + str(e))[/code]

Output when run in a directory containing directory dir1 containing file doc1.txt.

[quote]Info on file Item - the problematic one
Type: <class 'str'>
Len: 25
Dump: b'\x80\x03X\x19\x00\x00\x00D:\Temp\ttt\dir1\doc1.txtq\x00.'
Info on directory Item - this working OK
Type: <class 'win32com.client.CDispatch'>
Len: This dispatch object does not define a Count method
Dump: Can't pickle <class 'PyIDispatch'>: attribute lookup PyIDispatch on builtins failed
[/quote]

This looks to be the same underlying problem as your other question.

Do you plan to make necessary changes in the future? For this specific problem (in-place COM object, no file to fetch type library from) it is pretty hard to make a sensible workaround for Python, except for wrapping each function call in a proxy, which is odd and inconvenient.

If ActivePython is confused by the simple concept of methods which take zero arguments, and treats them inconsistently compared to the two standard ActiveScripting languages, I think it is the source of this oddness and inconvenience (as well as others we've already spent time on).

For an easier life in the domain of ActiveScripting, use Javascript or VBScript.

It's not ActivePython, it's python.org python + pywin, doing the same thing just better supported/developed.

And the problem is with any function (except one - see below), not just ones with 0 parameters - it's just where I first spotted it.

The problem is (I think) around the issue, that Python asks COM about object.function and then calls what's returned with any (or 0) parameters provided. If the returned item is not properly flagged by COM (as function), it is treated as non-callable property (more or less).

DOpus.Output() works without any problems with the same pywin mechanism, so I guess the full solution is to apply the same mechanics to the other functions.

Should DO expose the scripting COM via some file, not embedded, and make it available via Dispatch call, it would be just a case to run a python tool once on a machine to solve the problem. It's like this with fe. dopushelp, which apparently makes available all DO commands via COM (I have not checked this though).

Getting to JScript and VBScript (however broken I consider them) would be OK, if I had not known/used another couple languages + got some already done code I run separately for now and would like to integrate for convenience.