From 541332c90f873611ae9ca739709f62b40ebb15a2 Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Mon, 17 Apr 2017 19:32:06 +0200 Subject: [PATCH] Retire repo This repo was created by accident, use deb-python-oslo.cache instead. Needed-By: I1ac1a06931c8b6dd7c2e73620a0302c29e605f03 Change-Id: I81894aea69b9d09b0977039623c26781093a397a --- .coveragerc | 7 - .gitignore | 55 -- .gitreview | 4 - .mailmap | 3 - .testr.conf | 7 - CONTRIBUTING.rst | 16 - HACKING.rst | 4 - LICENSE | 176 ----- README.rst | 24 - README.txt | 13 + babel.cfg | 2 - doc/source/conf.py | 82 -- doc/source/contributing.rst | 5 - doc/source/history.rst | 1 - doc/source/index.rst | 26 - doc/source/installation.rst | 7 - doc/source/opts.rst | 8 - doc/source/usage.rst | 7 - oslo_cache/__init__.py | 23 - oslo_cache/_i18n.py | 35 - oslo_cache/_memcache_pool.py | 259 ------- oslo_cache/_opts.py | 124 --- oslo_cache/backends/__init__.py | 0 oslo_cache/backends/dictionary.py | 106 --- oslo_cache/backends/memcache_pool.py | 63 -- oslo_cache/backends/mongo.py | 579 -------------- oslo_cache/core.py | 372 --------- oslo_cache/exception.py | 21 - .../locale/de/LC_MESSAGES/oslo_cache.po | 54 -- .../locale/en_GB/LC_MESSAGES/oslo_cache.po | 53 -- .../locale/es/LC_MESSAGES/oslo_cache.po | 57 -- .../locale/fr/LC_MESSAGES/oslo_cache.po | 57 -- .../locale/it/LC_MESSAGES/oslo_cache.po | 56 -- .../locale/ko_KR/LC_MESSAGES/oslo_cache.po | 54 -- .../locale/pt_BR/LC_MESSAGES/oslo_cache.po | 57 -- .../locale/ru/LC_MESSAGES/oslo_cache.po | 58 -- .../locale/tr_TR/LC_MESSAGES/oslo_cache.po | 54 -- .../locale/zh_CN/LC_MESSAGES/oslo_cache.po | 53 -- .../locale/zh_TW/LC_MESSAGES/oslo_cache.po | 54 -- oslo_cache/testing.py | 70 -- oslo_cache/tests/__init__.py | 18 - oslo_cache/tests/test_cache.py | 326 -------- oslo_cache/tests/test_cache_backend_mongo.py | 727 ------------------ oslo_cache/tests/test_connection_pool.py | 147 ---- oslo_cache/tests/test_dict_backend.py | 115 --- oslo_cache/version.py | 18 - .../notes/add_reno-3b4ae0789e9c45b4.yaml | 3 - releasenotes/source/_static/.placeholder | 0 releasenotes/source/_templates/.placeholder | 0 releasenotes/source/conf.py | 273 ------- releasenotes/source/index.rst | 8 - .../locale/en_GB/LC_MESSAGES/releasenotes.po | 30 - releasenotes/source/unreleased.rst | 5 - requirements.txt | 10 - setup.cfg | 68 -- setup.py | 29 - test-requirements.txt | 9 - tox.ini | 43 -- 58 files changed, 13 insertions(+), 4522 deletions(-) delete mode 100644 .coveragerc delete mode 100644 .gitignore delete mode 100644 .gitreview delete mode 100644 .mailmap delete mode 100644 .testr.conf delete mode 100644 CONTRIBUTING.rst delete mode 100644 HACKING.rst delete mode 100644 LICENSE delete mode 100644 README.rst create mode 100644 README.txt delete mode 100644 babel.cfg delete mode 100755 doc/source/conf.py delete mode 100644 doc/source/contributing.rst delete mode 100644 doc/source/history.rst delete mode 100644 doc/source/index.rst delete mode 100644 doc/source/installation.rst delete mode 100644 doc/source/opts.rst delete mode 100644 doc/source/usage.rst delete mode 100644 oslo_cache/__init__.py delete mode 100644 oslo_cache/_i18n.py delete mode 100644 oslo_cache/_memcache_pool.py delete mode 100644 oslo_cache/_opts.py delete mode 100644 oslo_cache/backends/__init__.py delete mode 100644 oslo_cache/backends/dictionary.py delete mode 100644 oslo_cache/backends/memcache_pool.py delete mode 100644 oslo_cache/backends/mongo.py delete mode 100644 oslo_cache/core.py delete mode 100644 oslo_cache/exception.py delete mode 100644 oslo_cache/locale/de/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/en_GB/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/es/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/fr/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/it/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/ko_KR/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/pt_BR/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/ru/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/tr_TR/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/zh_CN/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/locale/zh_TW/LC_MESSAGES/oslo_cache.po delete mode 100644 oslo_cache/testing.py delete mode 100644 oslo_cache/tests/__init__.py delete mode 100644 oslo_cache/tests/test_cache.py delete mode 100644 oslo_cache/tests/test_cache_backend_mongo.py delete mode 100644 oslo_cache/tests/test_connection_pool.py delete mode 100644 oslo_cache/tests/test_dict_backend.py delete mode 100644 oslo_cache/version.py delete mode 100644 releasenotes/notes/add_reno-3b4ae0789e9c45b4.yaml delete mode 100644 releasenotes/source/_static/.placeholder delete mode 100644 releasenotes/source/_templates/.placeholder delete mode 100644 releasenotes/source/conf.py delete mode 100644 releasenotes/source/index.rst delete mode 100644 releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po delete mode 100644 releasenotes/source/unreleased.rst delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 test-requirements.txt delete mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index c692756..0000000 --- a/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -branch = True -source = cache -omit = cache/tests/*,cache/openstack/* - -[report] -ignore_errors = True diff --git a/.gitignore b/.gitignore deleted file mode 100644 index dba59ee..0000000 --- a/.gitignore +++ /dev/null @@ -1,55 +0,0 @@ -*.py[cod] - -# C extensions -*.so - -# Packages -*.egg* -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg -lib -lib64 - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox -nosetests.xml -.testrepository - -# Translations -*.mo - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Complexity -output/*.html -output/*/index.html - -# Sphinx -doc/build -doc/source/api - -# pbr generates these -AUTHORS -ChangeLog - -# Editors -*~ -.*.swp - -# reno build -releasenotes/build diff --git a/.gitreview b/.gitreview deleted file mode 100644 index 4e7a9cd..0000000 --- a/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=openstack/oslo.cache.git diff --git a/.mailmap b/.mailmap deleted file mode 100644 index 516ae6f..0000000 --- a/.mailmap +++ /dev/null @@ -1,3 +0,0 @@ -# Format is: -# -# diff --git a/.testr.conf b/.testr.conf deleted file mode 100644 index 735255b..0000000 --- a/.testr.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ - OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ - OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover -t ./ ./oslo_cache $LISTOPT $IDOPTION -test_id_option=--load-list $IDFILE -test_list_option=--list diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index c2f7802..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,16 +0,0 @@ -If you would like to contribute to the development of OpenStack, -you must follow the steps in this page: - - http://docs.openstack.org/infra/manual/developers.html - -Once those steps have been completed, changes to OpenStack -should be submitted for review via the Gerrit tool, following -the workflow documented at: - - http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on Launchpad, not GitHub: - - https://bugs.launchpad.net/oslo.cache diff --git a/HACKING.rst b/HACKING.rst deleted file mode 100644 index bbf6c32..0000000 --- a/HACKING.rst +++ /dev/null @@ -1,4 +0,0 @@ -oslo.cache Style Commandments -====================================================== - -Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/ diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 68c771a..0000000 --- a/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - diff --git a/README.rst b/README.rst deleted file mode 100644 index 962e719..0000000 --- a/README.rst +++ /dev/null @@ -1,24 +0,0 @@ -========== -oslo.cache -========== - -.. image:: https://img.shields.io/pypi/v/oslo.cache.svg - :target: https://pypi.python.org/pypi/oslo.cache/ - :alt: Latest Version - -.. image:: https://img.shields.io/pypi/dm/oslo.cache.svg - :target: https://pypi.python.org/pypi/oslo.cache/ - :alt: Downloads - -`oslo.cache` aims to provide a generic caching mechanism for OpenStack projects -by wrapping the `dogpile.cache -`_ library. The dogpile.cache -library provides support memoization, key value storage and interfaces to common -caching backends such as `Memcached `_. - - - -* Free software: Apache license -* Documentation: http://docs.openstack.org/developer/oslo.cache -* Source: http://git.openstack.org/cgit/openstack/oslo.cache -* Bugs: http://bugs.launchpad.net/oslo.cache diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..1de554a --- /dev/null +++ b/README.txt @@ -0,0 +1,13 @@ +This project is no longer maintained. + +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". + +Use instead the project deb-python-oslo.cache at +http://git.openstack.org/cgit/openstack/deb-python-oslo.cache . + +For any further questions, please email +openstack-dev@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/babel.cfg b/babel.cfg deleted file mode 100644 index 15cd6cb..0000000 --- a/babel.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[python: **.py] - diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100755 index eacff6d..0000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -sys.path.insert(0, os.path.abspath('../..')) -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', - 'oslosphinx', - 'oslo_config.sphinxext', -] - -# autodoc generation is a bit aggressive and a nuisance when doing heavy -# text edit cycles. -# execute "export SPHINX_DEBUG=1" in your terminal to disable - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'oslo.cache' -copyright = u'2014, OpenStack Foundation' - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['oslo_cache.'] - -# -- Options for HTML output -------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -# html_theme_path = ["."] -# html_theme = '_theme' -# html_static_path = ['static'] - -# Output file base name for HTML help builder. -htmlhelp_basename = '%sdoc' % project - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ('index', - '%s.tex' % project, - u'%s Documentation' % project, - u'OpenStack Foundation', 'manual'), -] - -intersphinx_mapping = { - 'python': ('https://docs.python.org/', None), - 'osloconfig': ('http://docs.openstack.org/developer/oslo.config/', None), - 'dogpilecache': ('https://dogpilecache.readthedocs.io/en/latest/', None), -} diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst deleted file mode 100644 index 2ca75d1..0000000 --- a/doc/source/contributing.rst +++ /dev/null @@ -1,5 +0,0 @@ -============== - Contributing -============== - -.. include:: ../../CONTRIBUTING.rst diff --git a/doc/source/history.rst b/doc/source/history.rst deleted file mode 100644 index 69ed4fe..0000000 --- a/doc/source/history.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../ChangeLog diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index 8fe606a..0000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,26 +0,0 @@ -============ - oslo.cache -============ - -Cache storage for Openstack projects. - -Contents -======== - -.. toctree:: - :maxdepth: 2 - - installation - api/modules - usage - opts - contributing - history - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/doc/source/installation.rst b/doc/source/installation.rst deleted file mode 100644 index 5111fb7..0000000 --- a/doc/source/installation.rst +++ /dev/null @@ -1,7 +0,0 @@ -============== - Installation -============== - -At the command line:: - - $ pip install oslo.cache diff --git a/doc/source/opts.rst b/doc/source/opts.rst deleted file mode 100644 index 0827952..0000000 --- a/doc/source/opts.rst +++ /dev/null @@ -1,8 +0,0 @@ -======================= - Configuration Options -======================= - -oslo.cache uses oslo.config to define and manage configuration options -to allow the deployer to control how an application uses this library. - -.. show-options:: oslo.cache diff --git a/doc/source/usage.rst b/doc/source/usage.rst deleted file mode 100644 index 675cc7b..0000000 --- a/doc/source/usage.rst +++ /dev/null @@ -1,7 +0,0 @@ -======= - Usage -======= - -To use oslo.cache in a project:: - - import oslo_cache diff --git a/oslo_cache/__init__.py b/oslo_cache/__init__.py deleted file mode 100644 index 6dd171c..0000000 --- a/oslo_cache/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from oslo_cache.core import * # noqa - - -__all__ = [ - 'configure', - 'configure_cache_region', - 'create_region', - 'get_memoization_decorator', - 'NO_VALUE', -] diff --git a/oslo_cache/_i18n.py b/oslo_cache/_i18n.py deleted file mode 100644 index 03cbb3d..0000000 --- a/oslo_cache/_i18n.py +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html - -""" - -import oslo_i18n - - -_translators = oslo_i18n.TranslatorFactory(domain='oslo_cache') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/oslo_cache/_memcache_pool.py b/oslo_cache/_memcache_pool.py deleted file mode 100644 index 45af9a9..0000000 --- a/oslo_cache/_memcache_pool.py +++ /dev/null @@ -1,259 +0,0 @@ -# Copyright 2014 Mirantis Inc -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Thread-safe connection pool for python-memcached.""" - -# NOTE(yorik-sar): this file is copied between keystone and keystonemiddleware -# and should be kept in sync until we can use external library for this. - -import collections -import contextlib -import itertools -import logging -import threading -import time - -import memcache -from oslo_log import log -from six.moves import queue -from six.moves import zip - -from oslo_cache._i18n import _ -from oslo_cache import exception - - -LOG = log.getLogger(__name__) - - -class _MemcacheClient(memcache.Client): - """Thread global memcache client - - As client is inherited from threading.local we have to restore object - methods overloaded by threading.local so we can reuse clients in - different threads - """ - __delattr__ = object.__delattr__ - __getattribute__ = object.__getattribute__ - __new__ = object.__new__ - __setattr__ = object.__setattr__ - - def __del__(self): - pass - - -_PoolItem = collections.namedtuple('_PoolItem', ['ttl', 'connection']) - - -class ConnectionPool(queue.Queue): - """Base connection pool class - - This class implements the basic connection pool logic as an abstract base - class. - """ - def __init__(self, maxsize, unused_timeout, conn_get_timeout=None): - """Initialize the connection pool. - - :param maxsize: maximum number of client connections for the pool - :type maxsize: int - :param unused_timeout: idle time to live for unused clients (in - seconds). If a client connection object has been - in the pool and idle for longer than the - unused_timeout, it will be reaped. This is to - ensure resources are released as utilization - goes down. - :type unused_timeout: int - :param conn_get_timeout: maximum time in seconds to wait for a - connection. If set to `None` timeout is - indefinite. - :type conn_get_timeout: int - """ - # super() cannot be used here because Queue in stdlib is an - # old-style class - queue.Queue.__init__(self, maxsize) - self._unused_timeout = unused_timeout - self._connection_get_timeout = conn_get_timeout - self._acquired = 0 - - def _create_connection(self): - """Returns a connection instance. - - This is called when the pool needs another instance created. - - :returns: a new connection instance - - """ - raise NotImplementedError - - def _destroy_connection(self, conn): - """Destroy and cleanup a connection instance. - - This is called when the pool wishes to get rid of an existing - connection. This is the opportunity for a subclass to free up - resources and cleanup after itself. - - :param conn: the connection object to destroy - - """ - raise NotImplementedError - - def _do_log(self, level, msg, *args, **kwargs): - if LOG.isEnabledFor(level): - thread_id = threading.current_thread().ident - args = (id(self), thread_id) + args - prefix = 'Memcached pool %s, thread %s: ' - LOG.log(level, prefix + msg, *args, **kwargs) - - def _debug_logger(self, msg, *args, **kwargs): - self._do_log(logging.DEBUG, msg, *args, **kwargs) - - def _trace_logger(self, msg, *args, **kwargs): - self._do_log(log.TRACE, msg, *args, **kwargs) - - @contextlib.contextmanager - def acquire(self): - self._trace_logger('Acquiring connection') - try: - conn = self.get(timeout=self._connection_get_timeout) - except queue.Empty: - raise exception.QueueEmpty( - _('Unable to get a connection from pool id %(id)s after ' - '%(seconds)s seconds.') % - {'id': id(self), 'seconds': self._connection_get_timeout}) - self._trace_logger('Acquired connection %s', id(conn)) - try: - yield conn - finally: - self._trace_logger('Releasing connection %s', id(conn)) - self._drop_expired_connections() - try: - # super() cannot be used here because Queue in stdlib is an - # old-style class - queue.Queue.put(self, conn, block=False) - except queue.Full: - self._trace_logger('Reaping exceeding connection %s', id(conn)) - self._destroy_connection(conn) - - def _qsize(self): - if self.maxsize: - return self.maxsize - self._acquired - else: - # A value indicating there is always a free connection - # if maxsize is None or 0 - return 1 - - # NOTE(dstanek): stdlib and eventlet Queue implementations - # have different names for the qsize method. This ensures - # that we override both of them. - if not hasattr(queue.Queue, '_qsize'): - qsize = _qsize - - def _get(self): - try: - conn = self.queue.pop().connection - except IndexError: - conn = self._create_connection() - self._acquired += 1 - return conn - - def _drop_expired_connections(self): - """Drop all expired connections from the left end of the queue.""" - now = time.time() - try: - while self.queue[0].ttl < now: - conn = self.queue.popleft().connection - self._trace_logger('Reaping connection %s', id(conn)) - self._destroy_connection(conn) - except IndexError: - # NOTE(amakarov): This is an expected excepton. so there's no - # need to react. We have to handle exceptions instead of - # checking queue length as IndexError is a result of race - # condition too as well as of mere queue depletio of mere queue - # depletionn. - pass - - def _put(self, conn): - self.queue.append(_PoolItem( - ttl=time.time() + self._unused_timeout, - connection=conn, - )) - self._acquired -= 1 - - -class MemcacheClientPool(ConnectionPool): - def __init__(self, urls, arguments, **kwargs): - # super() cannot be used here because Queue in stdlib is an - # old-style class - ConnectionPool.__init__(self, **kwargs) - self.urls = urls - self._arguments = arguments - # NOTE(morganfainberg): The host objects expect an int for the - # deaduntil value. Initialize this at 0 for each host with 0 indicating - # the host is not dead. - self._hosts_deaduntil = [0] * len(urls) - - def _create_connection(self): - return _MemcacheClient(self.urls, **self._arguments) - - def _destroy_connection(self, conn): - conn.disconnect_all() - - def _get(self): - # super() cannot be used here because Queue in stdlib is an - # old-style class - conn = ConnectionPool._get(self) - try: - # Propagate host state known to us to this client's list - now = time.time() - for deaduntil, host in zip(self._hosts_deaduntil, conn.servers): - if deaduntil > now and host.deaduntil <= now: - host.mark_dead('propagating death mark from the pool') - host.deaduntil = deaduntil - except Exception: - # We need to be sure that connection doesn't leak from the pool. - # This code runs before we enter context manager's try-finally - # block, so we need to explicitly release it here. - # super() cannot be used here because Queue in stdlib is an - # old-style class - ConnectionPool._put(self, conn) - raise - return conn - - def _put(self, conn): - try: - # If this client found that one of the hosts is dead, mark it as - # such in our internal list - now = time.time() - for i, host in zip(itertools.count(), conn.servers): - deaduntil = self._hosts_deaduntil[i] - # Do nothing if we already know this host is dead - if deaduntil <= now: - if host.deaduntil > now: - self._hosts_deaduntil[i] = host.deaduntil - self._debug_logger( - 'Marked host %s dead until %s', - self.urls[i], host.deaduntil) - else: - self._hosts_deaduntil[i] = 0 - # If all hosts are dead we should forget that they're dead. This - # way we won't get completely shut off until dead_retry seconds - # pass, but will be checking servers as frequent as we can (over - # way smaller socket_timeout) - if all(deaduntil > now for deaduntil in self._hosts_deaduntil): - self._debug_logger('All hosts are dead. Marking them as live.') - self._hosts_deaduntil[:] = [0] * len(self._hosts_deaduntil) - finally: - # super() cannot be used here because Queue in stdlib is an - # old-style class - ConnectionPool._put(self, conn) diff --git a/oslo_cache/_opts.py b/oslo_cache/_opts.py deleted file mode 100644 index 5e24f4d..0000000 --- a/oslo_cache/_opts.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config import cfg - - -_DEFAULT_BACKEND = 'dogpile.cache.null' - -FILE_OPTIONS = { - 'cache': [ - cfg.StrOpt('config_prefix', default='cache.oslo', - help='Prefix for building the configuration dictionary ' - 'for the cache region. This should not need to be ' - 'changed unless there is another dogpile.cache ' - 'region with the same configuration name.'), - cfg.IntOpt('expiration_time', default=600, - help='Default TTL, in seconds, for any cached item in ' - 'the dogpile.cache region. This applies to any ' - 'cached method that doesn\'t have an explicit ' - 'cache expiration time defined for it.'), - # NOTE(morganfainberg): the dogpile.cache.memory acceptable in devstack - # and other such single-process/thread deployments. Running - # dogpile.cache.memory in any other configuration has the same pitfalls - # as the KVS token backend. It is recommended that either Redis or - # Memcached are used as the dogpile backend for real workloads. To - # prevent issues with the memory cache ending up in "production" - # unintentionally, we register a no-op as the keystone default caching - # backend. - cfg.StrOpt('backend', default=_DEFAULT_BACKEND, - help='Dogpile.cache backend module. It is recommended ' - 'that Memcache with pooling ' - '(oslo_cache.memcache_pool) or Redis ' - '(dogpile.cache.redis) be used in production ' - 'deployments. Small workloads (single process) ' - 'like devstack can use the dogpile.cache.memory ' - 'backend.'), - cfg.MultiStrOpt('backend_argument', default=[], secret=True, - help='Arguments supplied to the backend module. ' - 'Specify this option once per argument to be ' - 'passed to the dogpile.cache backend. Example ' - 'format: ":".'), - cfg.ListOpt('proxies', default=[], - help='Proxy classes to import that will affect the way ' - 'the dogpile.cache backend functions. See the ' - 'dogpile.cache documentation on ' - 'changing-backend-behavior.'), - cfg.BoolOpt('enabled', default=False, - help='Global toggle for caching.'), - cfg.BoolOpt('debug_cache_backend', default=False, - help='Extra debugging from the cache backend (cache ' - 'keys, get/set/delete/etc calls). This is only ' - 'really useful if you need to see the specific ' - 'cache-backend get/set/delete calls with the ' - 'keys/values. Typically this should be left set ' - 'to false.'), - cfg.ListOpt('memcache_servers', default=['localhost:11211'], - help='Memcache servers in the format of "host:port".' - ' (dogpile.cache.memcache and oslo_cache.memcache_pool' - ' backends only).'), - cfg.IntOpt('memcache_dead_retry', - default=5 * 60, - help='Number of seconds memcached server is considered dead' - ' before it is tried again. (dogpile.cache.memcache and' - ' oslo_cache.memcache_pool backends only).'), - cfg.IntOpt('memcache_socket_timeout', - default=3, - help='Timeout in seconds for every call to a server.' - ' (dogpile.cache.memcache and oslo_cache.memcache_pool' - ' backends only).'), - cfg.IntOpt('memcache_pool_maxsize', - default=10, - help='Max total number of open connections to every' - ' memcached server. (oslo_cache.memcache_pool backend' - ' only).'), - cfg.IntOpt('memcache_pool_unused_timeout', - default=60, - help='Number of seconds a connection to memcached is held' - ' unused in the pool before it is closed.' - ' (oslo_cache.memcache_pool backend only).'), - cfg.IntOpt('memcache_pool_connection_get_timeout', - default=10, - help='Number of seconds that an operation will wait to get ' - 'a memcache client connection.'), - ], -} - - -def configure(conf): - for section in FILE_OPTIONS: - for option in FILE_OPTIONS[section]: - conf.register_opt(option, group=section) - - -def list_opts(): - """Return a list of oslo_config options. - - The returned list includes all oslo_config options which are registered as - the "FILE_OPTIONS". - - Each object in the list is a two element tuple. The first element of - each tuple is the name of the group under which the list of options in the - second element will be registered. A group name of None corresponds to the - [DEFAULT] group in config files. - - This function is also discoverable via the 'oslo_config.opts' entry point - under the 'oslo_cache.config.opts' namespace. - - The purpose of this is to allow tools like the Oslo sample config file - generator to discover the options exposed to users by this library. - - :returns: a list of (group_name, opts) tuples - """ - return list(FILE_OPTIONS.items()) diff --git a/oslo_cache/backends/__init__.py b/oslo_cache/backends/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/oslo_cache/backends/dictionary.py b/oslo_cache/backends/dictionary.py deleted file mode 100644 index 352b63d..0000000 --- a/oslo_cache/backends/dictionary.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2015 Mirantis Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""dogpile.cache backend that uses dictionary for storage""" - -from dogpile.cache import api -from oslo_cache import core -from oslo_utils import timeutils - -__all__ = [ - 'DictCacheBackend' -] - -_NO_VALUE = core.NO_VALUE - - -class DictCacheBackend(api.CacheBackend): - """A DictCacheBackend based on dictionary. - - Arguments accepted in the arguments dictionary: - - :param expiration_time: interval in seconds to indicate maximum - time-to-live value for each key in DictCacheBackend. - Default expiration_time value is 0, that means that all keys have - infinite time-to-live value. - :type expiration_time: real - """ - - def __init__(self, arguments): - self.expiration_time = arguments.get('expiration_time', 0) - self.cache = {} - - def get(self, key): - """Retrieves the value for a key. - - :param key: dictionary key - :returns: value for a key or :data:`oslo_cache.core.NO_VALUE` - for nonexistent or expired keys. - """ - (value, timeout) = self.cache.get(key, (_NO_VALUE, 0)) - if self.expiration_time > 0 and timeutils.utcnow_ts() >= timeout: - self.cache.pop(key, None) - return _NO_VALUE - - return value - - def get_multi(self, keys): - """Retrieves the value for a list of keys.""" - return [self.get(key) for key in keys] - - def set(self, key, value): - """Sets the value for a key. - - Expunges expired keys during each set. - - :param key: dictionary key - :param value: value associated with the key - """ - self.set_multi({key: value}) - - def set_multi(self, mapping): - """Set multiple values in the cache. - Expunges expired keys during each set. - - :param mapping: dictionary with key/value pairs - """ - self._clear() - timeout = 0 - if self.expiration_time > 0: - timeout = timeutils.utcnow_ts() + self.expiration_time - for key, value in mapping.items(): - self.cache[key] = (value, timeout) - - def delete(self, key): - """Deletes the value associated with the key if it exists. - - :param key: dictionary key - """ - self.cache.pop(key, None) - - def delete_multi(self, keys): - """Deletes the value associated with each key in list if it exists. - - :param keys: list of dictionary keys - """ - for key in keys: - self.cache.pop(key, None) - - def _clear(self): - """Expunges expired keys.""" - now = timeutils.utcnow_ts() - for k in list(self.cache): - (_value, timeout) = self.cache[k] - if timeout > 0 and now >= timeout: - del self.cache[k] diff --git a/oslo_cache/backends/memcache_pool.py b/oslo_cache/backends/memcache_pool.py deleted file mode 100644 index 46176e3..0000000 --- a/oslo_cache/backends/memcache_pool.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2014 Mirantis Inc -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""dogpile.cache backend that uses Memcached connection pool""" - -import functools -import logging - -from dogpile.cache.backends import memcached as memcached_backend - -from oslo_cache import _memcache_pool - - -LOG = logging.getLogger(__name__) - - -# Helper to ease backend refactoring -class ClientProxy(object): - def __init__(self, client_pool): - self.client_pool = client_pool - - def _run_method(self, __name, *args, **kwargs): - with self.client_pool.acquire() as client: - return getattr(client, __name)(*args, **kwargs) - - def __getattr__(self, name): - return functools.partial(self._run_method, name) - - -class PooledMemcachedBackend(memcached_backend.MemcachedBackend): - """Memcached backend that does connection pooling.""" - - # Composed from GenericMemcachedBackend's and MemcacheArgs's __init__ - def __init__(self, arguments): - super(PooledMemcachedBackend, self).__init__(arguments) - self.client_pool = _memcache_pool.MemcacheClientPool( - self.url, - arguments={ - 'dead_retry': arguments.get('dead_retry', 5 * 60), - 'socket_timeout': arguments.get('socket_timeout', 3), - }, - maxsize=arguments.get('pool_maxsize', 10), - unused_timeout=arguments.get('pool_unused_timeout', 60), - conn_get_timeout=arguments.get('pool_connection_get_timeout', 10), - ) - - # Since all methods in backend just call one of methods of client, this - # lets us avoid need to hack it too much - @property - def client(self): - return ClientProxy(self.client_pool) diff --git a/oslo_cache/backends/mongo.py b/oslo_cache/backends/mongo.py deleted file mode 100644 index f66b8f0..0000000 --- a/oslo_cache/backends/mongo.py +++ /dev/null @@ -1,579 +0,0 @@ -# Copyright 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc -import datetime - -from dogpile.cache import api -from dogpile import util as dp_util -from oslo_cache import core -from oslo_log import log -from oslo_utils import importutils -from oslo_utils import timeutils -import six - -from oslo_cache._i18n import _ -from oslo_cache._i18n import _LW -from oslo_cache import exception - - -__all__ = [ - 'MongoCacheBackend' -] - -_NO_VALUE = core.NO_VALUE -LOG = log.getLogger(__name__) - - -class MongoCacheBackend(api.CacheBackend): - """A MongoDB based caching backend implementing dogpile backend APIs. - - Arguments accepted in the arguments dictionary: - - :param db_hosts: string (required), hostname or IP address of the - MongoDB server instance. This can be a single MongoDB connection URI, - or a list of MongoDB connection URIs. - - :param db_name: string (required), the name of the database to be used. - - :param cache_collection: string (required), the name of collection to store - cached data. - *Note:* Different collection name can be provided if there is need to - create separate container (i.e. collection) for cache data. So region - configuration is done per collection. - - Following are optional parameters for MongoDB backend configuration, - - :param username: string, the name of the user to authenticate. - - :param password: string, the password of the user to authenticate. - - :param max_pool_size: integer, the maximum number of connections that the - pool will open simultaneously. By default the pool size is 10. - - :param w: integer, write acknowledgement for MongoDB client - - If not provided, then no default is set on MongoDB and then write - acknowledgement behavior occurs as per MongoDB default. This parameter - name is same as what is used in MongoDB docs. This value is specified - at collection level so its applicable to `cache_collection` db write - operations. - - If this is a replica set, write operations will block until they have - been replicated to the specified number or tagged set of servers. - Setting w=0 disables write acknowledgement and all other write concern - options. - - :param read_preference: string, the read preference mode for MongoDB client - Expected value is ``primary``, ``primaryPreferred``, ``secondary``, - ``secondaryPreferred``, or ``nearest``. This read_preference is - specified at collection level so its applicable to `cache_collection` - db read operations. - - :param use_replica: boolean, flag to indicate if replica client to be - used. Default is `False`. `replicaset_name` value is required if - `True`. - - :param replicaset_name: string, name of replica set. - Becomes required if `use_replica` is `True` - - :param son_manipulator: string, name of class with module name which - implements MongoDB SONManipulator. - Default manipulator used is :class:`.BaseTransform`. - - This manipulator is added per database. In multiple cache - configurations, the manipulator name should be same if same - database name ``db_name`` is used in those configurations. - - SONManipulator is used to manipulate custom data types as they are - saved or retrieved from MongoDB. Custom impl is only needed if cached - data is custom class and needs transformations when saving or reading - from db. If dogpile cached value contains built-in data types, then - BaseTransform class is sufficient as it already handles dogpile - CachedValue class transformation. - - :param mongo_ttl_seconds: integer, interval in seconds to indicate maximum - time-to-live value. - If value is greater than 0, then its assumed that cache_collection - needs to be TTL type (has index at 'doc_date' field). - By default, the value is -1 and its disabled. - Reference: - - .. NOTE:: - - This parameter is different from Dogpile own - expiration_time, which is the number of seconds after which Dogpile - will consider the value to be expired. When Dogpile considers a - value to be expired, it continues to use the value until generation - of a new value is complete, when using CacheRegion.get_or_create(). - Therefore, if you are setting `mongo_ttl_seconds`, you will want to - make sure it is greater than expiration_time by at least enough - seconds for new values to be generated, else the value would not - be available during a regeneration, forcing all threads to wait for - a regeneration each time a value expires. - - :param ssl: boolean, If True, create the connection to the server - using SSL. Default is `False`. Client SSL connection parameters depends - on server side SSL setup. For further reference on SSL configuration: - - - :param ssl_keyfile: string, the private keyfile used to identify the - local connection against mongod. If included with the certfile then - only the `ssl_certfile` is needed. Used only when `ssl` is `True`. - - :param ssl_certfile: string, the certificate file used to identify the - local connection against mongod. Used only when `ssl` is `True`. - - :param ssl_ca_certs: string, the ca_certs file contains a set of - concatenated 'certification authority' certificates, which are used to - validate certificates passed from the other end of the connection. - Used only when `ssl` is `True`. - - :param ssl_cert_reqs: string, the parameter cert_reqs specifies whether - a certificate is required from the other side of the connection, and - whether it will be validated if provided. It must be one of the three - values ``ssl.CERT_NONE`` (certificates ignored), ``ssl.CERT_OPTIONAL`` - (not required, but validated if provided), or - ``ssl.CERT_REQUIRED`` (required and validated). If the value of this - parameter is not ``ssl.CERT_NONE``, then the ssl_ca_certs parameter - must point to a file of CA certificates. Used only when `ssl` - is `True`. - - Rest of arguments are passed to mongo calls for read, write and remove. - So related options can be specified to pass to these operations. - - Further details of various supported arguments can be referred from - - - """ - - def __init__(self, arguments): - self.api = MongoApi(arguments) - - @dp_util.memoized_property - def client(self): - """Initializes MongoDB connection and collection defaults. - - This initialization is done only once and performed as part of lazy - inclusion of MongoDB dependency i.e. add imports only if related - backend is used. - - :return: :class:`.MongoApi` instance - """ - self.api.get_cache_collection() - return self.api - - def get(self, key): - """Retrieves the value for a key. - - :param key: key to be retrieved. - :returns: value for a key or :data:`oslo_cache.core.NO_VALUE` - for nonexistent or expired keys. - """ - value = self.client.get(key) - if value is None: - return _NO_VALUE - else: - return value - - def get_multi(self, keys): - """Return multiple values from the cache, based on the given keys. - - :param keys: sequence of keys to be retrieved. - :returns: returns values (or :data:`oslo_cache.core.NO_VALUE`) - as a list matching the keys given. - """ - values = self.client.get_multi(keys) - return [ - _NO_VALUE if key not in values - else values[key] for key in keys - ] - - def set(self, key, value): - self.client.set(key, value) - - def set_multi(self, mapping): - self.client.set_multi(mapping) - - def delete(self, key): - self.client.delete(key) - - def delete_multi(self, keys): - self.client.delete_multi(keys) - - -class MongoApi(object): - """Class handling MongoDB specific functionality. - - This class uses PyMongo APIs internally to create database connection - with configured pool size, ensures unique index on key, does database - authentication and ensure TTL collection index if configured so. - This class also serves as handle to cache collection for dogpile cache - APIs. - - In a single deployment, multiple cache configuration can be defined. In - that case of multiple cache collections usage, db client connection pool - is shared when cache collections are within same database. - """ - - # class level attributes for re-use of db client connection and collection - _DB = {} # dict of db_name: db connection reference - _MONGO_COLLS = {} # dict of cache_collection : db collection reference - - def __init__(self, arguments): - self._init_args(arguments) - self._data_manipulator = None - - def _init_args(self, arguments): - """Helper logic for collecting and parsing MongoDB specific arguments. - - The arguments passed in are separated out in connection specific - setting and rest of arguments are passed to create/update/delete - db operations. - """ - self.conn_kwargs = {} # connection specific arguments - - self.hosts = arguments.pop('db_hosts', None) - if self.hosts is None: - msg = _('db_hosts value is required') - raise exception.ConfigurationError(msg) - - self.db_name = arguments.pop('db_name', None) - if self.db_name is None: - msg = _('database db_name is required') - raise exception.ConfigurationError(msg) - - self.cache_collection = arguments.pop('cache_collection', None) - if self.cache_collection is None: - msg = _('cache_collection name is required') - raise exception.ConfigurationError(msg) - - self.username = arguments.pop('username', None) - self.password = arguments.pop('password', None) - self.max_pool_size = arguments.pop('max_pool_size', 10) - - self.w = arguments.pop('w', -1) - try: - self.w = int(self.w) - except ValueError: - msg = _('integer value expected for w (write concern attribute)') - raise exception.ConfigurationError(msg) - - self.read_preference = arguments.pop('read_preference', None) - - self.use_replica = arguments.pop('use_replica', False) - if self.use_replica: - if arguments.get('replicaset_name') is None: - msg = _('replicaset_name required when use_replica is True') - raise exception.ConfigurationError(msg) - self.replicaset_name = arguments.get('replicaset_name') - - self.son_manipulator = arguments.pop('son_manipulator', None) - - # set if mongo collection needs to be TTL type. - # This needs to be max ttl for any cache entry. - # By default, -1 means don't use TTL collection. - # With ttl set, it creates related index and have doc_date field with - # needed expiration interval - self.ttl_seconds = arguments.pop('mongo_ttl_seconds', -1) - try: - self.ttl_seconds = int(self.ttl_seconds) - except ValueError: - msg = _('integer value expected for mongo_ttl_seconds') - raise exception.ConfigurationError(msg) - - self.conn_kwargs['ssl'] = arguments.pop('ssl', False) - if self.conn_kwargs['ssl']: - ssl_keyfile = arguments.pop('ssl_keyfile', None) - ssl_certfile = arguments.pop('ssl_certfile', None) - ssl_ca_certs = arguments.pop('ssl_ca_certs', None) - ssl_cert_reqs = arguments.pop('ssl_cert_reqs', None) - if ssl_keyfile: - self.conn_kwargs['ssl_keyfile'] = ssl_keyfile - if ssl_certfile: - self.conn_kwargs['ssl_certfile'] = ssl_certfile - if ssl_ca_certs: - self.conn_kwargs['ssl_ca_certs'] = ssl_ca_certs - if ssl_cert_reqs: - self.conn_kwargs['ssl_cert_reqs'] = ( - self._ssl_cert_req_type(ssl_cert_reqs)) - - # rest of arguments are passed to mongo crud calls - self.meth_kwargs = arguments - - def _ssl_cert_req_type(self, req_type): - try: - import ssl - except ImportError: - raise exception.ConfigurationError(_('no ssl support available')) - req_type = req_type.upper() - try: - return { - 'NONE': ssl.CERT_NONE, - 'OPTIONAL': ssl.CERT_OPTIONAL, - 'REQUIRED': ssl.CERT_REQUIRED - }[req_type] - except KeyError: - msg = _('Invalid ssl_cert_reqs value of %s, must be one of ' - '"NONE", "OPTIONAL", "REQUIRED"') % req_type - raise exception.ConfigurationError(msg) - - def _get_db(self): - # defer imports until backend is used - global pymongo - import pymongo - if self.use_replica: - connection = pymongo.MongoReplicaSetClient( - host=self.hosts, replicaSet=self.replicaset_name, - max_pool_size=self.max_pool_size, **self.conn_kwargs) - else: # used for standalone node or mongos in sharded setup - connection = pymongo.MongoClient( - host=self.hosts, max_pool_size=self.max_pool_size, - **self.conn_kwargs) - - database = getattr(connection, self.db_name) - - self._assign_data_mainpulator() - database.add_son_manipulator(self._data_manipulator) - if self.username and self.password: - database.authenticate(self.username, self.password) - return database - - def _assign_data_mainpulator(self): - if self._data_manipulator is None: - if self.son_manipulator: - self._data_manipulator = importutils.import_object( - self.son_manipulator) - else: - self._data_manipulator = BaseTransform() - - def _get_doc_date(self): - if self.ttl_seconds > 0: - expire_delta = datetime.timedelta(seconds=self.ttl_seconds) - doc_date = timeutils.utcnow() + expire_delta - else: - doc_date = timeutils.utcnow() - return doc_date - - def get_cache_collection(self): - if self.cache_collection not in self._MONGO_COLLS: - global pymongo - import pymongo - # re-use db client connection if already defined as part of - # earlier dogpile cache configuration - if self.db_name not in self._DB: - self._DB[self.db_name] = self._get_db() - coll = getattr(self._DB[self.db_name], self.cache_collection) - - self._assign_data_mainpulator() - if self.read_preference: - # pymongo 3.0 renamed mongos_enum to read_pref_mode_from_name - f = getattr(pymongo.read_preferences, - 'read_pref_mode_from_name', None) - if not f: - f = pymongo.read_preferences.mongos_enum - self.read_preference = f(self.read_preference) - coll.read_preference = self.read_preference - if self.w > -1: - coll.write_concern['w'] = self.w - if self.ttl_seconds > 0: - kwargs = {'expireAfterSeconds': self.ttl_seconds} - coll.ensure_index('doc_date', cache_for=5, **kwargs) - else: - self._validate_ttl_index(coll, self.cache_collection, - self.ttl_seconds) - self._MONGO_COLLS[self.cache_collection] = coll - - return self._MONGO_COLLS[self.cache_collection] - - def _get_cache_entry(self, key, value, meta, doc_date): - """MongoDB cache data representation. - - Storing cache key as ``_id`` field as MongoDB by default creates - unique index on this field. So no need to create separate field and - index for storing cache key. Cache data has additional ``doc_date`` - field for MongoDB TTL collection support. - """ - return dict(_id=key, value=value, meta=meta, doc_date=doc_date) - - def _validate_ttl_index(self, collection, coll_name, ttl_seconds): - """Checks if existing TTL index is removed on a collection. - - This logs warning when existing collection has TTL index defined and - new cache configuration tries to disable index with - ``mongo_ttl_seconds < 0``. In that case, existing index needs - to be addressed first to make new configuration effective. - Refer to MongoDB documentation around TTL index for further details. - """ - indexes = collection.index_information() - for indx_name, index_data in six.iteritems(indexes): - if all(k in index_data for k in ('key', 'expireAfterSeconds')): - existing_value = index_data['expireAfterSeconds'] - fld_present = 'doc_date' in index_data['key'][0] - if fld_present and existing_value > -1 and ttl_seconds < 1: - msg = _LW('TTL index already exists on db collection ' - '<%(c_name)s>, remove index <%(indx_name)s> ' - 'first to make updated mongo_ttl_seconds value ' - 'to be effective') - LOG.warning(msg, {'c_name': coll_name, - 'indx_name': indx_name}) - - def get(self, key): - criteria = {'_id': key} - result = self.get_cache_collection().find_one(spec_or_id=criteria, - **self.meth_kwargs) - if result: - return result['value'] - else: - return None - - def get_multi(self, keys): - db_results = self._get_results_as_dict(keys) - return {doc['_id']: doc['value'] for doc in six.itervalues(db_results)} - - def _get_results_as_dict(self, keys): - criteria = {'_id': {'$in': keys}} - db_results = self.get_cache_collection().find(spec=criteria, - **self.meth_kwargs) - return {doc['_id']: doc for doc in db_results} - - def set(self, key, value): - doc_date = self._get_doc_date() - ref = self._get_cache_entry(key, value.payload, value.metadata, - doc_date) - spec = {'_id': key} - # find and modify does not have manipulator support - # so need to do conversion as part of input document - ref = self._data_manipulator.transform_incoming(ref, self) - self.get_cache_collection().find_and_modify(spec, ref, upsert=True, - **self.meth_kwargs) - - def set_multi(self, mapping): - """Insert multiple documents specified as key, value pairs. - - In this case, multiple documents can be added via insert provided they - do not exist. - Update of multiple existing documents is done one by one - """ - doc_date = self._get_doc_date() - insert_refs = [] - update_refs = [] - existing_docs = self._get_results_as_dict(list(mapping.keys())) - for key, value in mapping.items(): - ref = self._get_cache_entry(key, value.payload, value.metadata, - doc_date) - if key in existing_docs: - ref['_id'] = existing_docs[key]['_id'] - update_refs.append(ref) - else: - insert_refs.append(ref) - if insert_refs: - self.get_cache_collection().insert(insert_refs, manipulate=True, - **self.meth_kwargs) - for upd_doc in update_refs: - self.get_cache_collection().save(upd_doc, manipulate=True, - **self.meth_kwargs) - - def delete(self, key): - criteria = {'_id': key} - self.get_cache_collection().remove(spec_or_id=criteria, - **self.meth_kwargs) - - def delete_multi(self, keys): - criteria = {'_id': {'$in': keys}} - self.get_cache_collection().remove(spec_or_id=criteria, - **self.meth_kwargs) - - -@six.add_metaclass(abc.ABCMeta) -class AbstractManipulator(object): - """Abstract class with methods which need to be implemented for custom - manipulation. - - Adding this as a base class for :class:`.BaseTransform` instead of adding - import dependency of pymongo specific class i.e. - `pymongo.son_manipulator.SONManipulator` and using that as base class. - This is done to avoid pymongo dependency if MongoDB backend is not used. - """ - @abc.abstractmethod - def transform_incoming(self, son, collection): - """Used while saving data to MongoDB. - - :param son: the SON object to be inserted into the database - :param collection: the collection the object is being inserted into - - :returns: transformed SON object - - """ - raise NotImplementedError() # pragma: no cover - - @abc.abstractmethod - def transform_outgoing(self, son, collection): - """Used while reading data from MongoDB. - - :param son: the SON object being retrieved from the database - :param collection: the collection this object was stored in - - :returns: transformed SON object - """ - raise NotImplementedError() # pragma: no cover - - def will_copy(self): - """Will this SON manipulator make a copy of the incoming document? - - Derived classes that do need to make a copy should override this - method, returning `True` instead of `False`. - - :returns: boolean - """ - return False - - -class BaseTransform(AbstractManipulator): - """Base transformation class to store and read dogpile cached data - from MongoDB. - - This is needed as dogpile internally stores data as a custom class - i.e. dogpile.cache.api.CachedValue - - Note: Custom manipulator needs to always override ``transform_incoming`` - and ``transform_outgoing`` methods. MongoDB manipulator logic specifically - checks that overridden method in instance and its super are different. - """ - - def transform_incoming(self, son, collection): - """Used while saving data to MongoDB.""" - for (key, value) in list(son.items()): - if isinstance(value, api.CachedValue): - son[key] = value.payload # key is 'value' field here - son['meta'] = value.metadata - elif isinstance(value, dict): # Make sure we recurse into sub-docs - son[key] = self.transform_incoming(value, collection) - return son - - def transform_outgoing(self, son, collection): - """Used while reading data from MongoDB.""" - metadata = None - # make sure its top level dictionary with all expected fields names - # present - if isinstance(son, dict) and all(k in son for k in - ('_id', 'value', 'meta', 'doc_date')): - payload = son.pop('value', None) - metadata = son.pop('meta', None) - for (key, value) in list(son.items()): - if isinstance(value, dict): - son[key] = self.transform_outgoing(value, collection) - if metadata is not None: - son['value'] = api.CachedValue(payload, metadata) - return son diff --git a/oslo_cache/core.py b/oslo_cache/core.py deleted file mode 100644 index 63d1d1d..0000000 --- a/oslo_cache/core.py +++ /dev/null @@ -1,372 +0,0 @@ -# Copyright 2013 Metacloud -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Caching Layer Implementation. - -To use this library: - -You must call :func:`configure`. - -Inside your application code, decorate the methods that you want the results -to be cached with a memoization decorator created with -:func:`get_memoization_decorator`. This function takes a group name from the -config. Register [`group`] ``caching`` and [`group`] ``cache_time`` options -for the groups that your decorators use so that caching can be configured. - -This library's configuration options must be registered in your application's -:class:`oslo_config.cfg.ConfigOpts` instance. Do this by passing the ConfigOpts -instance to :func:`configure`. - -The library has special public value for nonexistent or expired keys called -:data:`NO_VALUE`. To use this value you should import it from oslo_cache.core:: - - from oslo_cache import core - NO_VALUE = core.NO_VALUE -""" - -import dogpile.cache -from dogpile.cache import api -from dogpile.cache import proxy -from dogpile.cache import util -from oslo_log import log -from oslo_utils import importutils - -from oslo_cache._i18n import _ -from oslo_cache._i18n import _LE -from oslo_cache import _opts -from oslo_cache import exception - - -__all__ = [ - 'configure', - 'configure_cache_region', - 'create_region', - 'get_memoization_decorator', - 'NO_VALUE', -] - -NO_VALUE = api.NO_VALUE -"""Value returned for nonexistent or expired keys.""" - -_LOG = log.getLogger(__name__) - - -class _DebugProxy(proxy.ProxyBackend): - """Extra Logging ProxyBackend.""" - # NOTE(morganfainberg): Pass all key/values through repr to ensure we have - # a clean description of the information. Without use of repr, it might - # be possible to run into encode/decode error(s). For logging/debugging - # purposes encode/decode is irrelevant and we should be looking at the - # data exactly as it stands. - - def get(self, key): - value = self.proxied.get(key) - _LOG.debug('CACHE_GET: Key: "%(key)r" Value: "%(value)r"', - {'key': key, 'value': value}) - return value - - def get_multi(self, keys): - values = self.proxied.get_multi(keys) - _LOG.debug('CACHE_GET_MULTI: "%(keys)r" Values: "%(values)r"', - {'keys': keys, 'values': values}) - return values - - def set(self, key, value): - _LOG.debug('CACHE_SET: Key: "%(key)r" Value: "%(value)r"', - {'key': key, 'value': value}) - return self.proxied.set(key, value) - - def set_multi(self, keys): - _LOG.debug('CACHE_SET_MULTI: "%r"', keys) - self.proxied.set_multi(keys) - - def delete(self, key): - self.proxied.delete(key) - _LOG.debug('CACHE_DELETE: "%r"', key) - - def delete_multi(self, keys): - _LOG.debug('CACHE_DELETE_MULTI: "%r"', keys) - self.proxied.delete_multi(keys) - - -def _build_cache_config(conf): - """Build the cache region dictionary configuration. - - :returns: dict - """ - prefix = conf.cache.config_prefix - conf_dict = {} - conf_dict['%s.backend' % prefix] = _opts._DEFAULT_BACKEND - if conf.cache.enabled is True: - conf_dict['%s.backend' % prefix] = conf.cache.backend - conf_dict['%s.expiration_time' % prefix] = conf.cache.expiration_time - for argument in conf.cache.backend_argument: - try: - (argname, argvalue) = argument.split(':', 1) - except ValueError: - msg = _LE('Unable to build cache config-key. Expected format ' - '":". Skipping unknown format: %s') - _LOG.error(msg, argument) - continue - - arg_key = '.'.join([prefix, 'arguments', argname]) - conf_dict[arg_key] = argvalue - - _LOG.debug('Oslo Cache Config: %s', conf_dict) - # NOTE(yorik-sar): these arguments will be used for memcache-related - # backends. Use setdefault for url to support old-style setting through - # backend_argument=url:127.0.0.1:11211 - conf_dict.setdefault('%s.arguments.url' % prefix, - conf.cache.memcache_servers) - for arg in ('dead_retry', 'socket_timeout', 'pool_maxsize', - 'pool_unused_timeout', 'pool_connection_get_timeout'): - value = getattr(conf.cache, 'memcache_' + arg) - conf_dict['%s.arguments.%s' % (prefix, arg)] = value - - return conf_dict - - -def _sha1_mangle_key(key): - """Wrapper for dogpile's sha1_mangle_key. - - dogpile's sha1_mangle_key function expects an encoded string, so we - should take steps to properly handle multiple inputs before passing - the key through. - """ - try: - key = key.encode('utf-8', errors='xmlcharrefreplace') - except (UnicodeError, AttributeError): - # NOTE(stevemar): if encoding fails just continue anyway. - pass - return util.sha1_mangle_key(key) - - -def create_region(): - """Create a region. - - This is just dogpile.cache.make_region, but the key generator has a - different to_str mechanism. - - .. note:: - - You must call :func:`configure_cache_region` with this region before - a memoized method is called. - - :returns: The new region. - :rtype: :class:`dogpile.cache.region.CacheRegion` - - """ - - return dogpile.cache.make_region( - function_key_generator=_function_key_generator) - - -def configure_cache_region(conf, region): - """Configure a cache region. - - If the cache region is already configured, this function does nothing. - Otherwise, the region is configured. - - :param conf: config object, must have had :func:`configure` called on it. - :type conf: oslo_config.cfg.ConfigOpts - :param region: Cache region to configure (see :func:`create_region`). - :type region: dogpile.cache.region.CacheRegion - :raises oslo_cache.exception.ConfigurationError: If the region parameter is - not a dogpile.cache.CacheRegion. - :returns: The region. - :rtype: :class:`dogpile.cache.region.CacheRegion` - """ - if not isinstance(region, dogpile.cache.CacheRegion): - raise exception.ConfigurationError( - _('region not type dogpile.cache.CacheRegion')) - - if not region.is_configured: - # NOTE(morganfainberg): this is how you tell if a region is configured. - # There is a request logged with dogpile.cache upstream to make this - # easier / less ugly. - - config_dict = _build_cache_config(conf) - region.configure_from_config(config_dict, - '%s.' % conf.cache.config_prefix) - - if conf.cache.debug_cache_backend: - region.wrap(_DebugProxy) - - # NOTE(morganfainberg): if the backend requests the use of a - # key_mangler, we should respect that key_mangler function. If a - # key_mangler is not defined by the backend, use the sha1_mangle_key - # mangler provided by dogpile.cache. This ensures we always use a fixed - # size cache-key. - if region.key_mangler is None: - region.key_mangler = _sha1_mangle_key - - for class_path in conf.cache.proxies: - # NOTE(morganfainberg): if we have any proxy wrappers, we should - # ensure they are added to the cache region's backend. Since - # configure_from_config doesn't handle the wrap argument, we need - # to manually add the Proxies. For information on how the - # ProxyBackends work, see the dogpile.cache documents on - # "changing-backend-behavior" - cls = importutils.import_class(class_path) - _LOG.debug("Adding cache-proxy '%s' to backend.", class_path) - region.wrap(cls) - - return region - - -def _get_should_cache_fn(conf, group): - """Build a function that returns a config group's caching status. - - For any given object that has caching capabilities, a boolean config option - for that object's group should exist and default to ``True``. This - function will use that value to tell the caching decorator if caching for - that object is enabled. To properly use this with the decorator, pass this - function the configuration group and assign the result to a variable. - Pass the new variable to the caching decorator as the named argument - ``should_cache_fn``. - - :param conf: config object, must have had :func:`configure` called on it. - :type conf: oslo_config.cfg.ConfigOpts - :param group: name of the configuration group to examine - :type group: string - :returns: function reference - """ - def should_cache(value): - if not conf.cache.enabled: - return False - conf_group = getattr(conf, group) - return getattr(conf_group, 'caching', True) - return should_cache - - -def _get_expiration_time_fn(conf, group): - """Build a function that returns a config group's expiration time status. - - For any given object that has caching capabilities, an int config option - called ``cache_time`` for that driver's group should exist and typically - default to ``None``. This function will use that value to tell the caching - decorator of the TTL override for caching the resulting objects. If the - value of the config option is ``None`` the default value provided in the - ``[cache] expiration_time`` option will be used by the decorator. The - default may be set to something other than ``None`` in cases where the - caching TTL should not be tied to the global default(s). - - To properly use this with the decorator, pass this function the - configuration group and assign the result to a variable. Pass the new - variable to the caching decorator as the named argument - ``expiration_time``. - - :param group: name of the configuration group to examine - :type group: string - :rtype: function reference - """ - def get_expiration_time(): - conf_group = getattr(conf, group) - return getattr(conf_group, 'cache_time', None) - return get_expiration_time - - -def _key_generate_to_str(s): - # NOTE(morganfainberg): Since we need to stringify all arguments, attempt - # to stringify and handle the Unicode error explicitly as needed. - try: - return str(s) - except UnicodeEncodeError: - return s.encode('utf-8') - - -def _function_key_generator(namespace, fn, to_str=_key_generate_to_str): - # NOTE(morganfainberg): This wraps dogpile.cache's default - # function_key_generator to change the default to_str mechanism. - return util.function_key_generator(namespace, fn, to_str=to_str) - - -def get_memoization_decorator(conf, region, group, expiration_group=None): - """Build a function based on the `cache_on_arguments` decorator. - - The memoization decorator that gets created by this function is a - :meth:`dogpile.cache.region.CacheRegion.cache_on_arguments` decorator, - where - - * The ``should_cache_fn`` is set to a function that returns True if both - the ``[cache] enabled`` option is true and [`group`] ``caching`` is - True. - - * The ``expiration_time`` is set from the - [`expiration_group`] ``cache_time`` option if ``expiration_group`` - is passed in and the value is set, or [`group`] ``cache_time`` if - ``expiration_group`` is not passed in and the value is set, or - ``[cache] expiration_time`` otherwise. - - Example usage:: - - import oslo_cache.core - - MEMOIZE = oslo_cache.core.get_memoization_decorator(conf, - group='group1') - - @MEMOIZE - def function(arg1, arg2): - ... - - - ALTERNATE_MEMOIZE = oslo_cache.core.get_memoization_decorator( - conf, group='group2', expiration_group='group3') - - @ALTERNATE_MEMOIZE - def function2(arg1, arg2): - ... - - :param conf: config object, must have had :func:`configure` called on it. - :type conf: oslo_config.cfg.ConfigOpts - :param region: region as created by :func:`create_region`. - :type region: dogpile.cache.region.CacheRegion - :param group: name of the configuration group to examine - :type group: string - :param expiration_group: name of the configuration group to examine - for the expiration option. This will fall back to - using ``group`` if the value is unspecified or - ``None`` - :type expiration_group: string - :rtype: function reference - """ - if expiration_group is None: - expiration_group = group - should_cache = _get_should_cache_fn(conf, group) - expiration_time = _get_expiration_time_fn(conf, expiration_group) - - memoize = region.cache_on_arguments(should_cache_fn=should_cache, - expiration_time=expiration_time) - - # Make sure the actual "should_cache" and "expiration_time" methods are - # available. This is potentially interesting/useful to pre-seed cache - # values. - memoize.should_cache = should_cache - memoize.get_expiration_time = expiration_time - - return memoize - - -def configure(conf): - """Configure the library. - - Register the required oslo.cache config options into an oslo.config CONF - object. - - This must be called before :py:func:`configure_cache_region`. - - :param conf: The configuration object. - :type conf: oslo_config.cfg.ConfigOpts - """ - _opts.configure(conf) diff --git a/oslo_cache/exception.py b/oslo_cache/exception.py deleted file mode 100644 index 3fb31c4..0000000 --- a/oslo_cache/exception.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class ConfigurationError(Exception): - """Raised when the cache isn't configured correctly.""" - - -class QueueEmpty(Exception): - """Raised when a connection cannot be acquired.""" diff --git a/oslo_cache/locale/de/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/de/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index 8b50448..0000000 --- a/oslo_cache/locale/de/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,54 +0,0 @@ -# Tom Cocozzello , 2015. #zanata -# Alex Eng , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.9.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-12 08:30+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-06-03 05:50+0000\n" -"Last-Translator: Alex Eng \n" -"Language-Team: German\n" -"Language: de\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"Ungültiger Wert %s für ssl_cert_reqs, muss lauten \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "" -"Verbindung konnte von Pool-ID %(id)s nach %(seconds)s nicht abgerufen werden." - -msgid "cache_collection name is required" -msgstr "Ein Name für cache_collection ist erforderlich" - -msgid "database db_name is required" -msgstr "Die Datenbank db_name ist erforderlich" - -msgid "db_hosts value is required" -msgstr "Ein Wert für db_hosts ist erforderlich" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "Ganzzahlwert für mongo_ttl_seconds erwartet" - -msgid "integer value expected for w (write concern attribute)" -msgstr "Ganzzahlwert für Attribut 'w' ('write concern'-Attribut) erwartet" - -msgid "no ssl support available" -msgstr "Keine SSL-Unterstützung verfügbar" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "Region weist nicht den Typ 'dogpile.cache.CacheRegion' auf" - -msgid "replicaset_name required when use_replica is True" -msgstr "replicaset_name erforderlich, wenn use_replica 'True' ist" diff --git a/oslo_cache/locale/en_GB/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/en_GB/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index 9bb72fd..0000000 --- a/oslo_cache/locale/en_GB/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,53 +0,0 @@ -# Andi Chandler , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-06-28 05:53+0000\n" -"Last-Translator: Andi Chandler \n" -"Language-Team: English (United Kingdom)\n" -"Language: en-GB\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." - -msgid "cache_collection name is required" -msgstr "cache_collection name is required" - -msgid "database db_name is required" -msgstr "database db_name is required" - -msgid "db_hosts value is required" -msgstr "db_hosts value is required" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "integer value expected for mongo_ttl_seconds" - -msgid "integer value expected for w (write concern attribute)" -msgstr "integer value expected for w (write concern attribute)" - -msgid "no ssl support available" -msgstr "no SSL support available" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "region not type dogpile.cache.CacheRegion" - -msgid "replicaset_name required when use_replica is True" -msgstr "replicaset_name required when use_replica is True" diff --git a/oslo_cache/locale/es/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/es/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index b2101c0..0000000 --- a/oslo_cache/locale/es/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,57 +0,0 @@ -# OpenStack Infra , 2015. #zanata -# Tom Cocozzello , 2015. #zanata -# Alex Eng , 2016. #zanata -# KATO Tomoyuki , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-07-02 08:19+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: Spanish\n" -"Language: es\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"Valor ssl_cert_reqs no válido de %s, debe ser uno de \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "" -"No se puede obtener una conexión del ID de agrupación %(id)s después de " -"%(seconds)s segundos." - -msgid "cache_collection name is required" -msgstr "el nombre de cache_collection es necesario" - -msgid "database db_name is required" -msgstr "base de datos db_name es necesario" - -msgid "db_hosts value is required" -msgstr "El valor db_hosts es necesario" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "se esperaba un valor entero para mongo_ttl_seconds" - -msgid "integer value expected for w (write concern attribute)" -msgstr "se esperaba un valor entero para w (atributo en cuestión write)" - -msgid "no ssl support available" -msgstr "Soporte SSL no disponible" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "región no tipo dogpile.cache.CacheRegion" - -msgid "replicaset_name required when use_replica is True" -msgstr "se necesita replicaset_name cuando use_replica es True (verdadero)" diff --git a/oslo_cache/locale/fr/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/fr/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index ebe83f5..0000000 --- a/oslo_cache/locale/fr/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,57 +0,0 @@ -# OpenStack Infra , 2015. #zanata -# Tom Cocozzello , 2015. #zanata -# Alex Eng , 2016. #zanata -# KATO Tomoyuki , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-07-02 08:20+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: French\n" -"Language: fr\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=2; plural=(n > 1)\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"Valeur de ssl_cert_reqs non valide (%s), doit être l'une des valeurs " -"suivantes: \"NONE\", \"OPTIONAL\", \"REQUIRED\"" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "" -"Impossible d'établir une connexion à partir de l'ID de pool %(id)s après " -"%(seconds)s secondes." - -msgid "cache_collection name is required" -msgstr "Nom cache_collection est requis" - -msgid "database db_name is required" -msgstr "db_name database est requis" - -msgid "db_hosts value is required" -msgstr "Valeur db_hosts est requis" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "valeur entière attendue pour mongo_ttl_seconds" - -msgid "integer value expected for w (write concern attribute)" -msgstr "valeur entière attendue pour w (attribut d'écriture)" - -msgid "no ssl support available" -msgstr "pas de support du ssl" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "la région n'est pas de type dogpile.cache.CacheRegion" - -msgid "replicaset_name required when use_replica is True" -msgstr "replicaset_name requis si use_replica a la valeur True" diff --git a/oslo_cache/locale/it/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/it/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index e91d084..0000000 --- a/oslo_cache/locale/it/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,56 +0,0 @@ -# Tom Cocozzello , 2015. #zanata -# Alex Eng , 2016. #zanata -# KATO Tomoyuki , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-07-02 08:21+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: Italian\n" -"Language: it\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"Valore ssl_cert_reqs di %s non valido; deve essere uno tra \"NONE\", " -"\"OPTIONAL\", \"REQUIRED\"" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "" -"Impossibile ottenere una connessione dall'ID pool %(id)s dopo %(seconds)s " -"secondi." - -msgid "cache_collection name is required" -msgstr "Il nome cache_collection è obbligatorio" - -msgid "database db_name is required" -msgstr "Il database db_name è obbligatorio" - -msgid "db_hosts value is required" -msgstr "Il valore db_hosts è obbligatorio" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "valore intero previsto per mongo_ttl_seconds" - -msgid "integer value expected for w (write concern attribute)" -msgstr "valore intero previsto per w (attributo di scrittura)" - -msgid "no ssl support available" -msgstr "nessun supporto ssl disponibile" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "regione non tipo dogpile.cache.CacheRegion" - -msgid "replicaset_name required when use_replica is True" -msgstr "replicaset_name è obbligatorio quando use_replica è True" diff --git a/oslo_cache/locale/ko_KR/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/ko_KR/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index 8fa91be..0000000 --- a/oslo_cache/locale/ko_KR/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,54 +0,0 @@ -# Lucas Palm , 2015. #zanata -# Alex Eng , 2016. #zanata -# KATO Tomoyuki , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-07-02 08:22+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: Korean (South Korea)\n" -"Language: ko-KR\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=1; plural=0\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"%s의 ssl_cert_reqs 값이 올바르지 않음, \"NONE\", \"OPTIONAL\", \"REQUIRED\" " -"중 하나여야 함 " - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "풀 id %(id)s에서 %(seconds)s분 후에 연결할 수 없습니다." - -msgid "cache_collection name is required" -msgstr "cache_collection 이름이 필요함" - -msgid "database db_name is required" -msgstr "database db_name이 필요함" - -msgid "db_hosts value is required" -msgstr "db_hosts 값이 필요함" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "mongo_ttl_seconds 에 대해 정수 값이 예상됨 " - -msgid "integer value expected for w (write concern attribute)" -msgstr "w(write concern 속성)에 대해 정수 값이 예상됨" - -msgid "no ssl support available" -msgstr "사용 가능한 ssl 지원이 없음" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "리젼이 dogpile.cache.CacheRegion 유형이 아님 " - -msgid "replicaset_name required when use_replica is True" -msgstr "use_replica가 True인 경우 replicaset_name이 필요함 " diff --git a/oslo_cache/locale/pt_BR/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/pt_BR/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index bc768db..0000000 --- a/oslo_cache/locale/pt_BR/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,57 +0,0 @@ -# Lucas Palm , 2015. #zanata -# OpenStack Infra , 2015. #zanata -# Alex Eng , 2016. #zanata -# KATO Tomoyuki , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-07-02 08:23+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: Portuguese (Brazil)\n" -"Language: pt-BR\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"valor ssl_cert_reqs inválido de %s, deve ser um de \"NONE\", \"OPTIMAL\", " -"\"REQUIRED\"" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "" -"Não é possível obter uma conexão do ID do conjunto %(id)s após %(seconds)s " -"segundos." - -msgid "cache_collection name is required" -msgstr "nome cache_collection é necessário" - -msgid "database db_name is required" -msgstr "banco de dados db_name é necessário" - -msgid "db_hosts value is required" -msgstr "valor db_hosts é necessário" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "valor de número inteiro esperado para mongo_ttl_seconds" - -msgid "integer value expected for w (write concern attribute)" -msgstr "valor inteiro esperado para w (atributo relativo a gravação)" - -msgid "no ssl support available" -msgstr "suporte ssl não disponível" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "região não é do tipo dogpile.cache.CacheRegion" - -msgid "replicaset_name required when use_replica is True" -msgstr "replicaset_name necessário quando use_replica for True" diff --git a/oslo_cache/locale/ru/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/ru/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index ae41a1b..0000000 --- a/oslo_cache/locale/ru/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,58 +0,0 @@ -# Lucas Palm , 2015. #zanata -# Alex Eng , 2016. #zanata -# KATO Tomoyuki , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-07-02 08:24+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: Russian\n" -"Language: ru\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"Недопустимое значение ssl_cert_reqs, %s, необходимо указать одно из " -"значений: \"NONE\", \"OPTIONAL\", \"REQUIRED\"" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "" -"Не удалось получить соединение из пула с ИД %(id)s за %(seconds)s секунд." - -msgid "cache_collection name is required" -msgstr "имя cache_collection является обязательным" - -msgid "database db_name is required" -msgstr "db_name базы данных является обязательным" - -msgid "db_hosts value is required" -msgstr "Значение db_hosts является обязательным" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "для атрибута mongo_ttl_seconds ожидается целочисленное значение" - -msgid "integer value expected for w (write concern attribute)" -msgstr "для w (атрибут участия в записи) ожидается целочисленное значение" - -msgid "no ssl support available" -msgstr "отсутствует поддержка ssl" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "регион не относится к типу dogpile.cache.CacheRegion" - -msgid "replicaset_name required when use_replica is True" -msgstr "" -"replicaset_name является обязательным, если для use_replica задано значение " -"True" diff --git a/oslo_cache/locale/tr_TR/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/tr_TR/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index ba9efc6..0000000 --- a/oslo_cache/locale/tr_TR/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,54 +0,0 @@ -# OpenStack Infra , 2015. #zanata -# Alex Eng , 2016. #zanata -# KATO Tomoyuki , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-07-02 08:25+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: Turkish (Turkey)\n" -"Language: tr-TR\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=2; plural=(n>1)\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"%s değerinde geçersiz ssl_cert_reqs, \"HİÇBİRİ\", \"İSTEĞE BAĞLI\", " -"\"GEREKLİ\" den biri olmalı" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "%(seconds)s saniye sonra havuz %(id)s'den bağlantı alınamadı." - -msgid "cache_collection name is required" -msgstr "cache_collection ismi gerekli" - -msgid "database db_name is required" -msgstr "veri tabanı db_name gerekli" - -msgid "db_hosts value is required" -msgstr "db_hosts değeri gerekli" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "mongo_ttl_seconds için tam sayı değer bekleniyor" - -msgid "integer value expected for w (write concern attribute)" -msgstr "w için tam sayı değer bekleniyor (yazma ilgisi özniteliği)" - -msgid "no ssl support available" -msgstr "ssl desteği yok" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "bölge dogpile.cache.CacheRegion türünde değil" - -msgid "replicaset_name required when use_replica is True" -msgstr "use_replica True olduğunda replicaset_name gereklidir" diff --git a/oslo_cache/locale/zh_CN/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/zh_CN/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index a908e9a..0000000 --- a/oslo_cache/locale/zh_CN/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,53 +0,0 @@ -# Lucas Palm , 2015. #zanata -# Alex Eng , 2016. #zanata -# KATO Tomoyuki , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-07-02 08:27+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: Chinese (China)\n" -"Language: zh-CN\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=1; plural=0\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"ssl_cert_reqs 值 %s 无效,必须是下列其中一项:“NONE”、“OPTIONAL”和“REQUIRED”" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "在 %(seconds)s 秒之后,无法根据池标识 %(id)s 获取连接。" - -msgid "cache_collection name is required" -msgstr "需要 cache_collection 名称" - -msgid "database db_name is required" -msgstr "需要数据库 db_name" - -msgid "db_hosts value is required" -msgstr "需要 db_hosts 值" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "mongo_ttl_seconds 需要整数值" - -msgid "integer value expected for w (write concern attribute)" -msgstr "w(写相关属性)需要整数值" - -msgid "no ssl support available" -msgstr "未提供 ssl 支持" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "区域的类型不是 dogpile.cache.CacheRegion" - -msgid "replicaset_name required when use_replica is True" -msgstr "当 use_replica 为 True 时,需要 replicaset_name" diff --git a/oslo_cache/locale/zh_TW/LC_MESSAGES/oslo_cache.po b/oslo_cache/locale/zh_TW/LC_MESSAGES/oslo_cache.po deleted file mode 100644 index 8d112dd..0000000 --- a/oslo_cache/locale/zh_TW/LC_MESSAGES/oslo_cache.po +++ /dev/null @@ -1,54 +0,0 @@ -# Lucas Palm , 2015. #zanata -# Alex Eng , 2016. #zanata -# KATO Tomoyuki , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache 1.10.1.dev2\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-07-02 08:26+0000\n" -"Last-Translator: KATO Tomoyuki \n" -"Language-Team: Chinese (Taiwan)\n" -"Language: zh-TW\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=1; plural=0\n" - -#, python-format -msgid "" -"Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\", " -"\"REQUIRED\"" -msgstr "" -"%s 的 ssl_cert_reqs 值無效,必須是 \"NONE\"、\"OPTIONAL\" 及 \"REQUIRED\" 的" -"其中之一" - -#, python-format -msgid "" -"Unable to get a connection from pool id %(id)s after %(seconds)s seconds." -msgstr "在 %(seconds)s 秒之後,無法從儲存區 ID %(id)s 取得連線。" - -msgid "cache_collection name is required" -msgstr "需要 cache_collection 名稱" - -msgid "database db_name is required" -msgstr "需要資料庫 db_name" - -msgid "db_hosts value is required" -msgstr "需要 db_hosts 值" - -msgid "integer value expected for mongo_ttl_seconds" -msgstr "mongo_ttl_seconds 預期整數值" - -msgid "integer value expected for w (write concern attribute)" -msgstr "w(WriteConcern 屬性)預期整數值" - -msgid "no ssl support available" -msgstr "無法使用 SSL 支援" - -msgid "region not type dogpile.cache.CacheRegion" -msgstr "區域不是 dogpile.cache.CacheRegion 類型" - -msgid "replicaset_name required when use_replica is True" -msgstr "use_replica 為 True 時需要 replicaset_name" diff --git a/oslo_cache/testing.py b/oslo_cache/testing.py deleted file mode 100644 index 8abfcff..0000000 --- a/oslo_cache/testing.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2013 Metacloud -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Items useful for external testing.""" - - -import copy - -from dogpile.cache import proxy - -from oslo_cache import core as cache - - -__all__ = [ - 'CacheIsolatingProxy', -] - - -NO_VALUE = cache.NO_VALUE - - -def _copy_value(value): - if value is not NO_VALUE: - value = copy.deepcopy(value) - return value - - -# NOTE(morganfainberg): WARNING - It is not recommended to use the Memory -# backend for dogpile.cache in a real deployment under any circumstances. The -# backend does no cleanup of expired values and therefore will leak memory. The -# backend is not implemented in a way to share data across processes (e.g. -# Keystone in HTTPD. This proxy is a hack to get around the lack of isolation -# of values in memory. Currently it blindly stores and retrieves the values -# from the cache, and modifications to dicts/lists/etc returned can result in -# changes to the cached values. In short, do not use the dogpile.cache.memory -# backend unless you are running tests or expecting odd/strange results. -class CacheIsolatingProxy(proxy.ProxyBackend): - """Proxy that forces a memory copy of stored values. - - The default in-memory cache-region does not perform a copy on values it - is meant to cache. Therefore if the value is modified after set or after - get, the cached value also is modified. This proxy does a copy as the last - thing before storing data. - - In your application's tests, you'll want to set this as a proxy for the - in-memory cache, like this:: - - self.config_fixture.config( - group='cache', - backend='dogpile.cache.memory', - enabled=True, - proxies=['oslo_cache.testing.CacheIsolatingProxy']) - - """ - def get(self, key): - return _copy_value(self.proxied.get(key)) - - def set(self, key, value): - self.proxied.set(key, _copy_value(value)) diff --git a/oslo_cache/tests/__init__.py b/oslo_cache/tests/__init__.py deleted file mode 100644 index f34b057..0000000 --- a/oslo_cache/tests/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_cache import core - -from oslo_config import cfg - - -core.configure(cfg.CONF) diff --git a/oslo_cache/tests/test_cache.py b/oslo_cache/tests/test_cache.py deleted file mode 100644 index 1cbea46..0000000 --- a/oslo_cache/tests/test_cache.py +++ /dev/null @@ -1,326 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2013 Metacloud -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import time -import uuid - -from dogpile.cache import proxy -import mock -from oslo_config import cfg -from oslo_config import fixture as config_fixture -from oslotest import base - -from oslo_cache import _opts -from oslo_cache import core as cache -from oslo_cache import exception - - -NO_VALUE = cache.NO_VALUE -TEST_GROUP = uuid.uuid4().hex -TEST_GROUP2 = uuid.uuid4().hex - - -class BaseTestCase(base.BaseTestCase): - def setUp(self): - super(BaseTestCase, self).setUp() - self.config_fixture = self.useFixture(config_fixture.Config()) - self.config_fixture.config( - # TODO(morganfainberg): Make Cache Testing a separate test case - # in tempest, and move it out of the base unit tests. - group='cache', - backend='dogpile.cache.memory', - enabled=True, - proxies=['oslo_cache.testing.CacheIsolatingProxy']) - - -def _copy_value(value): - if value is not NO_VALUE: - value = copy.deepcopy(value) - return value - - -class TestProxy(proxy.ProxyBackend): - def get(self, key): - value = _copy_value(self.proxied.get(key)) - if value is not NO_VALUE: - if isinstance(value[0], TestProxyValue): - value[0].cached = True - return value - - -class TestProxyValue(object): - def __init__(self, value): - self.value = value - self.cached = False - - -class CacheRegionTest(BaseTestCase): - - def setUp(self): - super(CacheRegionTest, self).setUp() - self.region = cache.create_region() - cache.configure_cache_region(self.config_fixture.conf, self.region) - self.region.wrap(TestProxy) - self.test_value = TestProxyValue('Decorator Test') - - def _add_test_caching_option(self): - self.config_fixture.register_opt( - cfg.BoolOpt('caching', default=True), group='cache') - - def _add_dummy_config_group(self): - self.config_fixture.register_opt( - cfg.IntOpt('cache_time', default=None), group=TEST_GROUP) - self.config_fixture.register_opt( - cfg.IntOpt('cache_time', default=None), group=TEST_GROUP2) - - def _get_cacheable_function(self): - memoize = cache.get_memoization_decorator( - self.config_fixture.conf, self.region, group='cache') - - @memoize - def cacheable_function(value): - return value - - return cacheable_function - - def test_region_built_with_proxy_direct_cache_test(self): - # Verify cache regions are properly built with proxies. - test_value = TestProxyValue('Direct Cache Test') - self.region.set('cache_test', test_value) - cached_value = self.region.get('cache_test') - self.assertTrue(cached_value.cached) - - def test_cache_region_no_error_multiple_config(self): - # Verify configuring the CacheRegion again doesn't error. - cache.configure_cache_region(self.config_fixture.conf, self.region) - cache.configure_cache_region(self.config_fixture.conf, self.region) - - def _get_cache_fallthrough_fn(self, cache_time): - memoize = cache.get_memoization_decorator( - self.config_fixture.conf, - self.region, - group='cache', - expiration_group=TEST_GROUP2) - - class _test_obj(object): - def __init__(self, value): - self.test_value = value - - @memoize - def get_test_value(self): - return self.test_value - - def _do_test(value): - - test_obj = _test_obj(value) - - # Ensure the value has been cached - test_obj.get_test_value() - # Get the now cached value - cached_value = test_obj.get_test_value() - self.assertTrue(cached_value.cached) - self.assertEqual(value.value, cached_value.value) - self.assertEqual(cached_value.value, test_obj.test_value.value) - # Change the underlying value on the test object. - test_obj.test_value = TestProxyValue(uuid.uuid4().hex) - self.assertEqual(cached_value.value, - test_obj.get_test_value().value) - # override the system time to ensure the non-cached new value - # is returned - new_time = time.time() + (cache_time * 2) - with mock.patch.object(time, 'time', - return_value=new_time): - overriden_cache_value = test_obj.get_test_value() - self.assertNotEqual(cached_value.value, - overriden_cache_value.value) - self.assertEqual(test_obj.test_value.value, - overriden_cache_value.value) - - return _do_test - - def test_cache_no_fallthrough_expiration_time_fn(self): - self._add_dummy_config_group() - # Since we do not re-configure the cache region, for ease of testing - # this value is set the same as the expiration_time default in the - # [cache] group - cache_time = 600 - expiration_time = cache._get_expiration_time_fn( - self.config_fixture.conf, TEST_GROUP) - do_test = self._get_cache_fallthrough_fn(cache_time) - # Run the test with the dummy group cache_time value - self.config_fixture.config(cache_time=cache_time, - group=TEST_GROUP) - test_value = TestProxyValue(uuid.uuid4().hex) - self.assertEqual(cache_time, expiration_time()) - do_test(value=test_value) - - def test_cache_fallthrough_expiration_time_fn(self): - self._add_dummy_config_group() - # Since we do not re-configure the cache region, for ease of testing - # this value is set the same as the expiration_time default in the - # [cache] group - cache_time = 599 - expiration_time = cache._get_expiration_time_fn( - self.config_fixture.conf, TEST_GROUP) - do_test = self._get_cache_fallthrough_fn(cache_time) - # Run the test with the dummy group cache_time value set to None and - # the global value set. - self.config_fixture.config(cache_time=None, group=TEST_GROUP) - test_value = TestProxyValue(uuid.uuid4().hex) - self.assertIsNone(expiration_time()) - do_test(value=test_value) - - def test_should_cache_fn_global_cache_enabled(self): - # Verify should_cache_fn generates a sane function for subsystem and - # functions as expected with caching globally enabled. - cacheable_function = self._get_cacheable_function() - - self.config_fixture.config(group='cache', enabled=True) - cacheable_function(self.test_value) - cached_value = cacheable_function(self.test_value) - self.assertTrue(cached_value.cached) - - def test_should_cache_fn_global_cache_disabled(self): - # Verify should_cache_fn generates a sane function for subsystem and - # functions as expected with caching globally disabled. - cacheable_function = self._get_cacheable_function() - - self.config_fixture.config(group='cache', enabled=False) - cacheable_function(self.test_value) - cached_value = cacheable_function(self.test_value) - self.assertFalse(cached_value.cached) - - def test_should_cache_fn_global_cache_disabled_group_cache_enabled(self): - # Verify should_cache_fn generates a sane function for subsystem and - # functions as expected with caching globally disabled and the specific - # group caching enabled. - cacheable_function = self._get_cacheable_function() - - self._add_test_caching_option() - self.config_fixture.config(group='cache', enabled=False) - self.config_fixture.config(group='cache', caching=True) - - cacheable_function(self.test_value) - cached_value = cacheable_function(self.test_value) - self.assertFalse(cached_value.cached) - - def test_should_cache_fn_global_cache_enabled_group_cache_disabled(self): - # Verify should_cache_fn generates a sane function for subsystem and - # functions as expected with caching globally enabled and the specific - # group caching disabled. - cacheable_function = self._get_cacheable_function() - - self._add_test_caching_option() - self.config_fixture.config(group='cache', enabled=True) - self.config_fixture.config(group='cache', caching=False) - - cacheable_function(self.test_value) - cached_value = cacheable_function(self.test_value) - self.assertFalse(cached_value.cached) - - def test_should_cache_fn_global_cache_enabled_group_cache_enabled(self): - # Verify should_cache_fn generates a sane function for subsystem and - # functions as expected with caching globally enabled and the specific - # group caching enabled. - cacheable_function = self._get_cacheable_function() - - self._add_test_caching_option() - self.config_fixture.config(group='cache', enabled=True) - self.config_fixture.config(group='cache', caching=True) - - cacheable_function(self.test_value) - cached_value = cacheable_function(self.test_value) - self.assertTrue(cached_value.cached) - - def test_cache_dictionary_config_builder(self): - """Validate we build a sane dogpile.cache dictionary config.""" - self.config_fixture.config(group='cache', - config_prefix='test_prefix', - backend='some_test_backend', - expiration_time=86400, - backend_argument=['arg1:test', - 'arg2:test:test', - 'arg3.invalid']) - - config_dict = cache._build_cache_config(self.config_fixture.conf) - self.assertEqual( - self.config_fixture.conf.cache.backend, - config_dict['test_prefix.backend']) - self.assertEqual( - self.config_fixture.conf.cache.expiration_time, - config_dict['test_prefix.expiration_time']) - self.assertEqual('test', config_dict['test_prefix.arguments.arg1']) - self.assertEqual('test:test', - config_dict['test_prefix.arguments.arg2']) - self.assertNotIn('test_prefix.arguments.arg3', config_dict) - - def test_cache_dictionary_config_builder_global_disabled(self): - """Validate the backend is reset to default if caching is disabled.""" - self.config_fixture.config(group='cache', - enabled=False, - config_prefix='test_prefix', - backend='some_test_backend') - - self.assertFalse(self.config_fixture.conf.cache.enabled) - config_dict = cache._build_cache_config(self.config_fixture.conf) - self.assertEqual( - _opts._DEFAULT_BACKEND, - config_dict['test_prefix.backend']) - - def test_cache_debug_proxy(self): - single_value = 'Test Value' - single_key = 'testkey' - multi_values = {'key1': 1, 'key2': 2, 'key3': 3} - - self.region.set(single_key, single_value) - self.assertEqual(single_value, self.region.get(single_key)) - - self.region.delete(single_key) - self.assertEqual(NO_VALUE, self.region.get(single_key)) - - self.region.set_multi(multi_values) - cached_values = self.region.get_multi(multi_values.keys()) - for value in multi_values.values(): - self.assertIn(value, cached_values) - self.assertEqual(len(multi_values.values()), len(cached_values)) - - self.region.delete_multi(multi_values.keys()) - for value in self.region.get_multi(multi_values.keys()): - self.assertEqual(NO_VALUE, value) - - def test_configure_non_region_object_raises_error(self): - self.assertRaises(exception.ConfigurationError, - cache.configure_cache_region, - self.config_fixture.conf, - "bogus") - - -class UTF8KeyManglerTests(BaseTestCase): - - def test_key_is_utf8_encoded(self): - key = u'fäké1' - encoded = cache._sha1_mangle_key(key) - self.assertIsNotNone(encoded) - - def test_key_is_bytestring(self): - key = b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82' - encoded = cache._sha1_mangle_key(key) - self.assertIsNotNone(encoded) - - def test_key_is_string(self): - key = 'fake' - encoded = cache._sha1_mangle_key(key) - self.assertIsNotNone(encoded) diff --git a/oslo_cache/tests/test_cache_backend_mongo.py b/oslo_cache/tests/test_cache_backend_mongo.py deleted file mode 100644 index fcedd08..0000000 --- a/oslo_cache/tests/test_cache_backend_mongo.py +++ /dev/null @@ -1,727 +0,0 @@ -# Copyright 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import collections -import copy -import functools -import uuid - -from dogpile.cache import region as dp_region -import six -from six.moves import range - -from oslo_cache.backends import mongo -from oslo_cache import core -from oslo_cache import exception -from oslo_cache.tests import test_cache - -# Mock database structure sample where 'ks_cache' is database and -# 'cache' is collection. Dogpile CachedValue data is divided in two -# fields `value` (CachedValue.payload) and `meta` (CachedValue.metadata) -ks_cache = { - "cache": [ - { - "value": { - "serviceType": "identity", - "allVersionsUrl": "https://dummyUrl", - "dateLastModified": "ISODDate(2014-02-08T18:39:13.237Z)", - "serviceName": "Identity", - "enabled": "True" - }, - "meta": { - "v": 1, - "ct": 1392371422.015121 - }, - "doc_date": "ISODate('2014-02-14T09:50:22.015Z')", - "_id": "8251dc95f63842719c077072f1047ddf" - }, - { - "value": "dummyValueX", - "meta": { - "v": 1, - "ct": 1392371422.014058 - }, - "doc_date": "ISODate('2014-02-14T09:50:22.014Z')", - "_id": "66730b9534d146f0804d23729ad35436" - } - ] -} - - -COLLECTIONS = {} -SON_MANIPULATOR = None -NO_VALUE = core.NO_VALUE - - -class MockCursor(object): - - def __init__(self, collection, dataset_factory): - super(MockCursor, self).__init__() - self.collection = collection - self._factory = dataset_factory - self._dataset = self._factory() - self._limit = None - self._skip = None - - def __iter__(self): - return self - - def __next__(self): - if self._skip: - for _ in range(self._skip): - next(self._dataset) - self._skip = None - if self._limit is not None and self._limit <= 0: - raise StopIteration() - if self._limit is not None: - self._limit -= 1 - return next(self._dataset) - - next = __next__ - - def __getitem__(self, index): - arr = [x for x in self._dataset] - self._dataset = iter(arr) - return arr[index] - - -class MockCollection(object): - - def __init__(self, db, name): - super(MockCollection, self).__init__() - self.name = name - self._collection_database = db - self._documents = {} - self.write_concern = {} - - def __getattr__(self, name): - if name == 'database': - return self._collection_database - - def ensure_index(self, key_or_list, *args, **kwargs): - pass - - def index_information(self): - return {} - - def find_one(self, spec_or_id=None, *args, **kwargs): - if spec_or_id is None: - spec_or_id = {} - if not isinstance(spec_or_id, collections.Mapping): - spec_or_id = {'_id': spec_or_id} - - try: - return next(self.find(spec_or_id, *args, **kwargs)) - except StopIteration: - return None - - def find(self, spec=None, *args, **kwargs): - return MockCursor(self, functools.partial(self._get_dataset, spec)) - - def _get_dataset(self, spec): - dataset = (self._copy_doc(document, dict) for document in - self._iter_documents(spec)) - return dataset - - def _iter_documents(self, spec=None): - return (SON_MANIPULATOR.transform_outgoing(document, self) for - document in six.itervalues(self._documents) - if self._apply_filter(document, spec)) - - def _apply_filter(self, document, query): - for key, search in six.iteritems(query): - doc_val = document.get(key) - if isinstance(search, dict): - op_dict = {'$in': lambda dv, sv: dv in sv} - is_match = all( - op_str in op_dict and op_dict[op_str](doc_val, search_val) - for op_str, search_val in six.iteritems(search) - ) - else: - is_match = doc_val == search - - return is_match - - def _copy_doc(self, obj, container): - if isinstance(obj, list): - new = [] - for item in obj: - new.append(self._copy_doc(item, container)) - return new - if isinstance(obj, dict): - new = container() - for key, value in list(obj.items()): - new[key] = self._copy_doc(value, container) - return new - else: - return copy.copy(obj) - - def insert(self, data, manipulate=True, **kwargs): - if isinstance(data, list): - return [self._insert(element) for element in data] - return self._insert(data) - - def save(self, data, manipulate=True, **kwargs): - return self._insert(data) - - def _insert(self, data): - if '_id' not in data: - data['_id'] = uuid.uuid4().hex - object_id = data['_id'] - self._documents[object_id] = self._internalize_dict(data) - return object_id - - def find_and_modify(self, spec, document, upsert=False, **kwargs): - self.update(spec, document, upsert, **kwargs) - - def update(self, spec, document, upsert=False, **kwargs): - - existing_docs = [doc for doc in six.itervalues(self._documents) - if self._apply_filter(doc, spec)] - if existing_docs: - existing_doc = existing_docs[0] # should find only 1 match - _id = existing_doc['_id'] - existing_doc.clear() - existing_doc['_id'] = _id - existing_doc.update(self._internalize_dict(document)) - elif upsert: - existing_doc = self._documents[self._insert(document)] - - def _internalize_dict(self, d): - return {k: copy.deepcopy(v) for k, v in six.iteritems(d)} - - def remove(self, spec_or_id=None, search_filter=None): - """Remove objects matching spec_or_id from the collection.""" - if spec_or_id is None: - spec_or_id = search_filter if search_filter else {} - if not isinstance(spec_or_id, dict): - spec_or_id = {'_id': spec_or_id} - to_delete = list(self.find(spec=spec_or_id)) - for doc in to_delete: - doc_id = doc['_id'] - del self._documents[doc_id] - - return { - "connectionId": uuid.uuid4().hex, - "n": len(to_delete), - "ok": 1.0, - "err": None, - } - - -class MockMongoDB(object): - def __init__(self, dbname): - self._dbname = dbname - - def authenticate(self, username, password): - pass - - def add_son_manipulator(self, manipulator): - global SON_MANIPULATOR - SON_MANIPULATOR = manipulator - - def __getattr__(self, name): - if name == 'authenticate': - return self.authenticate - elif name == 'name': - return self._dbname - elif name == 'add_son_manipulator': - return self.add_son_manipulator - else: - return get_collection(self._dbname, name) - - def __getitem__(self, name): - return get_collection(self._dbname, name) - - -class MockMongoClient(object): - def __init__(self, *args, **kwargs): - pass - - def __getattr__(self, dbname): - return MockMongoDB(dbname) - - -def get_collection(db_name, collection_name): - mongo_collection = MockCollection(MockMongoDB(db_name), collection_name) - return mongo_collection - - -def pymongo_override(): - global pymongo - import pymongo - if pymongo.MongoClient is not MockMongoClient: - pymongo.MongoClient = MockMongoClient - if pymongo.MongoReplicaSetClient is not MockMongoClient: - pymongo.MongoClient = MockMongoClient - - -class MyTransformer(mongo.BaseTransform): - """Added here just to check manipulator logic is used correctly.""" - - def transform_incoming(self, son, collection): - return super(MyTransformer, self).transform_incoming(son, collection) - - def transform_outgoing(self, son, collection): - return super(MyTransformer, self).transform_outgoing(son, collection) - - -class MongoCache(test_cache.BaseTestCase): - def setUp(self): - super(MongoCache, self).setUp() - global COLLECTIONS - COLLECTIONS = {} - mongo.MongoApi._DB = {} - mongo.MongoApi._MONGO_COLLS = {} - pymongo_override() - # using typical configuration - self.arguments = { - 'db_hosts': 'localhost:27017', - 'db_name': 'ks_cache', - 'cache_collection': 'cache', - 'username': 'test_user', - 'password': 'test_password' - } - - def test_missing_db_hosts(self): - self.arguments.pop('db_hosts') - region = dp_region.make_region() - self.assertRaises(exception.ConfigurationError, region.configure, - 'oslo_cache.mongo', - arguments=self.arguments) - - def test_missing_db_name(self): - self.arguments.pop('db_name') - region = dp_region.make_region() - self.assertRaises(exception.ConfigurationError, region.configure, - 'oslo_cache.mongo', - arguments=self.arguments) - - def test_missing_cache_collection_name(self): - self.arguments.pop('cache_collection') - region = dp_region.make_region() - self.assertRaises(exception.ConfigurationError, region.configure, - 'oslo_cache.mongo', - arguments=self.arguments) - - def test_incorrect_write_concern(self): - self.arguments['w'] = 'one value' - region = dp_region.make_region() - self.assertRaises(exception.ConfigurationError, region.configure, - 'oslo_cache.mongo', - arguments=self.arguments) - - def test_correct_write_concern(self): - self.arguments['w'] = 1 - region = dp_region.make_region().configure('oslo_cache.mongo', - arguments=self.arguments) - - random_key = uuid.uuid4().hex - region.set(random_key, "dummyValue10") - # There is no proxy so can access MongoCacheBackend directly - self.assertEqual(1, region.backend.api.w) - - def test_incorrect_read_preference(self): - self.arguments['read_preference'] = 'inValidValue' - region = dp_region.make_region().configure('oslo_cache.mongo', - arguments=self.arguments) - # As per delayed loading of pymongo, read_preference value should - # still be string and NOT enum - self.assertEqual('inValidValue', region.backend.api.read_preference) - - random_key = uuid.uuid4().hex - self.assertRaises(ValueError, region.set, - random_key, "dummyValue10") - - def test_correct_read_preference(self): - self.arguments['read_preference'] = 'secondaryPreferred' - region = dp_region.make_region().configure('oslo_cache.mongo', - arguments=self.arguments) - # As per delayed loading of pymongo, read_preference value should - # still be string and NOT enum - self.assertEqual('secondaryPreferred', - region.backend.api.read_preference) - - random_key = uuid.uuid4().hex - region.set(random_key, "dummyValue10") - - # Now as pymongo is loaded so expected read_preference value is enum. - # There is no proxy so can access MongoCacheBackend directly - self.assertEqual(3, region.backend.api.read_preference) - - def test_missing_replica_set_name(self): - self.arguments['use_replica'] = True - region = dp_region.make_region() - self.assertRaises(exception.ConfigurationError, region.configure, - 'oslo_cache.mongo', - arguments=self.arguments) - - def test_provided_replica_set_name(self): - self.arguments['use_replica'] = True - self.arguments['replicaset_name'] = 'my_replica' - dp_region.make_region().configure('oslo_cache.mongo', - arguments=self.arguments) - self.assertTrue(True) # reached here means no initialization error - - def test_incorrect_mongo_ttl_seconds(self): - self.arguments['mongo_ttl_seconds'] = 'sixty' - region = dp_region.make_region() - self.assertRaises(exception.ConfigurationError, region.configure, - 'oslo_cache.mongo', - arguments=self.arguments) - - def test_cache_configuration_values_assertion(self): - self.arguments['use_replica'] = True - self.arguments['replicaset_name'] = 'my_replica' - self.arguments['mongo_ttl_seconds'] = 60 - self.arguments['ssl'] = False - region = dp_region.make_region().configure('oslo_cache.mongo', - arguments=self.arguments) - # There is no proxy so can access MongoCacheBackend directly - self.assertEqual('localhost:27017', region.backend.api.hosts) - self.assertEqual('ks_cache', region.backend.api.db_name) - self.assertEqual('cache', region.backend.api.cache_collection) - self.assertEqual('test_user', region.backend.api.username) - self.assertEqual('test_password', region.backend.api.password) - self.assertEqual(True, region.backend.api.use_replica) - self.assertEqual('my_replica', region.backend.api.replicaset_name) - self.assertEqual(False, region.backend.api.conn_kwargs['ssl']) - self.assertEqual(60, region.backend.api.ttl_seconds) - - def test_multiple_region_cache_configuration(self): - arguments1 = copy.copy(self.arguments) - arguments1['cache_collection'] = 'cache_region1' - - region1 = dp_region.make_region().configure('oslo_cache.mongo', - arguments=arguments1) - # There is no proxy so can access MongoCacheBackend directly - self.assertEqual('localhost:27017', region1.backend.api.hosts) - self.assertEqual('ks_cache', region1.backend.api.db_name) - self.assertEqual('cache_region1', region1.backend.api.cache_collection) - self.assertEqual('test_user', region1.backend.api.username) - self.assertEqual('test_password', region1.backend.api.password) - # Should be None because of delayed initialization - self.assertIsNone(region1.backend.api._data_manipulator) - - random_key1 = uuid.uuid4().hex - region1.set(random_key1, "dummyValue10") - self.assertEqual("dummyValue10", region1.get(random_key1)) - # Now should have initialized - self.assertIsInstance(region1.backend.api._data_manipulator, - mongo.BaseTransform) - - class_name = '%s.%s' % (MyTransformer.__module__, "MyTransformer") - - arguments2 = copy.copy(self.arguments) - arguments2['cache_collection'] = 'cache_region2' - arguments2['son_manipulator'] = class_name - - region2 = dp_region.make_region().configure('oslo_cache.mongo', - arguments=arguments2) - # There is no proxy so can access MongoCacheBackend directly - self.assertEqual('localhost:27017', region2.backend.api.hosts) - self.assertEqual('ks_cache', region2.backend.api.db_name) - self.assertEqual('cache_region2', region2.backend.api.cache_collection) - - # Should be None because of delayed initialization - self.assertIsNone(region2.backend.api._data_manipulator) - - random_key = uuid.uuid4().hex - region2.set(random_key, "dummyValue20") - self.assertEqual("dummyValue20", region2.get(random_key)) - # Now should have initialized - self.assertIsInstance(region2.backend.api._data_manipulator, - MyTransformer) - - region1.set(random_key1, "dummyValue22") - self.assertEqual("dummyValue22", region1.get(random_key1)) - - def test_typical_configuration(self): - - dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - self.assertTrue(True) # reached here means no initialization error - - def test_backend_get_missing_data(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - - random_key = uuid.uuid4().hex - # should return NO_VALUE as key does not exist in cache - self.assertEqual(NO_VALUE, region.get(random_key)) - - def test_backend_set_data(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - - random_key = uuid.uuid4().hex - region.set(random_key, "dummyValue") - self.assertEqual("dummyValue", region.get(random_key)) - - def test_backend_set_data_with_string_as_valid_ttl(self): - - self.arguments['mongo_ttl_seconds'] = '3600' - region = dp_region.make_region().configure('oslo_cache.mongo', - arguments=self.arguments) - self.assertEqual(3600, region.backend.api.ttl_seconds) - random_key = uuid.uuid4().hex - region.set(random_key, "dummyValue") - self.assertEqual("dummyValue", region.get(random_key)) - - def test_backend_set_data_with_int_as_valid_ttl(self): - - self.arguments['mongo_ttl_seconds'] = 1800 - region = dp_region.make_region().configure('oslo_cache.mongo', - arguments=self.arguments) - self.assertEqual(1800, region.backend.api.ttl_seconds) - random_key = uuid.uuid4().hex - region.set(random_key, "dummyValue") - self.assertEqual("dummyValue", region.get(random_key)) - - def test_backend_set_none_as_data(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - - random_key = uuid.uuid4().hex - region.set(random_key, None) - self.assertIsNone(region.get(random_key)) - - def test_backend_set_blank_as_data(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - - random_key = uuid.uuid4().hex - region.set(random_key, "") - self.assertEqual("", region.get(random_key)) - - def test_backend_set_same_key_multiple_times(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - - random_key = uuid.uuid4().hex - region.set(random_key, "dummyValue") - self.assertEqual("dummyValue", region.get(random_key)) - - dict_value = {'key1': 'value1'} - region.set(random_key, dict_value) - self.assertEqual(dict_value, region.get(random_key)) - - region.set(random_key, "dummyValue2") - self.assertEqual("dummyValue2", region.get(random_key)) - - def test_backend_multi_set_data(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - random_key = uuid.uuid4().hex - random_key1 = uuid.uuid4().hex - random_key2 = uuid.uuid4().hex - random_key3 = uuid.uuid4().hex - mapping = {random_key1: 'dummyValue1', - random_key2: 'dummyValue2', - random_key3: 'dummyValue3'} - region.set_multi(mapping) - # should return NO_VALUE as key does not exist in cache - self.assertEqual(NO_VALUE, region.get(random_key)) - self.assertFalse(region.get(random_key)) - self.assertEqual("dummyValue1", region.get(random_key1)) - self.assertEqual("dummyValue2", region.get(random_key2)) - self.assertEqual("dummyValue3", region.get(random_key3)) - - def test_backend_multi_get_data(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - random_key = uuid.uuid4().hex - random_key1 = uuid.uuid4().hex - random_key2 = uuid.uuid4().hex - random_key3 = uuid.uuid4().hex - mapping = {random_key1: 'dummyValue1', - random_key2: '', - random_key3: 'dummyValue3'} - region.set_multi(mapping) - - keys = [random_key, random_key1, random_key2, random_key3] - results = region.get_multi(keys) - # should return NO_VALUE as key does not exist in cache - self.assertEqual(NO_VALUE, results[0]) - self.assertEqual("dummyValue1", results[1]) - self.assertEqual("", results[2]) - self.assertEqual("dummyValue3", results[3]) - - def test_backend_multi_set_should_update_existing(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - random_key = uuid.uuid4().hex - random_key1 = uuid.uuid4().hex - random_key2 = uuid.uuid4().hex - random_key3 = uuid.uuid4().hex - mapping = {random_key1: 'dummyValue1', - random_key2: 'dummyValue2', - random_key3: 'dummyValue3'} - region.set_multi(mapping) - # should return NO_VALUE as key does not exist in cache - self.assertEqual(NO_VALUE, region.get(random_key)) - self.assertEqual("dummyValue1", region.get(random_key1)) - self.assertEqual("dummyValue2", region.get(random_key2)) - self.assertEqual("dummyValue3", region.get(random_key3)) - - mapping = {random_key1: 'dummyValue4', - random_key2: 'dummyValue5'} - region.set_multi(mapping) - self.assertEqual(NO_VALUE, region.get(random_key)) - self.assertEqual("dummyValue4", region.get(random_key1)) - self.assertEqual("dummyValue5", region.get(random_key2)) - self.assertEqual("dummyValue3", region.get(random_key3)) - - def test_backend_multi_set_get_with_blanks_none(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - random_key = uuid.uuid4().hex - random_key1 = uuid.uuid4().hex - random_key2 = uuid.uuid4().hex - random_key3 = uuid.uuid4().hex - random_key4 = uuid.uuid4().hex - mapping = {random_key1: 'dummyValue1', - random_key2: None, - random_key3: '', - random_key4: 'dummyValue4'} - region.set_multi(mapping) - # should return NO_VALUE as key does not exist in cache - self.assertEqual(NO_VALUE, region.get(random_key)) - self.assertEqual("dummyValue1", region.get(random_key1)) - self.assertIsNone(region.get(random_key2)) - self.assertEqual("", region.get(random_key3)) - self.assertEqual("dummyValue4", region.get(random_key4)) - - keys = [random_key, random_key1, random_key2, random_key3, random_key4] - results = region.get_multi(keys) - - # should return NO_VALUE as key does not exist in cache - self.assertEqual(NO_VALUE, results[0]) - self.assertEqual("dummyValue1", results[1]) - self.assertIsNone(results[2]) - self.assertEqual("", results[3]) - self.assertEqual("dummyValue4", results[4]) - - mapping = {random_key1: 'dummyValue5', - random_key2: 'dummyValue6'} - region.set_multi(mapping) - self.assertEqual(NO_VALUE, region.get(random_key)) - self.assertEqual("dummyValue5", region.get(random_key1)) - self.assertEqual("dummyValue6", region.get(random_key2)) - self.assertEqual("", region.get(random_key3)) - - def test_backend_delete_data(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - - random_key = uuid.uuid4().hex - region.set(random_key, "dummyValue") - self.assertEqual("dummyValue", region.get(random_key)) - - region.delete(random_key) - # should return NO_VALUE as key no longer exists in cache - self.assertEqual(NO_VALUE, region.get(random_key)) - - def test_backend_multi_delete_data(self): - - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - random_key = uuid.uuid4().hex - random_key1 = uuid.uuid4().hex - random_key2 = uuid.uuid4().hex - random_key3 = uuid.uuid4().hex - mapping = {random_key1: 'dummyValue1', - random_key2: 'dummyValue2', - random_key3: 'dummyValue3'} - region.set_multi(mapping) - # should return NO_VALUE as key does not exist in cache - self.assertEqual(NO_VALUE, region.get(random_key)) - self.assertEqual("dummyValue1", region.get(random_key1)) - self.assertEqual("dummyValue2", region.get(random_key2)) - self.assertEqual("dummyValue3", region.get(random_key3)) - self.assertEqual(NO_VALUE, region.get("InvalidKey")) - - keys = mapping.keys() - - region.delete_multi(keys) - - self.assertEqual(NO_VALUE, region.get("InvalidKey")) - # should return NO_VALUE as keys no longer exist in cache - self.assertEqual(NO_VALUE, region.get(random_key1)) - self.assertEqual(NO_VALUE, region.get(random_key2)) - self.assertEqual(NO_VALUE, region.get(random_key3)) - - def test_additional_crud_method_arguments_support(self): - """Additional arguments should works across find/insert/update.""" - - self.arguments['wtimeout'] = 30000 - self.arguments['j'] = True - self.arguments['continue_on_error'] = True - self.arguments['secondary_acceptable_latency_ms'] = 60 - region = dp_region.make_region().configure( - 'oslo_cache.mongo', - arguments=self.arguments - ) - - # There is no proxy so can access MongoCacheBackend directly - api_methargs = region.backend.api.meth_kwargs - self.assertEqual(30000, api_methargs['wtimeout']) - self.assertEqual(True, api_methargs['j']) - self.assertEqual(True, api_methargs['continue_on_error']) - self.assertEqual(60, api_methargs['secondary_acceptable_latency_ms']) - - random_key = uuid.uuid4().hex - region.set(random_key, "dummyValue1") - self.assertEqual("dummyValue1", region.get(random_key)) - - region.set(random_key, "dummyValue2") - self.assertEqual("dummyValue2", region.get(random_key)) - - random_key = uuid.uuid4().hex - region.set(random_key, "dummyValue3") - self.assertEqual("dummyValue3", region.get(random_key)) diff --git a/oslo_cache/tests/test_connection_pool.py b/oslo_cache/tests/test_connection_pool.py deleted file mode 100644 index 07ea7f1..0000000 --- a/oslo_cache/tests/test_connection_pool.py +++ /dev/null @@ -1,147 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import threading -import time - -import mock -import six -from six.moves import queue -import testtools -from testtools import matchers - -from oslo_cache import _memcache_pool -from oslo_cache import exception -from oslo_cache.tests import test_cache - - -class _TestConnectionPool(_memcache_pool.ConnectionPool): - destroyed_value = 'destroyed' - - def _create_connection(self): - return mock.MagicMock() - - def _destroy_connection(self, conn): - conn(self.destroyed_value) - - -class TestConnectionPool(test_cache.BaseTestCase): - def setUp(self): - super(TestConnectionPool, self).setUp() - self.unused_timeout = 10 - self.maxsize = 2 - self.connection_pool = _TestConnectionPool( - maxsize=self.maxsize, - unused_timeout=self.unused_timeout) - self.addCleanup(self.cleanup_instance('connection_pool')) - - def cleanup_instance(self, *names): - """Create a function suitable for use with self.addCleanup. - - :returns: a callable that uses a closure to delete instance attributes - """ - - def cleanup(): - for name in names: - if hasattr(self, name): - delattr(self, name) - return cleanup - - def test_get_context_manager(self): - self.assertThat(self.connection_pool.queue, matchers.HasLength(0)) - with self.connection_pool.acquire() as conn: - self.assertEqual(1, self.connection_pool._acquired) - self.assertEqual(0, self.connection_pool._acquired) - self.assertThat(self.connection_pool.queue, matchers.HasLength(1)) - self.assertEqual(conn, self.connection_pool.queue[0].connection) - - def test_cleanup_pool(self): - self.test_get_context_manager() - newtime = time.time() + self.unused_timeout * 2 - non_expired_connection = _memcache_pool._PoolItem( - ttl=(newtime * 2), - connection=mock.MagicMock()) - self.connection_pool.queue.append(non_expired_connection) - self.assertThat(self.connection_pool.queue, matchers.HasLength(2)) - with mock.patch.object(time, 'time', return_value=newtime): - conn = self.connection_pool.queue[0].connection - with self.connection_pool.acquire(): - pass - conn.assert_has_calls( - [mock.call(self.connection_pool.destroyed_value)]) - self.assertThat(self.connection_pool.queue, matchers.HasLength(1)) - self.assertEqual(0, non_expired_connection.connection.call_count) - - def test_acquire_conn_exception_returns_acquired_count(self): - class TestException(Exception): - pass - - with mock.patch.object(_TestConnectionPool, '_create_connection', - side_effect=TestException): - with testtools.ExpectedException(TestException): - with self.connection_pool.acquire(): - pass - self.assertThat(self.connection_pool.queue, - matchers.HasLength(0)) - self.assertEqual(0, self.connection_pool._acquired) - - def test_connection_pool_limits_maximum_connections(self): - # NOTE(morganfainberg): To ensure we don't lockup tests until the - # job limit, explicitly call .get_nowait() and .put_nowait() in this - # case. - conn1 = self.connection_pool.get_nowait() - conn2 = self.connection_pool.get_nowait() - - # Use a nowait version to raise an Empty exception indicating we would - # not get another connection until one is placed back into the queue. - self.assertRaises(queue.Empty, self.connection_pool.get_nowait) - - # Place the connections back into the pool. - self.connection_pool.put_nowait(conn1) - self.connection_pool.put_nowait(conn2) - - # Make sure we can get a connection out of the pool again. - self.connection_pool.get_nowait() - - def test_connection_pool_maximum_connection_get_timeout(self): - connection_pool = _TestConnectionPool( - maxsize=1, - unused_timeout=self.unused_timeout, - conn_get_timeout=0) - - def _acquire_connection(): - with connection_pool.acquire(): - pass - - # Make sure we've consumed the only available connection from the pool - conn = connection_pool.get_nowait() - - self.assertRaises(exception.QueueEmpty, _acquire_connection) - - # Put the connection back and ensure we can acquire the connection - # after it is available. - connection_pool.put_nowait(conn) - _acquire_connection() - - -class TestMemcacheClientOverrides(test_cache.BaseTestCase): - - def test_client_stripped_of_threading_local(self): - """threading.local overrides are restored for _MemcacheClient""" - client_class = _memcache_pool._MemcacheClient - # get the genuine thread._local from MRO - thread_local = client_class.__mro__[2] - self.assertTrue(thread_local is threading.local) - for field in six.iterkeys(thread_local.__dict__): - if field not in ('__dict__', '__weakref__'): - self.assertNotEqual(id(getattr(thread_local, field, None)), - id(getattr(client_class, field, None))) diff --git a/oslo_cache/tests/test_dict_backend.py b/oslo_cache/tests/test_dict_backend.py deleted file mode 100644 index be3ddb1..0000000 --- a/oslo_cache/tests/test_dict_backend.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright 2015 Mirantis Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from dogpile.cache import region as dp_region - -from oslo_cache import core -from oslo_cache.tests import test_cache -from oslo_config import fixture as config_fixture -from oslo_utils import fixture as time_fixture - - -NO_VALUE = core.NO_VALUE -KEY = 'test_key' -VALUE = 'test_value' - - -class CacheDictBackendTest(test_cache.BaseTestCase): - - def setUp(self): - super(CacheDictBackendTest, self).setUp() - self.config_fixture = self.useFixture(config_fixture.Config()) - self.config_fixture.config(group='cache', backend='oslo_cache.dict') - self.time_fixture = self.useFixture(time_fixture.TimeFixture()) - self.region = dp_region.make_region() - self.region.configure( - 'oslo_cache.dict', arguments={'expiration_time': 0.5}) - - def test_dict_backend(self): - self.assertIs(NO_VALUE, self.region.get(KEY)) - - self.region.set(KEY, VALUE) - self.assertEqual(VALUE, self.region.get(KEY)) - - self.region.delete(KEY) - self.assertIs(NO_VALUE, self.region.get(KEY)) - - def test_dict_backend_expiration_time(self): - self.region.set(KEY, VALUE) - self.assertEqual(VALUE, self.region.get(KEY)) - - self.time_fixture.advance_time_seconds(1) - self.assertIs(NO_VALUE, self.region.get(KEY)) - - def test_dict_backend_clear_cache(self): - self.region.set(KEY, VALUE) - - self.time_fixture.advance_time_seconds(1) - - self.assertEqual(1, len(self.region.backend.cache)) - self.region.backend._clear() - self.assertEqual(0, len(self.region.backend.cache)) - - def test_dict_backend_zero_expiration_time(self): - self.region = dp_region.make_region() - self.region.configure( - 'oslo_cache.dict', arguments={'expiration_time': 0}) - - self.region.set(KEY, VALUE) - self.time_fixture.advance_time_seconds(1) - - self.assertEqual(VALUE, self.region.get(KEY)) - self.assertEqual(1, len(self.region.backend.cache)) - - self.region.backend._clear() - - self.assertEqual(VALUE, self.region.get(KEY)) - self.assertEqual(1, len(self.region.backend.cache)) - - def test_dict_backend_multi_keys(self): - self.region.set('key1', 'value1') - self.region.set('key2', 'value2') - self.time_fixture.advance_time_seconds(1) - self.region.set('key3', 'value3') - - self.assertEqual(1, len(self.region.backend.cache)) - self.assertIs(NO_VALUE, self.region.get('key1')) - self.assertIs(NO_VALUE, self.region.get('key2')) - self.assertEqual('value3', self.region.get('key3')) - - def test_dict_backend_multi_keys_in_one_call(self): - single_value = 'Test Value' - single_key = 'testkey' - multi_values = {'key1': 1, 'key2': 2, 'key3': 3} - - self.region.set(single_key, single_value) - self.assertEqual(single_value, self.region.get(single_key)) - - self.region.delete(single_key) - self.assertEqual(NO_VALUE, self.region.get(single_key)) - - self.region.set_multi(multi_values) - cached_values = self.region.get_multi(multi_values.keys()) - for value in multi_values.values(): - self.assertIn(value, cached_values) - self.assertEqual(len(multi_values.values()), len(cached_values)) - - self.region.delete_multi(multi_values.keys()) - for value in self.region.get_multi(multi_values.keys()): - self.assertEqual(NO_VALUE, value) - - def test_dict_backend_rewrite_value(self): - self.region.set(KEY, 'value1') - self.region.set(KEY, 'value2') - self.assertEqual('value2', self.region.get(KEY)) diff --git a/oslo_cache/version.py b/oslo_cache/version.py deleted file mode 100644 index 23c3ecd..0000000 --- a/oslo_cache/version.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2016 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import pbr.version - -version_info = pbr.version.VersionInfo('oslo_cache') diff --git a/releasenotes/notes/add_reno-3b4ae0789e9c45b4.yaml b/releasenotes/notes/add_reno-3b4ae0789e9c45b4.yaml deleted file mode 100644 index 46a2da6..0000000 --- a/releasenotes/notes/add_reno-3b4ae0789e9c45b4.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -other: - - Switch to reno for managing release notes. \ No newline at end of file diff --git a/releasenotes/source/_static/.placeholder b/releasenotes/source/_static/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/source/_templates/.placeholder b/releasenotes/source/_templates/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py deleted file mode 100644 index 81c3e96..0000000 --- a/releasenotes/source/conf.py +++ /dev/null @@ -1,273 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'oslosphinx', - 'reno.sphinxext', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'oslo.cache Release Notes' -copyright = u'2016, oslo.cache Developers' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -from oslo_cache.version import version_info as oslo_cache_version -# The full version, including alpha/beta/rc tags. -release = oslo_cache_version.version_string_with_vcs() -# The short X.Y version. -version = oslo_cache_version.canonical_version_string() - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'oslo.cacheReleaseNotesDoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # 'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ('index', 'oslo.cacheReleaseNotes.tex', - u'oslo.cache Release Notes Documentation', - u'oslo.cache Developers', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'oslo.cacheReleaseNotes', - u'oslo.cache Release Notes Documentation', - [u'oslo.cache Developers'], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'oslo.cacheReleaseNotes', - u'oslo.cache Release Notes Documentation', - u'oslo.cache Developers', 'oslo.cacheReleaseNotes', - 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst deleted file mode 100644 index 6e19934..0000000 --- a/releasenotes/source/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -============================= - oslo.cache Release Notes -============================= - - .. toctree:: - :maxdepth: 1 - - unreleased diff --git a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po deleted file mode 100644 index 9351441..0000000 --- a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po +++ /dev/null @@ -1,30 +0,0 @@ -# Andi Chandler , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.cache Release Notes 1.10.1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-07-11 22:41+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-06-28 05:54+0000\n" -"Last-Translator: Andi Chandler \n" -"Language-Team: English (United Kingdom)\n" -"Language: en-GB\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -msgid "1.9.0" -msgstr "1.9.0" - -msgid "Other Notes" -msgstr "Other Notes" - -msgid "Switch to reno for managing release notes." -msgstr "Switch to reno for managing release notes." - -msgid "Unreleased Release Notes" -msgstr "Unreleased Release Notes" - -msgid "oslo.cache Release Notes" -msgstr "oslo.cache Release Notes" diff --git a/releasenotes/source/unreleased.rst b/releasenotes/source/unreleased.rst deleted file mode 100644 index 5860a46..0000000 --- a/releasenotes/source/unreleased.rst +++ /dev/null @@ -1,5 +0,0 @@ -========================== - Unreleased Release Notes -========================== - -.. release-notes:: diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 2f4ebb9..0000000 --- a/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -dogpile.cache>=0.6.1 # BSD -six>=1.9.0 # MIT -oslo.config>=3.12.0 # Apache-2.0 -oslo.i18n>=2.1.0 # Apache-2.0 -oslo.log>=1.14.0 # Apache-2.0 -oslo.utils>=3.16.0 # Apache-2.0 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 3c88bd8..0000000 --- a/setup.cfg +++ /dev/null @@ -1,68 +0,0 @@ -[metadata] -name = oslo.cache -summary = Cache storage for Openstack projects. -description-file = - README.rst -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = http://launchpad.net/oslo -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.4 - Programming Language :: Python :: 3.5 - -[files] -packages = - oslo_cache - -[entry_points] -oslo.config.opts = - oslo.cache = oslo_cache._opts:list_opts - -dogpile.cache = - oslo_cache.mongo = oslo_cache.backends.mongo:MongoCacheBackend - oslo_cache.memcache_pool = oslo_cache.backends.memcache_pool:PooledMemcachedBackend - oslo_cache.dict = oslo_cache.backends.dictionary:DictCacheBackend - -[extras] -dogpile = - python-memcached>=1.56 # PSF -mongo = - pymongo!=3.1,>=3.0.2 # Apache-2.0 - -[pbr] -warnerrors = true -autodoc_tree_index_modules = True - -[build_sphinx] -source-dir = doc/source -build-dir = doc/build -all_files = 1 - -[upload_sphinx] -upload-dir = doc/build/html - -[compile_catalog] -directory = oslo_cache/locale -domain = oslo_cache - -[update_catalog] -domain = oslo_cache -output_dir = oslo_cache/locale -input_file = oslo_cache/locale/oslo_cache.pot - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext -mapping_file = babel.cfg -output_file = oslo_cache/locale/oslo_cache.pot - -[wheel] -universal = true diff --git a/setup.py b/setup.py deleted file mode 100644 index 782bb21..0000000 --- a/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=1.8'], - pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 0510e84..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -hacking<0.11,>=0.10.0 -mock>=2.0 # BSD -oslotest>=1.10.0 # Apache-2.0 -oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0 -sphinx!=1.3b1,<1.3,>=1.2.1 # BSD -reno>=1.8.0 # Apache2 diff --git a/tox.ini b/tox.ini deleted file mode 100644 index fb6c492..0000000 --- a/tox.ini +++ /dev/null @@ -1,43 +0,0 @@ -[tox] -minversion = 1.6 -envlist = py35,py34,py27,pypy,pep8 - -[testenv] -deps = .[dogpile] - .[mongo] - -r{toxinidir}/test-requirements.txt -commands = - find . -type f -name "*.pyc" -delete - python setup.py testr --slowest --testr-args='{posargs}' - -[testenv:pep8] -commands = flake8 - -[testenv:venv] -commands = {posargs} - -[testenv:docs] -commands = python setup.py build_sphinx - -[testenv:cover] -commands = python setup.py testr --coverage --testr-args='{posargs}' - -[flake8] -show-source = True -ignore = H405 -builtins = _ -exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build - -[hacking] -import_exceptions = - -[testenv:pip-missing-reqs] -# do not install test-requirements as that will pollute the virtualenv for -# determining missing packages -# this also means that pip-missing-reqs must be installed separately, outside -# of the requirements.txt files -deps = pip_missing_reqs -commands = pip-missing-reqs -d --ignore-module=oslo_cache* --ignore-file=oslo_cache/tests/* --ignore-file=tests/ oslo_cache - -[testenv:releasenotes] -commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html