dataflake: Apologies for increasing the size of the patch, I took the opportunity to do some of those cleanups we have been doing in other packages so that the tests have a common configuration and pass.

The version pin in `setup.py` will introduce a version conflict in Zope itself. Maybe it's easier to just fix the incompatibility for real?
dataflake: @icemac I added a "real" fix in 2f732e5bd52b80ca61ac04318bc689ed09b65769 and think this is ready to go. The `register` call was done in test code only so there is no change in production code behavior at all. Take a look and let me know or merge yourself.
icemac: @dataflake Thank you for actually fixing the problem. I cannot approve my own PR so I am going to merge it. Should we cut a new release or does it not matter as the change is only in test code?
diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 162b92a..0000000
--- a/.coveragerc
+++ /dev/null
@@ -1,6 +0,0 @@
-[run]
-branch = True
-source = Products.Sessions
-
-[report]
-precision = 2
diff --git a/.travis.yml b/.travis.yml
index e7790a7..7728cb7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,11 +3,8 @@ language: python
 matrix:
     include:
         - python: "3.7"
-          env: TOXENV=lint-py37
-        - python: "3.7"
-          env: TOXENV=coverage-report
+          env: TOXENV=lint
           after_success:
-              - coveralls
         - python: "2.7"
           env: TOXENV=py27
         - python: "3.5"
@@ -16,17 +13,19 @@ matrix:
           env: TOXENV=py36
         - python: "3.7"
           env: TOXENV=py37
-          dist: xenial
         - python: "3.8"
           env: TOXENV=py38
-          dist: xenial
 
 install:
-    - travis_retry pip install -U pip setuptools tox
-    - travis_retry pip install -U coverage coveralls
+    - pip install -U pip setuptools tox
+    - pip install -U coverage coveralls
 
 script:
-    - travis_retry tox
+    - tox
+
+after_success:
+    - coverage combine
+    - coveralls
 
 notifications:
     email: false
diff --git a/CHANGES.rst b/CHANGES.rst
index f8b52d7..5791452 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,6 +4,9 @@ Changelog
 4.7 (unreleased)
 ----------------
 
+- Make the product compatible with ``transaction`` version 3
+  (`#32 <https://github.com/zopefoundation/Products.Sessions/issues/32>`_)
+
 
 4.6 (2019-10-12)
 ----------------
diff --git a/MANIFEST.in b/MANIFEST.in
index ca7f877..b3f90a1 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,5 @@
 include *.txt
 include *.rst
-include .coveragerc
 include tox.ini
 
 exclude MANIFEST.in
diff --git a/buildout.cfg b/buildout.cfg
index 8c74e49..8e2ad9b 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -5,7 +5,6 @@ develop = .
 parts = 
     interpreter
     test
-    tox
 
 [versions]
 Products.Sessions =
@@ -18,7 +17,3 @@ eggs = Products.Sessions
 [test]
 recipe = zc.recipe.testrunner
 eggs = Products.Sessions[tests]
-
-[tox]
-recipe = zc.recipe.egg
-eggs = tox
diff --git a/setup.cfg b/setup.cfg
index 3f9ee1a..cabf35f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -9,11 +9,11 @@ combine_as_imports = True
 sections = FUTURE,STDLIB,THIRDPARTY,ZOPE,FIRSTPARTY,LOCALFOLDER
 known_third_party = six
 known_zope = Products
+known_first_party = Products.TemporaryFolder
+known_local_folder = Products.Sessions, Products.Transience
 default_section = ZOPE
 line_length = 79
 lines_after_imports = 2
-not_skip =
-    __init__.py
 
 [flake8]
 ignore =
@@ -26,9 +26,9 @@ ignore =
     N812,
     # For now also ignore following checks:
     T000
-
 exclude =
     bootstrap.py
+doctests = True
 no-accept-encodings = True
 
 [bdist_wheel]
@@ -36,7 +36,7 @@ universal = 1
 
 [coverage:run]
 branch = True
-source = src
+source = Products.Sessions
 omit =
 
 [coverage:report]
@@ -45,4 +45,4 @@ show_missing = True
 sort = Name
 
 [coverage:html]
-directory = _build/coverage
+directory = parts/coverage
diff --git a/src/Products/Sessions/BrowserIdManager.py b/src/Products/Sessions/BrowserIdManager.py
index 45d6275..9a6a1a4 100644
--- a/src/Products/Sessions/BrowserIdManager.py
+++ b/src/Products/Sessions/BrowserIdManager.py
@@ -39,17 +39,17 @@ from OFS.role import RoleManager
 from OFS.SimpleItem import Item
 from Persistence import Persistent
 from persistent import TimeStamp
