Author: jure
Date: Wed Jan 30 11:14:17 2013
New Revision: 1440346
URL: http://svn.apache.org/viewvc?rev=1440346&view=rev
Log:
#288, product environment context manager from
t288_r1438538_sql_translate_global_env.diff (from olemis) and some changes to
make it work properly
Modified:
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_dashboard/bhdashboard/model.py
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/api.py
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/dbcursor.py
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/env.py
Modified:
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_dashboard/bhdashboard/model.py
URL:
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_dashboard/bhdashboard/model.py?rev=1440346&r1=1440345&r2=1440346&view=diff
==============================================================================
---
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_dashboard/bhdashboard/model.py
(original)
+++
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_dashboard/bhdashboard/model.py
Wed Jan 30 11:14:17 2013
@@ -158,7 +158,7 @@ class ModelBase(object):
sdata)
for key in self._meta['key_fields']:
- if not self._data[key]:
+ if self._data[key] is None:
sdata = {'key':key}
sdata.update(self._meta)
raise TracError('%(key)s required for %(object_name)s' %
Modified:
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/api.py
URL:
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/api.py?rev=1440346&r1=1440345&r2=1440346&view=diff
==============================================================================
---
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/api.py
(original)
+++
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/api.py
Wed Jan 30 11:14:17 2013
@@ -118,10 +118,13 @@ class MultiProductSystem(Component):
db_installed_version = self._update_db_version(db, 2)
if db_installed_version < 3:
- from multiproduct.dbcursor import DEFAULT_PRODUCT
from multiproduct.model import Product
import trac.db_default
+
+ DEFAULT_PRODUCT = 'default'
+
migrate_tables = ['enum', 'component', 'milestone', 'version',
'permission', 'wiki']
+
# extend trac default schema by adding product column and
extending key with product
table_defs = [copy.deepcopy(t) for t in trac.db_default.schema
if t.name in migrate_tables]
for t in table_defs:
Modified:
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/dbcursor.py
URL:
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/dbcursor.py?rev=1440346&r1=1440345&r2=1440346&view=diff
==============================================================================
---
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/dbcursor.py
(original)
+++
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/dbcursor.py
Wed Jan 30 11:14:17 2013
@@ -35,7 +35,7 @@ SKIP_TABLES = ['system', 'auth_cookie',
]
TRANSLATE_TABLES = ['ticket', 'enum', 'component', 'milestone', 'version',
'permission', 'wiki']
PRODUCT_COLUMN = 'product'
-DEFAULT_PRODUCT = 'default'
+DEFAULT_PRODUCT = ''
class BloodhoundIterableCursor(trac.db.util.IterableCursor):
__slots__ = trac.db.util.IterableCursor.__slots__ + ['_translator']
@@ -72,6 +72,63 @@ class BloodhoundIterableCursor(trac.db.u
def set_env(cls, env):
cls._tls.env = env
+ @classmethod
+ def get_env(cls):
+ return cls._tls.env
+
+class ProductEnvContextManager(object):
+ """Wrap an underlying database context manager so as to keep track
+ of (nested) product context.
+ """
+ def __init__(self, context, env=None):
+ """Initialize product database context.
+
+ :param context: Inner database context (e.g. `QueryContextManager`,
+ `TransactionContextManager` )
+ :param env: An instance of either `trac.env.Environment` or
+ `multiproduct.env.ProductEnvironment` used to
+ reduce the scope of database queries. If set
+ to `None` then SQL queries will not be translated,
+ which is equivalent to having direct database access.
+ """
+ self.db_context = context
+ self.env = env
+
+ def __enter__(self):
+ """Keep track of previous product context and override it with `env`;
+ then enter the inner database context.
+ """
+ self._last_env = BloodhoundIterableCursor.get_env()
+ BloodhoundIterableCursor.set_env(self.env)
+ return self.db_context.__enter__()
+
+ def __exit__(self, et, ev, tb):
+ """Uninstall current product context by restoring the last one;
+ then leave the inner database context.
+ """
+ BloodhoundIterableCursor.set_env(self._last_env)
+ del self._last_env
+ return self.db_context.__exit__(et, ev, tb)
+
+ def __call__(self, *args, **kwargs):
+ """Forward attribute access to nested database context on failure.
+ """
+ BloodhoundIterableCursor.set_env(self.env)
+ return self.db_context(*args, **kwargs)
+
+ def __getattr__(self, attrnm):
+ """Forward attribute access to nested database context on failure.
+ """
+ return getattr(self.db_context, attrnm)
+
+ def execute(self, sql, params=None):
+ BloodhoundIterableCursor.set_env(self.env)
+ return self.db_context.execute(sql, params=params)
+
+ def executemany(self, sql, params=None):
+ BloodhoundIterableCursor.set_env(self.env)
+ return self.db_context.executemany(sql, params=params)
+
# replace trac.db.util.IterableCursor with BloodhoundIterableCursor
trac.db.util.IterableCursor = BloodhoundIterableCursor
Modified:
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/env.py
URL:
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/env.py?rev=1440346&r1=1440345&r2=1440346&view=diff
==============================================================================
---
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/env.py
(original)
+++
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_multiproduct/multiproduct/env.py
Wed Jan 30 11:14:17 2013
@@ -23,7 +23,7 @@ from urlparse import urlsplit
from trac.config import ConfigSection, Option
from trac.core import Component, ComponentManager, implements
-from trac.db.api import with_transaction, TransactionContextManager,
QueryContextManager
+from trac.db.api import TransactionContextManager, QueryContextManager
from trac.util import get_pkginfo, lazy
from trac.util.compat import sha1
from trac.versioncontrol import RepositoryManager
@@ -31,8 +31,8 @@ from trac.web.href import Href
from multiproduct.api import MultiProductSystem
from multiproduct.config import Configuration
+from multiproduct.dbcursor import ProductEnvContextManager
from multiproduct.model import Product
-from multiproduct.dbcursor import BloodhoundIterableCursor
import trac.env
@@ -54,13 +54,19 @@ class Environment(trac.env.Environment):
@property
def db_query(self):
- BloodhoundIterableCursor.set_env(self)
- return super(Environment, self).db_query
+ return ProductEnvContextManager(super(Environment, self).db_query,
self)
@property
def db_transaction(self):
- BloodhoundIterableCursor.set_env(self)
- return super(Environment, self).db_transaction
+ return ProductEnvContextManager(super(Environment,
self).db_transaction, self)
+
+ @property
+ def db_direct_query(self):
+ return ProductEnvContextManager(super(Environment, self).db_query)
+
+ @property
+ def db_direct_transaction(self):
+ return ProductEnvContextManager(super(Environment,
self).db_transaction)
# replace trac.env.Environment with Environment
trac.env.Environment = Environment
@@ -84,16 +90,6 @@ class EnvironmentStub(trac.test.Environm
enable=enable, disable=disable,
path=path, destroying=destroying)
- @property
- def db_query(self):
- BloodhoundIterableCursor.set_env(self)
- return super(EnvironmentStub, self).db_query
-
- @property
- def db_transaction(self):
- BloodhoundIterableCursor.set_env(self)
- return super(EnvironmentStub, self).db_transaction
-
# replace trac.test.EnvironmentStub
trac.test.EnvironmentStub = EnvironmentStub
@@ -349,15 +345,16 @@ class ProductEnvironment(Component, Comp
return self.parent.db_exc()
def with_transaction(self, db=None):
- """Decorator for transaction functions :deprecated:"""
- return with_transaction(self, db)
+ """Decorator for transaction functions :deprecated:
+ """
+ raise NotImplementedError('Deprecated method')
def get_read_db(self):
"""Return a database connection for read purposes :deprecated:
- See `trac.db.api.get_read_db` for detailed documentation."""
- # database connection is shared with global environment
- return self.parent.get_read_db()
+ See `trac.db.api.get_read_db` for detailed documentation.
+ """
+ raise NotImplementedError('Deprecated method')
@property
def db_query(self):
@@ -391,8 +388,7 @@ class ProductEnvironment(Component, Comp
context was the outermost context (`db_query` or
`db_transaction`).
"""
- BloodhoundIterableCursor.set_env(self)
- return QueryContextManager(self.parent)
+ return ProductEnvContextManager(QueryContextManager(self.parent), self)
@property
def db_transaction(self):
@@ -427,8 +423,7 @@ class ProductEnvironment(Component, Comp
context, if this context was the outermost context
(`db_query` or `db_transaction`).
"""
- BloodhoundIterableCursor.set_env(self)
- return TransactionContextManager(self.parent)
+ return
ProductEnvContextManager(TransactionContextManager(self.parent), self)
def shutdown(self, tid=None):
"""Close the environment."""