Confusing bug

I have been trying unsuccessfully to use packp3d for ages. I keep getting KeyError ‘game’. I have checked and all module directories contain a init.py. I was finally able to produce this problem consistently. Can somebody help confirm that this is a bug.

To reproduce (pay close attention to capitalization):

  • Create a directory called ‘test’
  • inside the 'test directory create a main.py and another directory called ‘subtest’
  • Inside ‘subtest’ create the files ‘TestFile.py’ and ‘init.py’

You will end up with a directory tree like this (sorry for the crazy formatting):

+test
–+main.py
–+subtest
----+init.py
----+TestFile.py

Here are the contents of the files

main.py

import direct.directbase.DirectStart

def main():
	run()

if __name__ == '__main__':
	
	main()

TestFile.py

import os

class SomeClass():
	def __init__(self):
		pass

Now try to pack test directory into a p3d file. I used a command like this

panda3d packp3d.p3d -o test.p3d -d /path/to/test/

I get a KeyError: ‘subtest’. Some experimentation has shown that if you change ‘TestFile.py’ to testfile.py the packing works or if you remove the ‘import os’ the packing works. Apperently you can not have a module file whose name has capital letters AND imports os.

I’m lost on this one. Any one have an idea?

Hmm, it does appear to be an interesting bug. I’ll investigate more closely.

Another workaround is to “import subfile.TestFile” from main.py, which appears to satisfy the ordering requirement.

David

Followup: the problem is due to the way packp3d discovers Python files to add to the p3d. There are two ways it can find them: (a) scanning import statements, or (b) scanning the directory for .py files explicitly. In either case, when it finds them, it adds them to the p3d file.

The problem occurs when it finds a .py file via (b) within a subdirectory that was not earlier discovered via (a). In this case, it must infer what the proper module name is; and it guesses that the module name is based off an import chain from the root: in this case, “subtest.TestFile”. But this fails because nothing has already imported subtest, so it’s not a known module.

The fix is to sort the module imports to guarantee that the subtest module is imported before subtest.TestFile internally, when the p3d file is being built; and I’ve just checked in this fix for the future. But the workaround of putting simply “import subtest” in your main.py file should also solve the problem nicely.

David

David,

Thanks for your help. Your workaround does indeed fix the test case I presented. However, it doesn’t seem to do the trick in my game.

I’ve zipped a few files that should allow you to test. You can download from here http://chadrempp.com/pub/psgtest.zip

I can put together the whole thing if you’d like.

I really appreciate any help :slight_smile: I’ve been reading the modulefinder source trying to track down the issue but I think the problem is in packp3d.p3d. Do you know where I can find the source for packp3d.p3d?

Thanks again.

Chad

It’s direct/src/p3d/packp3d.py.