-from Products.Sessions.interfaces import BrowserIdManagerErr
-from Products.Sessions.interfaces import IBrowserIdManager
-from Products.Sessions.SessionPermissions import ACCESS_CONTENTS_PERM
-from Products.Sessions.SessionPermissions import CHANGE_IDMGR_PERM
-from Products.Sessions.SessionPermissions import MGMT_SCREEN_PERM
 from zope.interface import implementer
 from ZPublisher.BeforeTraverse import queryBeforeTraverse
 from ZPublisher.BeforeTraverse import registerBeforeTraverse
 from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
 
 from ._compat import html_escape as escape
+from .interfaces import BrowserIdManagerErr
+from .interfaces import IBrowserIdManager
+from .SessionPermissions import ACCESS_CONTENTS_PERM
+from .SessionPermissions import CHANGE_IDMGR_PERM
+from .SessionPermissions import MGMT_SCREEN_PERM
 
 
 badidnamecharsin = re.compile(r'[\?&;,<> ]').search
diff --git a/src/Products/Sessions/SessionDataManager.py b/src/Products/Sessions/SessionDataManager.py
index c9b8fdc..abeb782 100644
--- a/src/Products/Sessions/SessionDataManager.py
+++ b/src/Products/Sessions/SessionDataManager.py
@@ -26,6 +26,11 @@ from OFS.owner import Owned
 from OFS.role import RoleManager
 from OFS.SimpleItem import Item
 from Persistence import Persistent
+from ZODB.POSException import ConflictError
+from zope.interface import implementer
+from ZPublisher.BeforeTraverse import registerBeforeTraverse
+from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
+
 from Products.Sessions.BrowserIdManager import BROWSERID_MANAGER_NAME
 from Products.Sessions.common import DEBUG
 from Products.Sessions.interfaces import ISessionDataManager
@@ -35,10 +40,6 @@ from Products.Sessions.SessionPermissions import ACCESS_SESSIONDATA_PERM
 from Products.Sessions.SessionPermissions import ARBITRARY_SESSIONDATA_PERM
 from Products.Sessions.SessionPermissions import CHANGE_DATAMGR_PERM
 from Products.Sessions.SessionPermissions import MGMT_SCREEN_PERM
-from ZODB.POSException import ConflictError
-from zope.interface import implementer
-from ZPublisher.BeforeTraverse import registerBeforeTraverse
-from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
 
 
 bad_path_chars_in = re.compile(r'[^a-zA-Z0-9-_~\,\. \/]').search
diff --git a/src/Products/Transience/TransactionHelper.py b/src/Products/Transience/TransactionHelper.py
index f97e86b..0eb8ec8 100644
--- a/src/Products/Transience/TransactionHelper.py
+++ b/src/Products/Transience/TransactionHelper.py
@@ -18,10 +18,10 @@ class UncommittableJar:
     def sortKey(self):
         return str(id(self))
 
-    def tpc_begin(self, *arg, **kw):
+    def tpc_begin(self, *args):
         pass
 
-    def commit(self, obj, transaction):
+    def commit(self, *args):
         pass
 
     def tpc_vote(self, transaction):
