I'm developping multiple webservices with CherryPy. Some of them have to use the same code parts, so I'd want to avoid code duplication.
I'd want the CherryPy WebServer to serve all the applications, mounted on different urls.
This is how I organized my file hierarchy (it's a simplified version of course):
apps/
server.py -- runs the WSGI Server
app1/
api/
lib/
ext/
app.py -- provides a function get_wsgi_app(name, config)
app2/
api/
lib/
ext/
app.py
common/ -- All common classes and modules
Consider that server.py is the entry point. It imports each app.py and get a WSGI application from it. Then it mounts them to be served.
I'd want to be able to import some classes from common/ but without altering multiple times sys.path. So I tought I may be able to import the needed modules in ext. And when I need them in an app I'd just have to make an import like :
from ext.share_module import class
1 - Do you think the file hierarchy is fine?
2 - I'd want each app to be independent from the server and the other apps. So, for the import I'd want to be able to simply consider that app1/ is the root folder and not apps/ . But because server.py is the entry point, I can't import the modules like I want.
3 - Any suggestion, consideration or advice ? :)
OK here's the solution I ended up with. It is almost the same that in the question.
apps/
server.py -- runs the WSGI Server
app1/
api/ -- contains the business logic
controller/ -- makes the interface between HTTP and the API
lib/
model/
app.py -- provides a function get_wsgi_app(name, config, app_instance_name)
url.py -- like django, makes a binding between urls and controller
app2/
-- same as app1
common/ -- All common classes and modules. Folders are the same that apps.
api/
controller/
lib/
model/
configs/
app1.cfg
app2.cfg
server.cfg
How does it works :
server.py is the entry point. His role is to start the WSGI Server and mount the WSGI Applications. app.py instanciates the application and loads it's config. (you can have multiple instance of app1)
urls.py contains the application's URLs.
When I need to import a module, I just use an absolute import starting from the app folder.
Ex :
from app1.api.my_module import API
from common.api.login_api import LoginAPI
class Foo():
...
I never tried to use relative imports because I prefer when it is explicit, especially in that case where the folders are often named the same.