testrail-python
testrail-python copied to clipboard
Config collision when creating multiple client instances
It is not possible to create multiple client instances to different testrail accounts within a single session. A brief glance at the code in api.py
suggests it's probably related to config settings being stored in API
class attributes.
In [1]: from testrail import TestRail
In [2]: tr1 = TestRail(project_id=1, email='[email protected]', key='abc123', url='https://foo.testrail.net')
In [3]: tr2 = TestRail(project_id=1, email='[email protected]', key='xyz999', url='https://bar.testrail.net')
In [4]: tr2.api._config
Out[4]:
{'email': '[email protected]',
'key': 'xyz999',
'url': 'https://bar.testrail.net'}
In [5]: tr1.api._config
Out[5]:
{'email': '[email protected]',
'key': 'xyz999',
'url': 'https://bar.testrail.net'}
I thought there was a reason it was done this way but I can't recall what it was. That being said you have a very valid use case. I will look into it tonight.
They were stored as class attributes because of the way the API class is instantiated in multiple places throughout the code.
Yeah this is going to be a bigger issue than I thought. The way we store our cache in shared state will clobber multiple instances as well.
Yeah, so we make very heavy use of the fact that that API class using the borg pattern. So multiple instances will not work without a fairly heavy refactor. PRs are welcome but this is not something that I will plan to do unless it becomes a major issue.
@lbjay is this a showstopper for you? What are you trying to accomplish? Maybe we can find a different way to achieve it.
After digging around in the code for a bit, I concur with Travis: it would take a non-trivial refactoring of the code to make your example work.
One thing I just noticed while debugging something: the changes to API
to store the credentials in the a class attribute are in the master branch, but haven't been officially released to PyPI yet. This may or not be affecting @lbjay, depending on if he is using the tip of master, or the 3.7 on PyPI.
I pushed master to 0.3.8 on PyPI. While a major hack, and slower it may work to set api._timeout to 0. The two instances will constantly clobber each other but being the cache will always be marked as stale it wouldn't matter. This assumes of course that the processes are not running in parallel.
I've been looking at this off and on all day. For future reference, there are two options that I can see to make multiple clients work within the same python process:
-
Create a client id with each testrail client, and use a combination performing object introspection on the calling object and overriding the
__new__
constructor ofTestRaileBase
to propagate the client id throughout the system. This would require the least amount of code change, but breaks encapsulation. Additionally, the introspection method involves using python'sinspect
module to inspect the previous frame, and this is frowned upon by the python community for anything but debugging. -
Create a client id with each testrail client, and explicitly propagate that through the system by including it with every testrail object instantiation. The API would be modified to map client connection configurations and
_shared_state
objects to the client ids. This would be the cleanest approach, but would touch a significant portion of the code base.
In either case, I'm not sure its possible to make multiple client instances work AND keep the borg design pattern of API
intact.