← Back to team overview

sikuli-driver team mailing list archive

Re: [Question #210973]: Sikuli code organization / code reuse

 

Question #210973 on Sikuli changed:
https://answers.launchpad.net/sikuli/+question/210973

Description changed to:
I discovered a solution for the below problem. My current solution
however isn't quite ideal, and I'd still love any feedback. Here's the
solution:

I created a directory structure as follows:

parent.sikuli
parent.sikuli/project1.sikuli/
parent.sikuli/project1.sikuli/(sikuli objects go here)
parent.sikuli/shared.sikuli/
parent.sikuli/shared.sikuli/(sikuli objects go here)

Each parent .sikuli directory is essentially an empty file that you can
use to initialize other imports. For example:

parent.sikuli/parent.py
------------------------------
from project1.sikuli import *
from shared.sikuli import *

shared.sikuli/shared.py
------------------------------
from ReusableComponent1 import *
from ReusableComponent2 import *

Still, this has the problem that you need to change an initialization
file each time you add a new object to the directory structure. It would
be nice if there was a way to recursively import everything. Also, it's
a little hacky and doesn't allow you to selectively import certain
files. Furthermore, this creates a bit of dependency hell, since
components at the project level can't directly import shared components.

------------------------------------------------------------------------------------------------------
Question:
I am trying to create a good structure for Sikuli code to use across many tests on many projects. I am trying to organize my code as follows:

parent/
parent/project1
parent/project1/(project1 .sikuli files here)
parent/shared
parent/shared/(shared .sikuli files here)

In order to do this, there needs to be a way to either:
1) Package the project at the parent level
2) Import the other modules dynamically

I couldn't find a way to create a sikuli package, so I went with method
#2, which is fine. The problem with method #2 is that you need to import
all of the folders dynamically into os.path for _every_ file. This is
really a big problem. Also, I'm currently statically getting the
directories by using getBundlePath(). This is another problem because
you have to update this anytime you add another folder to the directory
structure.

In other words, In order to import other modules dynamically, I need to
include something similar to the following code at the top of _each_ .py
file.

import os
project1Path = os.path.dirname(getBundlePath()) + "\.." + "\project1Path"
if not project1Path in sys.path: sys.path.append(project1Path)
sharedPath = os.path.dirname(getBundlePath()) + "\.." + "\shared"
if not sharedPath in sys.path: sys.path.append(sharedPath)

Is there a way that I can:
1) Create one __init__.py file (or similar) to preload all of the modules required so that I do not have to repeat the previous code at the top of _every_ file?
2) Recursively get all of the folders under the parent directory and import all the .sikuli modules so I do not have to update the __init__ file every time there is a change to the directory structure?

Alternatively, is there a way to create a package of .sikuli files?

The only solution I can get to work at the moment is to actually throw
all the .sikuli files into one parent folder and then use a naming
convention as follows:

parent/
parent/Project1Object1.sikuli
parent/Project1Object2.sikuli
parent/Project1Object3.sikuli
parent/SharedComponent1.sikuli
etc...

Then you can use the following code at the top of each file:

import os
myPath = os.path.dirname(getBundlePath())
if not myPath in sys.path: sys.path.append(myPath)

This code shouldn't change if you keep a flat directory structure. Even
so, this isn't very ideal because you're still copy-paste coding this
snippet into the top of every file instead of maintaining it in one
place, and if you're using thousands of .sikuli scripts (or more) then
things will get messy.

-- 
You received this question notification because you are a member of
Sikuli Drivers, which is an answer contact for Sikuli.