1

I'm currently writing an internal abstraction layer in Python to help our developers talk to our internal data store without exposing them to the details.

Some parts of the abstraction layer require various connections and configuration (like paths, database connection, etc.) and since we would like to stay as flexible as possible we decided to abstract away the details. For this I have created a Configuration class that has a bunch of unimplemented methods to get the details that are needed internally:

class Configuration:

    def get_mongo_client(self):
        """
        :returns: a :py:class:`pymongo.MongoClient` instance that should be used \
        for talking to the database
        """
        raise NotImplementedError()

    # more getters...

Now, lets say I have a Users class that requires a Configuration instance internally. What would be the best way to make it available? I would really like to *avoid making Configuration a parameter to __init__. Are there any other ways to pass it around? Is there some kind of process local store that i could use?

Martin Thurau
  • 7,564
  • 7
  • 43
  • 80
  • 4
    "Explicit is better than implicit"... – Daniel Roseman Jan 13 '14 at 13:46
  • Why don't you want it in `__init__`? – Steinar Lima Jan 13 '14 at 13:47
  • 1
    This doesn't answer your question - but facing the same problem I realized it was simpler to expose the shared functionality _especially as it was database related_ as an internal (REST) API. Not only did this make integration a breeze, but as an added bonus it made tracking use of the data store a non-issue. Something to think about. – Burhan Khalid Jan 13 '14 at 14:12

2 Answers2

0

You have a couple of choice here. The best is probably to pass a configuration instance as a parameter to init. As Daniel Roseman points out above "Explicit is better than implicit". Alternatively you can set up a global variable that contains an instance of the Configuration and can be accessed where needed. But obviously global variables should be avoided. Lastly you can use a singleton pattern although this is little better than a global variable in many ways. The singleton is described here:

http://en.wikipedia.org/wiki/Singleton_pattern

but basically it would allow you to create a new instance of the Configuration object wherever you need to use its information but because of the way it is created you will get back a reference to the same Configuration instance with the same internal data.

So something like:

    def SingletonConfiguration():
    # implementation

    config = SingletonConfiguration()
    config.Setup()
    # Do any configuration ended of instance

   class UseConfig():
       def __init__():
           a = SingletonConfiguration() # will return same config instance as was
                                        # previously setup
           a.getconfig()

More info on the singleton in python can be seen here:

Python and the Singleton Pattern

If you do not want to pass an instance of Configuration into init then a singleton is probably the way to go. Bare in mind though that it has similar problems to a global variable though. While it is not as visible in the global namespace any modification to any singleton instance will modify its value wherever it is used. So completely different parts of your application are now tied together and can interact in possibly bad ways in a way that is difficult to see and debug. If a relationship is needed between two parts of your program then it is far better to explicitly add it in as you would with a partner passed to init then to have it with a more concealed interface like this.

Community
  • 1
  • 1
Tommy
  • 622
  • 5
  • 8
0

You can try using whs.commons.abc. It provides Session abstraction. You can create your own Session class, in which you can implement at_begin and at_end hooks, then you can register it by decorating with Session.use (import Session from whs.commons.abc.session). Now, at the beginning of your app use Session().begin() with any arguments you need (they will be passed to at_begin kwargs) and Session().end() at the end of your program. Session object is already a Singleton so you can use it to store configuration data (maybe as single Config object?).

Unfortunately, this package has no online docs, but you can unpack its source and check what modules are there and what is in those modules (docstrings are pretty good there, I think).

Filip Malczak
  • 3,124
  • 24
  • 44