-
Notifications
You must be signed in to change notification settings - Fork 34
SAGA Python Internal Developer Notes
These are notes for SAGA-Python developers. If you're writing SAGA-Python adaptors or patching the engine, these could be useful for you!
You can fix small bugs on devel, no problem, and then merge or rebase to the feature branches to benefit from the fix. Larger fixes (i.e. which will likely be worked on for a while and consist of multiple commits) may justify their own temporary branch, to make sure that devel remains in a usable state.
Fixes on master (i.e. on releases) are handled differently: there you always create a hotfix branch, so that you can merge it to both master (for a errata release), and to devel (where you likely need that fix as well). That should be done only for fixes which make a release kind of unusable.
So, you should get changes from devel into your feature branch with
git merge devel
or
git rebase devel
whichever you prefer more ('rebase' will delete the commit history of your branch, and squash all commits into one -- it will look like you branched one commit ago, not x commits ago -- 'merge' will keep your history).
Ole: Looking at existing adaptors, I have noticed that you generally don't write ERROR log messages when you throw an exception. This can be problematic when analyzing logs post-mortem because you simply won't see any errors!
Andre M: I saw your log_error_and_raise, and liked it, but wanted to keep explicit 'raise' calls in the code to make the intent very obvious. So I added a static member to the exception class, and you can now do:
raise saga.BadParameter._log (self._logger, "No no no no NO! No integers, please!!")
see saga.utils.exception.py, where you'll also find some documentation actually). This also keeps the stack trace clean -- which, btw, you can now simply print to the debug log stream with
self._logger.trace ()
When adding new adaptors, for SAGA-Python to see them you need to make modifications to setup.py, saga/engine/engine.py, and don't forget that you need an empty __init.py__ file in your adaptor directory as well! (AM working on changing this latter requirement, may change) Why do you have to do this? Find out here: http://effbot.org/pyfaq/what-is-init-py-used-for.htm
FWIW, if you want to check the set of adaptors registered by the engine, you can do:
e = saga.engine.engine.Engine ()
e._dump ()
While coding an adaptor if you get an error of type:
Traceback (most recent call last):
File "examples/jobs/slurm/slurm.py", line 77, in main
print "Exitcode :", catjob.exit_code
File "/home/azebro1/saga-python-env/lib/python2.7/site-packages/saga/attributes.py", line 2236, in __getattr__
return self._attributes_i_get (key, flow=self._DOWN)
File "/home/azebro1/saga-python-env/lib/python2.7/site-packages/saga/attributes.py", line 1017, in _attributes_i_get
self._attributes_t_call_getter (key)
File "/home/azebro1/saga-python-env/lib/python2.7/site-packages/saga/attributes.py", line 593, in _attributes_t_call_getter
if not retries : raise e
TypeError: get_exit_code() got an unexpected keyword argument 'ttype'
Exitcode : *** get_exit_code() got an unexpected keyword argument 'ttype'
then you're probably missing a @SYNC_CALL/@ASYNC_CALL decorator!
@SYNC_CALL
def get_exit_code(self) :
Add it in and the error should clear up.
You may have something like:
"job_attributes" : [saga.job.EXIT_CODE,
saga.job.EXECUTION_HOSTS,
saga.job.CREATED,
saga.job.STARTED,
saga.job.FINISHED],
and
@SYNC_CALL
def get_created(self) :
return self._created
but the following call from an external script will fail:
print catjob.get_created()
with error message:
Traceback (most recent call last):
File "examples/jobs/slurmssh.py", line 86, in main
print catjob.get_created()
File "/home/azebro1/saga-python-env/lib/python2.7/site-packages/saga/attributes.py", line 2236, in __getattr__
return self._attributes_i_get (key, flow=self._DOWN)
File "/home/azebro1/saga-python-env/lib/python2.7/site-packages/saga/attributes.py", line 1014, in _attributes_i_get
d = self._attributes_t_init (key)
File "/home/azebro1/saga-python-env/lib/python2.7/site-packages/saga/attributes.py", line 372, in _attributes_t_init
raise DoesNotExist ("attribute key is invalid: %s" % (key))
DoesNotExist: attribute key is invalid: get_created
*** attribute key is invalid: get_created
That's because get_created is an internal accessor method, which is not part of the API. On API level, you should see the attribute job.created, which, if accessed, will call your adaptor method...
So
print catjob.get_created()
should be
print catjob.created
and then it will work as intended!