@@ -38,4 +38,4 @@ class makeTransactionUncommittable:
     """
     def __init__(self, transaction, reason):
         self._p_jar = UncommittableJar(reason)
-        transaction.register(self)
+        transaction.join(self._p_jar)
diff --git a/src/Products/Transience/Transience.py b/src/Products/Transience/Transience.py
index be274aa..e36b2f9 100644
--- a/src/Products/Transience/Transience.py
+++ b/src/Products/Transience/Transience.py
@@ -35,13 +35,13 @@ from BTrees.Length import Length as BTreesLength
 from BTrees.OOBTree import OOBTree
 from OFS.SimpleItem import SimpleItem
 from Persistence import Persistent
-from Products.Transience.TransienceInterfaces import ItemWithId
-from Products.Transience.TransienceInterfaces import \
-    StringKeyedHomogeneousItemContainer
-from Products.Transience.TransienceInterfaces import TransientItemContainer
-from Products.Transience.TransientObject import TransientObject
 from zope.interface import implementer
 
+from .TransienceInterfaces import ItemWithId
+from .TransienceInterfaces import StringKeyedHomogeneousItemContainer
+from .TransienceInterfaces import TransientItemContainer
+from .TransientObject import TransientObject
+
 
 try:
     from html import escape as html_escape
diff --git a/src/Products/Transience/TransientObject.py b/src/Products/Transience/TransientObject.py
index 8c33046..c588990 100644
--- a/src/Products/Transience/TransientObject.py
+++ b/src/Products/Transience/TransientObject.py
@@ -26,16 +26,16 @@ from AccessControl.class_init import InitializeClass
 from AccessControl.SecurityInfo import ClassSecurityInfo
 from Acquisition import Implicit
 from Persistence import Persistent
-from Products.Transience.TransienceInterfaces import DictionaryLike
-from Products.Transience.TransienceInterfaces import \
-    ImmutablyValuedMappingOfPickleableObjects  # NOQA: E501
-from Products.Transience.TransienceInterfaces import ItemWithId
-from Products.Transience.TransienceInterfaces import Transient
-from Products.Transience.TransienceInterfaces import TransientItemContainer
-from Products.Transience.TransienceInterfaces import TTWDictionary
 from ZODB.POSException import ConflictError
 from zope.interface import implementer
 
+from .TransienceInterfaces import DictionaryLike
+from .TransienceInterfaces import ImmutablyValuedMappingOfPickleableObjects
+from .TransienceInterfaces import ItemWithId
+from .TransienceInterfaces import Transient
+from .TransienceInterfaces import TransientItemContainer
+from .TransienceInterfaces import TTWDictionary
+
 
 DEBUG = int(os.environ.get('Z_TOC_DEBUG', 0))
 LOG = logging.getLogger('Zope.TransientObject')
diff --git a/tox.ini b/tox.ini
index f147e15..f6b2817 100644
--- a/tox.ini
+++ b/tox.ini
@@ -5,45 +5,47 @@ envlist =
     py36,
     py37,
     py38,
-    lint-py37,
+    lint,
     coverage-report,
 
 [testenv]
 skip_install = true
 commands =
-    {envbindir}/buildout -c {toxinidir}/buildout.cfg buildout:directory={envdir} buildout:develop={toxinidir} bootstrap
     {envbindir}/buildout -c {toxinidir}/buildout.cfg buildout:directory={envdir} buildout:develop={toxinidir} install test
-    {envbindir}/test --all {posargs:-vc}
+    coverage run {envbindir}/test --all {posargs:-vc}
 deps =
+    coverage
     zc.buildout
+setenv =
+    COVERAGE_FILE=.coverage.{envname}
 
 [testenv:coverage-report]
 basepython = python3.7
 commands =
-    {envbindir}/buildout -c {toxinidir}/buildout.cfg buildout:directory={envdir} buildout:develop={toxinidir} bootstrap
-    {envbindir}/buildout -c {toxinidir}/buildout.cfg buildout:directory={envdir} buildout:develop={toxinidir} install test
     coverage erase
-    coverage run {envbindir}/test {posargs:-cv}
+    coverage combine
     coverage html -i
     coverage xml -i
     coverage report -i --fail-under=91
 deps =
     {[testenv]deps}
-    coverage
+depends =
+    py27,
+    py35,
+    py36,
+    py37,
+    py38,
 setenv =
     COVERAGE_FILE=.coverage
 
-[testenv:isort-apply]
+
+[testenv:lint]
 basepython = python3.7
 skip_install = true
-deps =
-    isort
 
 commands =
-    isort --apply --recursive {toxinidir}/src setup.py {posargs}
-
-[lint]
-skip_install = true
+    - isort --check-only --diff {toxinidir}/src setup.py
+    flake8 src setup.py --doctests
 
 deps =
     isort
@@ -56,7 +58,6 @@ deps =
     flake8-deprecated
     flake8-pytest
     flake8-todo
-    flake8-isort
     mccabe
     # Potential flake8 plugins that should be used:  # TBD
     #flake8-blind-except
@@ -69,18 +70,5 @@ deps =
     #flake8_strict
     #flake8-quotes
 
-commands =
-    mkdir -p {toxinidir}/_build/flake8
-    - flake8 --format=html --htmldir={toxinidir}/_build/flake8 --doctests src setup.py
-    flake8 src setup.py --doctests
-    isort --check-only --recursive {toxinidir}/src setup.py
-
 whitelist_externals =
     mkdir
-
-[testenv:lint-py37]
-basepython = python3.7
-skip_install = true
-deps = {[lint]deps}
-commands = {[lint]commands}
-whitelist_externals = {[lint]whitelist_externals}

All builds are broken
```
Error in test testUncommittable (Products.Transience.tests.testTransactionHelper.TestTransactionHelper)
Traceback (most recent call last):
  File "/opt/python/2.7.15/lib/python2.7/unittest/case.py", line 329, in run
    testMethod()
  File "/home/travis/build/zopefoundation/Products.Sessions/src/Products/Transience/tests/testTransactionHelper.py", line 30, in testUncommittable
    makeTransactionUncommittable(self.t, "test")
  File "/home/travis/build/zopefoundation/Products.Sessions/src/Products/Transience/TransactionHelper.py", line 41, in __init__
    transaction.register(self)
AttributeError: 'Transaction' object has no attribute 'register'
```

https://travis-ci.org/github/zopefoundation/Products.Sessions

@icemac mentioned in the wrap up of the Zope sprint, that this is no easy fix
diff --git a/src/Products/Sessions/stresstests/stresstestMultiThread.py b/src/Products/Sessions/stresstests/stresstestMultiThread.py
index e1baa2f..6a1f283 100644
--- a/src/Products/Sessions/stresstests/stresstestMultiThread.py
+++ b/src/Products/Sessions/stresstests/stresstestMultiThread.py
@@ -22,23 +22,25 @@ from unittest import TestSuite
 from unittest import makeSuite
 
 import Acquisition
-import Products.Transience.Transience
-import Products.Transience.TransientObject
 import transaction
 import ZODB  # in order to get Persistence.Persistent working
 from OFS.Application import Application
-from Products.Sessions.BrowserIdManager import BrowserIdManager
-from Products.Sessions.BrowserIdManager import getNewBrowserId
-from Products.Sessions.SessionDataManager import SessionDataManager
-from Products.TemporaryFolder.TemporaryFolder import MountedTemporaryFolder
-from Products.Transience.tests import fauxtime
-from Products.Transience.Transience import TransientObjectContainer
 from Testing import makerequest
 from ZODB.DemoStorage import DemoStorage
 from ZODB.POSException import BTreesConflictError
 from ZODB.POSException import ConflictError
 from ZODB.POSException import ReadConflictError
 
+from Products.TemporaryFolder.TemporaryFolder import MountedTemporaryFolder
+
+import Products.Transience.Transience
+import Products.Transience.TransientObject
+from Products.Sessions.BrowserIdManager import BrowserIdManager
+from Products.Sessions.BrowserIdManager import getNewBrowserId
+from Products.Sessions.SessionDataManager import SessionDataManager
+from Products.Transience.tests import fauxtime
+from Products.Transience.Transience import TransientObjectContainer
+
 
 Products.Transience.Transience.time = fauxtime
 Products.Transience.TransientObject.time = fauxtime
diff --git a/src/Products/Sessions/tests/testBrowserIdManager.py b/src/Products/Sessions/tests/testBrowserIdManager.py
index 3fc61ae..d4aa5f3 100644
--- a/src/Products/Sessions/tests/testBrowserIdManager.py
+++ b/src/Products/Sessions/tests/testBrowserIdManager.py
@@ -558,8 +558,8 @@ class TestBrowserIdManager(unittest.TestCase):
     def test_updateTraversalData_w_url_ns(self):
         from Acquisition import Implicit
         from ZPublisher.BeforeTraverse import queryBeforeTraverse
-        from Products.Sessions.BrowserIdManager import \
-            BrowserIdManagerTraverser
+
+        from ..BrowserIdManager import BrowserIdManagerTraverser
 
         class Parent(Implicit):
             pass
@@ -610,8 +610,8 @@ class TestBrowserIdManager(unittest.TestCase):
     def test_registerTraversalHook_normal(self):
         from Acquisition import Implicit
         from ZPublisher.BeforeTraverse import queryBeforeTraverse
-        from Products.Sessions.BrowserIdManager import \
-            BrowserIdManagerTraverser
+
+        from ..BrowserIdManager import BrowserIdManagerTraverser
 
         class Parent(Implicit):
             pass
@@ -654,8 +654,7 @@ class TestBrowserIdManager(unittest.TestCase):
 class TestBrowserIdManagerTraverser(unittest.TestCase):
 
     def _getTargetClass(self):
-        from Products.Sessions.BrowserIdManager \
-            import BrowserIdManagerTraverser
+        from ..BrowserIdManager import BrowserIdManagerTraverser
         return BrowserIdManagerTraverser
 
     def _makeOne(self):
diff --git a/src/Products/Sessions/tests/testSessionDataManager.py b/src/Products/Sessions/tests/testSessionDataManager.py
index c92bd44..dd67802 100644
--- a/src/Products/Sessions/tests/testSessionDataManager.py
+++ b/src/Products/Sessions/tests/testSessionDataManager.py
@@ -22,8 +22,8 @@ stuff = {}
 
 
 def _getDB():
-    from OFS.Application import Application
     import transaction
+    from OFS.Application import Application
     db = stuff.get('db')
     if not db:
         from ZODB import DB
@@ -48,12 +48,14 @@ def _delDB():
 
 
 def _populate(app):
+    import transaction
     from OFS.DTMLMethod import DTMLMethod
+
+    from Products.TemporaryFolder.TemporaryFolder import MountedTemporaryFolder
+
     from Products.Sessions.BrowserIdManager import BrowserIdManager
     from Products.Sessions.SessionDataManager import SessionDataManager
-    from Products.TemporaryFolder.TemporaryFolder import MountedTemporaryFolder
     from Products.Transience.Transience import TransientObjectContainer
-    import transaction
     bidmgr = BrowserIdManager(idmgr_name)
     tf = MountedTemporaryFolder(tf_name, title="Temporary Folder")
     toc = TransientObjectContainer(
@@ -156,7 +158,9 @@ class TestSessionManager(unittest.TestCase):
 
     def testNewSessionDataObjectIsValid(self):
         from Acquisition import aq_base
+
         from Products.Transience.Transience import TransientObject
+
         sdType = type(TransientObject(1))
         sd = self.app.session_data_manager.getSessionData()
         self.assertTrue(type(aq_base(sd)) is sdType)
@@ -205,8 +209,8 @@ class TestSessionManager(unittest.TestCase):
 
     def testSubcommitAssignsPJar(self):
         global DummyPersistent  # so pickle can find it
-        from Persistence import Persistent
         import transaction
+        from Persistence import Persistent
 
         class DummyPersistent(Persistent):
             pass
@@ -235,8 +239,8 @@ class TestSessionManager(unittest.TestCase):
         transaction.commit()
 
     def testAqWrappedObjectsFail(self):
-        from Acquisition import Implicit
         import transaction
+        from Acquisition import Implicit
 
         class DummyAqImplicit(Implicit):
             pass
@@ -255,7 +259,9 @@ class TestSessionManager(unittest.TestCase):
 
     def testUnlazifyAutoPopulated(self):
         from Acquisition import aq_base
+
         from Products.Transience.Transience import TransientObject
+
         self.app.REQUEST['PARENTS'] = [self.app]
         self.app.REQUEST['URL'] = 'a'
         self.app.REQUEST.traverse('/')
diff --git a/src/Products/Transience/tests/testTimeoutRelated.py b/src/Products/Transience/tests/testTimeoutRelated.py
index f3e5a81..88bc0b6 100644
--- a/src/Products/Transience/tests/testTimeoutRelated.py
+++ b/src/Products/Transience/tests/testTimeoutRelated.py
@@ -3,15 +3,15 @@ from unittest import TestCase
 from unittest import TestSuite
 from unittest import makeSuite
 
-import Products.Transience.Transience
-import Products.Transience.TransientObject
 import transaction
 import ZODB  # in order to get Persistence.Persistent working
 from OFS.Application import Application
-from Products.Transience.Transience import TransientObjectContainer
 from Testing import makerequest
 from ZODB.DemoStorage import DemoStorage
 
+import Products.Transience.Transience
+import Products.Transience.TransientObject
+from ..Transience import TransientObjectContainer
 from . import fauxtime
 
 
diff --git a/src/Products/Transience/tests/testTransactionHelper.py b/src/Products/Transience/tests/testTransactionHelper.py
index afe404e..963a58d 100644
--- a/src/Products/Transience/tests/testTransactionHelper.py
+++ b/src/Products/Transience/tests/testTransactionHelper.py
@@ -15,8 +15,9 @@ from unittest import TestCase
 from unittest import makeSuite
 
 import transaction
-from Products.Transience.TransactionHelper import PreventTransactionCommit
-from Products.Transience.TransactionHelper import makeTransactionUncommittable
+
+from ..TransactionHelper import PreventTransactionCommit
+from ..TransactionHelper import makeTransactionUncommittable
 
 
 class TestTransactionHelper(TestCase):
diff --git a/src/Products/Transience/tests/testTransientObject.py b/src/Products/Transience/tests/testTransientObject.py
index 231b260..6beadca 100644
--- a/src/Products/Transience/tests/testTransientObject.py
+++ b/src/Products/Transience/tests/testTransientObject.py
@@ -20,8 +20,7 @@ import six
 
 import Products.Transience.Transience
 import Products.Transience.TransientObject
-from Products.Transience.Transience import TransientObjectContainer
-
+from ..Transience import TransientObjectContainer
 from . import fauxtime
 
 
diff --git a/src/Products/Transience/tests/testTransientObjectContainer.py b/src/Products/Transience/tests/testTransientObjectContainer.py
index f637f43..eba7d0c 100644
--- a/src/Products/Transience/tests/testTransientObjectContainer.py
+++ b/src/Products/Transience/tests/testTransientObjectContainer.py
@@ -18,11 +18,10 @@ from unittest import makeSuite
 
 import Products.Transience.Transience
 import Products.Transience.TransientObject
-from Products.Transience.Transience import SPARE_BUCKETS
-from Products.Transience.Transience import MaxTransientObjectsExceeded
-from Products.Transience.Transience import TransientObjectContainer
-from Products.Transience.TransientObject import TransientObject
-
+from ..Transience import SPARE_BUCKETS
+from ..Transience import MaxTransientObjectsExceeded
+from ..Transience import TransientObjectContainer
+from ..TransientObject import TransientObject
 from . import fauxtime
 from . import slowfauxtime
 

pip install -e .[tests]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio
3.7
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
AccessControl==6.3
Acquisition==5.2
AuthEncoding==5.0
beautifulsoup4==4.13.3
BTrees==5.2
certifi @ file:///croot/certifi_1671487769961/work/certifi
cffi==1.15.1
Chameleon==4.2.0
coverage==7.2.7
DateTime==5.5
DocumentTemplate==4.6
exceptiongroup==1.2.2
execnet==2.0.2
ExtensionClass==5.1
importlib-metadata==6.7.0
iniconfig==2.0.0
MultiMapping==5.0
multipart==1.1.0
packaging==24.0
PasteDeploy==3.1.0
Persistence==4.1
persistent==5.2
pluggy==1.2.0
-e git+https://github.com/zopefoundation/Products.Sessions.git@1743e82f8875419a95d71a1f9d3bcfc032ec548c#egg=Products.Sessions
Products.TemporaryFolder==7.0
Products.ZODBMountPoint==2.0
pycparser==2.21
pytest==7.4.4
pytest-asyncio==0.21.2
pytest-cov==4.1.0
pytest-mock==3.11.1
pytest-xdist==3.5.0
python-gettext==5.0
pytz==2025.2
RestrictedPython==7.3
roman==4.2
six==1.17.0
soupsieve==2.4.1
tempstorage==6.0
tomli==2.0.1
transaction==4.0
typing_extensions==4.7.1
waitress==2.1.2
WebOb==1.8.9
WebTest==3.0.1
WSGIProxy2==0.5.1
z3c.pt==4.4
zc.lockfile==3.0.post1
ZConfig==4.1
zExceptions==5.0
zipp==3.15.0
ZODB==6.0
zodbpickle==3.3
Zope==5.10
zope.annotation==5.0
zope.browser==3.0
zope.browsermenu==5.0
zope.browserpage==5.0
zope.browserresource==5.1
zope.cachedescriptors==5.0
zope.component==6.0
zope.configuration==5.0.1
zope.container==5.2
zope.contentprovider==5.0
zope.contenttype==5.1
zope.datetime==5.0.0
zope.deferredimport==5.0
zope.deprecation==5.0
zope.dottedname==6.0
zope.event==5.0
zope.exceptions==5.1
zope.filerepresentation==6.0
zope.globalrequest==2.0
zope.hookable==6.0
zope.i18n==5.1
zope.i18nmessageid==6.1.0
zope.interface==6.4.post2
zope.lifecycleevent==5.0
zope.location==5.0
zope.pagetemplate==5.1
zope.processlifetime==3.0
zope.proxy==5.3
zope.ptresource==5.0
zope.publisher==7.0
zope.schema==7.0.1
zope.security==6.2
zope.sequencesort==5.0
zope.site==5.0
zope.size==5.0
zope.structuredtext==5.0
zope.tal==5.0.1
zope.tales==6.0
zope.testbrowser==6.0
zope.testing==5.0.1
zope.traversing==5.0
zope.viewlet==5.0

name: Products.Sessions
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - accesscontrol==6.3
      - acquisition==5.2
      - authencoding==5.0
      - beautifulsoup4==4.13.3
      - btrees==5.2
      - cffi==1.15.1
      - chameleon==4.2.0
      - coverage==7.2.7
      - datetime==5.5
      - documenttemplate==4.6
      - exceptiongroup==1.2.2
      - execnet==2.0.2
      - extensionclass==5.1
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - multimapping==5.0
      - multipart==1.1.0
      - packaging==24.0
      - pastedeploy==3.1.0
      - persistence==4.1
      - persistent==5.2
      - pluggy==1.2.0
      - products-temporaryfolder==7.0
      - products-zodbmountpoint==2.0
      - pycparser==2.21
      - pytest==7.4.4
      - pytest-asyncio==0.21.2
      - pytest-cov==4.1.0
      - pytest-mock==3.11.1
      - pytest-xdist==3.5.0
      - python-gettext==5.0
      - pytz==2025.2
      - restrictedpython==7.3
      - roman==4.2
      - six==1.17.0
      - soupsieve==2.4.1
      - tempstorage==6.0
      - tomli==2.0.1
      - transaction==4.0
      - typing-extensions==4.7.1
      - waitress==2.1.2
      - webob==1.8.9
      - webtest==3.0.1
      - wsgiproxy2==0.5.1
      - z3c-pt==4.4
      - zc-lockfile==3.0.post1
      - zconfig==4.1
      - zexceptions==5.0
      - zipp==3.15.0
      - zodb==6.0
      - zodbpickle==3.3
      - zope==5.10
      - zope-annotation==5.0
      - zope-browser==3.0
      - zope-browsermenu==5.0
      - zope-browserpage==5.0
      - zope-browserresource==5.1
      - zope-cachedescriptors==5.0
      - zope-component==6.0
      - zope-configuration==5.0.1
      - zope-container==5.2
      - zope-contentprovider==5.0
      - zope-contenttype==5.1
      - zope-datetime==5.0.0
      - zope-deferredimport==5.0
      - zope-deprecation==5.0
      - zope-dottedname==6.0
      - zope-event==5.0
      - zope-exceptions==5.1
      - zope-filerepresentation==6.0
      - zope-globalrequest==2.0
      - zope-hookable==6.0
      - zope-i18n==5.1
      - zope-i18nmessageid==6.1.0
      - zope-interface==6.4.post2
      - zope-lifecycleevent==5.0
      - zope-location==5.0
      - zope-pagetemplate==5.1
      - zope-processlifetime==3.0
      - zope-proxy==5.3
      - zope-ptresource==5.0
      - zope-publisher==7.0
      - zope-schema==7.0.1
      - zope-security==6.2
      - zope-sequencesort==5.0
      - zope-site==5.0
      - zope-size==5.0
      - zope-structuredtext==5.0
      - zope-tal==5.0.1
      - zope-tales==6.0
      - zope-testbrowser==6.0
      - zope-testing==5.0.1
      - zope-traversing==5.0
      - zope-viewlet==5.0
prefix: /opt/conda/envs/Products.Sessions

src/Products/Transience/tests/testTransactionHelper.py::TestTransactionHelper::testUncommittable
src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManagerPublish::test_encodeUrl_safe
src/Products/Sessions/stresstests/stresstestMultiThread.py::TestMultiThread::testNonOverlappingBrowserIds src/Products/Sessions/stresstests/stresstestMultiThread.py::TestMultiThread::testOverlappingBrowserIds src/Products/Sessions/stresstests/stresstestMultiThread.py::test_suite src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setCookie_cookie_life_days src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setCookie_cookie_secure_is_https src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setCookie_cookie_secure_no_URL1_sets_no_cookie src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setCookie_cookie_secure_not_https_sets_no_cookie src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setCookie_domain src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setCookie_http_only src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setCookie_http_only_missing_attr src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setCookie_path src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setCookie_remove src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setId_different_id_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test__setId_same_id_noop src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_encodeUrl_no_create_no_bid_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_encodeUrl_no_create_w_bid_inline_style src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_encodeUrl_no_create_w_bid_querystring_style src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_encodeUrl_no_create_w_bid_querystring_style_existing_qs src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_flushBrowserIdCookie_ok src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_flushBrowserIdCookie_wrong_ns_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_getBrowserId_already_set_on_request src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_getBrowserId_already_set_on_request_invalid_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_getBrowserId_considers_replaced_characters_well_formed src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_getBrowserId_namespace_hit src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_getBrowserId_namespace_miss_no_create src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_getBrowserId_namespace_miss_w_create_no_cookies src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_getBrowserId_namespace_miss_w_create_w_cookies src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_getHiddenFormField src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_hasBrowserId_already_set_on_request src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_hasBrowserId_already_set_on_request_invalid src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_hasBrowserId_namespace_hit src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_hasBrowserId_namespace_miss src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_hasTraversalHook_missing src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_hasTraversalHook_present src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdFromCookie_nonesuch_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdFromCookie_right_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdFromCookie_wrong_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdFromForm_nonesuch_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdFromForm_right_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdFromForm_wrong_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdFromUrl_nonesuch_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdFromUrl_right_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdFromUrl_wrong_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdNew_no_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdNew_nonesuch_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isBrowserIdNew_w_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_isUrlInBidNamespaces src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_registerTraversalHook_doesnt_replace_existing src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_registerTraversalHook_normal src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setAutoUrlEncoding_bool src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setBrowserIdCookieByForce_ok src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setBrowserIdCookieByForce_wrong_ns_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setBrowserIdName_empty_string_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setBrowserIdName_non_string_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setBrowserIdName_normal src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setBrowserIdNamespaces_invalid_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setBrowserIdNamespaces_normal src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieDomain_empty_OK src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieDomain_no_dots_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieDomain_non_string_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieDomain_one_dot_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieDomain_three_dots src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieDomain_trailing_semicolon_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieDomain_two_dots src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieHTTPOnly_bool src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieLifeDays_invalid_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieLifeDays_normal src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookiePath_invalid_raises src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookiePath_normal src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieSecure_bool src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieSecure_int src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_setCookieSecure_non_HTTPS_doesnt_set_cookie src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_unregisterTraversalHook_nonesuch_doesnt_raise src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_unregisterTraversalHook_normal src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_updateTraversalData_not_url_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManager::test_updateTraversalData_w_url_ns src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManagerTraverser::test___call___no_mgr src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManagerTraverser::test___call___w_mgr_request_empty_stack_w_auto_encode src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManagerTraverser::test___call___w_mgr_request_has_no_stack src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManagerTraverser::test___call___w_mgr_request_has_stack_no_auto_encode src/Products/Sessions/tests/testBrowserIdManager.py::TestBrowserIdManagerTraverser::test___call___w_mgr_request_has_stack_w_auto_encode src/Products/Sessions/tests/testBrowserIdManager.py::test_suite src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testAqWrappedObjectsFail src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testAutoReqPopulate src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testBadExternalSDCPath src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testBrowserIdIsSet src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testForeignObject src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testGetSessionDataByKey src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testGetSessionDataCreate src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testGetSessionDataNoCreate src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testGhostUnghostSessionManager src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testHasId src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testHasSessionData src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testHasTitle src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testInvalidateSessionDataObject src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testNewSessionDataObjectIsValid src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testNotHasSessionData src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testSessionDataWrappedInSDMandTOC src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testSubcommitAssignsPJar src/Products/Sessions/tests/testSessionDataManager.py::TestSessionManager::testUnlazifyAutoPopulated src/Products/Sessions/tests/testSessionDataManager.py::test_suite src/Products/Transience/tests/testTimeoutRelated.py::TestLastAccessed::testLastAccessed src/Products/Transience/tests/testTimeoutRelated.py::TestNotifications::testAddNotification src/Products/Transience/tests/testTimeoutRelated.py::TestNotifications::testDelNotification src/Products/Transience/tests/testTimeoutRelated.py::TestNotifications::testMissingCallbackGetCallbackReturnsNone src/Products/Transience/tests/testTimeoutRelated.py::test_suite src/Products/Transience/tests/testTransactionHelper.py::test_suite src/Products/Transience/tests/testTransientObject.py::TestTransientObject::testSetLastModified src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_TTWDictionary src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_dictionaryLike src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_getCreated src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_getLastAccessed src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_getLastModifiedSet src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_getLastModifiedUnset src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_id src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_p_resolveConflict_doesnt_fail_on_wrong_sort_usage src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_repr_leaking_information src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_setLastAccessed src/Products/Transience/tests/testTransientObject.py::TestTransientObject::test_validate src/Products/Transience/tests/testTransientObject.py::test_suite src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testDeleteInvalidKeyRaisesKeyError src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testGarbageCollection src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testGetDelaysTimeout src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testGetItemFails src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testGetReturnsDefault src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testGetTimeoutMinutesWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testHasKeyWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testItemsWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testKeysWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testLen src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testPathologicalLeftBranching src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testPathologicalRightBranching src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testRandomDeletes src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testRandomNonOverlappingInserts src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testRandomOverlappingInserts src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testReplaceWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testResetWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testSetItemDelaysTimeout src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testSetItemGetItemWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testSubobjectLimitWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testSuccessorChildParentRewriteExerciseCase src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testTargetedDeletes src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testValuesWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::testZeroTimeoutMeansPersistForever src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::test_getId src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::test_new src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::test_newDupFails src/Products/Transience/tests/testTransientObjectContainer.py::TestTransientObjectContainer::test_new_or_existing src/Products/Transience/tests/testTransientObjectContainer.py::TestSlowTransientObjectContainer::testChangingTimeoutWorks src/Products/Transience/tests/testTransientObjectContainer.py::TestSlowTransientObjectContainer::testItemsGetExpired src/Products/Transience/tests/testTransientObjectContainer.py::test_suite
src/Products/Sessions/SessionDataManager.py src/Products/Transience/Transience.py MANIFEST.in src/Products/Sessions/BrowserIdManager.py .travis.yml setup.cfg .coveragerc CHANGES.rst src/Products/Transience/TransientObject.py tox.ini buildout.cfg src/Products/Transience/TransactionHelper.py
src/Products/Sessions/SessionDataManager.py src/Products/Transience/Transience.py MANIFEST.in src/Products/Sessions/BrowserIdManager.py .travis.yml setup.cfg .coveragerc CHANGES.rst src/Products/Transience/TransientObject.py tox.ini buildout.cfg src/Products/Transience/TransactionHelper.py