summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavanum Srinivas <davanum@gmail.com>2015-06-28 20:58:46 -0400
committerDavanum Srinivas (dims) <davanum@gmail.com>2015-08-15 01:02:48 +0000
commit0cc2d63d78b66c9ddfccb31a050ee9498278b0f4 (patch)
tree6a40b04374b33dd237071206ccf3f61a1604dc9e
parentf7934f4d01472d9c856b7f6f8e4482bf43241d46 (diff)
downloadoslo-incubator-0cc2d63d78b66c9ddfccb31a050ee9498278b0f4.tar.gz
Remove openstack/common/report as oslo.reports is graduating
implements blueprint graduate-oslo-reports Change-Id: I6228c9ec258dd894595535f0e24e9f7ffd72d43c
-rw-r--r--MAINTAINERS5
-rw-r--r--openstack/common/report/__init__.py25
-rw-r--r--openstack/common/report/generators/__init__.py21
-rw-r--r--openstack/common/report/generators/conf.py44
-rw-r--r--openstack/common/report/generators/process.py38
-rw-r--r--openstack/common/report/generators/threading.py86
-rw-r--r--openstack/common/report/generators/version.py60
-rw-r--r--openstack/common/report/guru_meditation_report.py227
-rw-r--r--openstack/common/report/models/__init__.py20
-rw-r--r--openstack/common/report/models/base.py162
-rw-r--r--openstack/common/report/models/conf.py66
-rw-r--r--openstack/common/report/models/process.py62
-rw-r--r--openstack/common/report/models/threading.py100
-rw-r--r--openstack/common/report/models/version.py44
-rw-r--r--openstack/common/report/models/with_default_views.py81
-rw-r--r--openstack/common/report/report.py187
-rw-r--r--openstack/common/report/utils.py46
-rw-r--r--openstack/common/report/views/__init__.py22
-rw-r--r--openstack/common/report/views/jinja_view.py137
-rw-r--r--openstack/common/report/views/json/__init__.py19
-rw-r--r--openstack/common/report/views/json/generic.py66
-rw-r--r--openstack/common/report/views/text/__init__.py19
-rw-r--r--openstack/common/report/views/text/generic.py202
-rw-r--r--openstack/common/report/views/text/header.py51
-rw-r--r--openstack/common/report/views/text/process.py38
-rw-r--r--openstack/common/report/views/text/threading.py80
-rw-r--r--openstack/common/report/views/xml/__init__.py19
-rw-r--r--openstack/common/report/views/xml/generic.py87
-rw-r--r--tests/unit/reports/__init__.py0
-rw-r--r--tests/unit/reports/test_base_report.py150
-rw-r--r--tests/unit/reports/test_guru_meditation_report.py186
-rw-r--r--tests/unit/reports/test_openstack_generators.py140
-rw-r--r--tests/unit/reports/test_views.py420
33 files changed, 0 insertions, 2910 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index cd17dadb..64b973b6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -89,11 +89,6 @@ M:
S: Orphan
F: memorycache.py
-== reports ==
-
-M:
-S: Graduating
-F: report/
== scheduler ==
diff --git a/openstack/common/report/__init__.py b/openstack/common/report/__init__.py
deleted file mode 100644
index 35390ecd..00000000
--- a/openstack/common/report/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides a way to generate serializable reports
-
-This package/module provides mechanisms for defining reports
-which may then be serialized into various data types. Each
-report ( :class:`openstack.common.report.report.BasicReport` )
-is composed of one or more report sections
-( :class:`openstack.common.report.report.BasicSection` ),
-which contain generators which generate data models
-( :class:`openstack.common.report.models.base.ReportModels` ),
-which are then serialized by views.
-"""
diff --git a/openstack/common/report/generators/__init__.py b/openstack/common/report/generators/__init__.py
deleted file mode 100644
index 68473f22..00000000
--- a/openstack/common/report/generators/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides Data Model Generators
-
-This module defines classes for generating data models
-( :class:`openstack.common.report.models.base.ReportModel` ).
-A generator is any object which is callable with no parameters
-and returns a data model.
-"""
diff --git a/openstack/common/report/generators/conf.py b/openstack/common/report/generators/conf.py
deleted file mode 100644
index 619e4898..00000000
--- a/openstack/common/report/generators/conf.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides OpenStack config generators
-
-This module defines a class for configuration
-generators for generating the model in
-:mod:`openstack.common.report.models.conf`.
-"""
-
-from oslo_config import cfg
-
-from openstack.common.report.models import conf as cm
-
-
-class ConfigReportGenerator(object):
- """A Configuration Data Generator
-
- This generator returns
- :class:`openstack.common.report.models.conf.ConfigModel`,
- by default using the configuration options stored
- in :attr:`oslo_config.cfg.CONF`, which is where
- OpenStack stores everything.
-
- :param cnf: the configuration option object
- :type cnf: :class:`oslo_config.cfg.ConfigOpts`
- """
-
- def __init__(self, cnf=cfg.CONF):
- self.conf_obj = cnf
-
- def __call__(self):
- return cm.ConfigModel(self.conf_obj)
diff --git a/openstack/common/report/generators/process.py b/openstack/common/report/generators/process.py
deleted file mode 100644
index 9c2151fc..00000000
--- a/openstack/common/report/generators/process.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2014 Red Hat, 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.
-
-"""Provides process-data generators
-
-This modules defines a class for generating
-process data by way of the psutil package.
-"""
-
-import os
-
-import psutil
-
-from openstack.common.report.models import process as pm
-
-
-class ProcessReportGenerator(object):
- """A Process Data Generator
-
- This generator returns a
- :class:`openstack.common.report.models.process.ProcessModel`
- based on the current process (which will also include
- all subprocesses, recursively) using the :class:`psutil.Process` class`.
- """
-
- def __call__(self):
- return pm.ProcessModel(psutil.Process(os.getpid()))
diff --git a/openstack/common/report/generators/threading.py b/openstack/common/report/generators/threading.py
deleted file mode 100644
index b3038cf2..00000000
--- a/openstack/common/report/generators/threading.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides thread-related generators
-
-This module defines classes for threading-related
-generators for generating the models in
-:mod:`openstack.common.report.models.threading`.
-"""
-
-from __future__ import absolute_import
-
-import sys
-import threading
-
-import greenlet
-
-from openstack.common.report.models import threading as tm
-from openstack.common.report.models import with_default_views as mwdv
-from openstack.common.report import utils as rutils
-from openstack.common.report.views.text import generic as text_views
-
-
-class ThreadReportGenerator(object):
- """A Thread Data Generator
-
- This generator returns a collection of
- :class:`openstack.common.report.models.threading.ThreadModel`
- objects by introspecting the current python state using
- :func:`sys._current_frames()` . Its constructor may optionally
- be passed a frame object. This frame object will be interpreted
- as the actual stack trace for the current thread, and, come generation
- time, will be used to replace the stack trace of the thread in which
- this code is running.
- """
-
- def __init__(self, curr_thread_traceback=None):
- self.traceback = curr_thread_traceback
-
- def __call__(self):
- threadModels = dict(
- (thread_id, tm.ThreadModel(thread_id, stack))
- for thread_id, stack in sys._current_frames().items()
- )
-
- if self.traceback is not None:
- curr_thread_id = threading.current_thread().ident
- threadModels[curr_thread_id] = tm.ThreadModel(curr_thread_id,
- self.traceback)
-
- return mwdv.ModelWithDefaultViews(threadModels,
- text_view=text_views.MultiView())
-
-
-class GreenThreadReportGenerator(object):
- """A Green Thread Data Generator
-
- This generator returns a collection of
- :class:`openstack.common.report.models.threading.GreenThreadModel`
- objects by introspecting the current python garbage collection
- state, and sifting through for :class:`greenlet.greenlet` objects.
-
- .. seealso::
-
- Function :func:`openstack.common.report.utils._find_objects`
- """
-
- def __call__(self):
- threadModels = [
- tm.GreenThreadModel(gr.gr_frame)
- for gr in rutils._find_objects(greenlet.greenlet)
- ]
-
- return mwdv.ModelWithDefaultViews(threadModels,
- text_view=text_views.MultiView())
diff --git a/openstack/common/report/generators/version.py b/openstack/common/report/generators/version.py
deleted file mode 100644
index 5979f883..00000000
--- a/openstack/common/report/generators/version.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides OpenStack version generators
-
-This module defines a class for OpenStack
-version and package information
-generators for generating the model in
-:mod:`openstack.common.report.models.version`.
-"""
-
-from openstack.common.report.models import version as vm
-
-
-class PackageReportGenerator(object):
- """A Package Information Data Generator
-
- This generator returns
- :class:`openstack.common.report.models.version.PackageModel`,
- extracting data from the given version object, which should follow
- the general format defined in Nova's version information (i.e. it
- should contain the methods vendor_string, product_string, and
- version_string_with_package).
-
- :param version_object: the version information object
- """
-
- def __init__(self, version_obj):
- self.version_obj = version_obj
-
- def __call__(self):
- if hasattr(self.version_obj, "vendor_string"):
- vendor_string = self.version_obj.vendor_string()
- else:
- vendor_string = None
-
- if hasattr(self.version_obj, "product_string"):
- product_string = self.version_obj.product_string()
- else:
- product_string = None
-
- if hasattr(self.version_obj, "version_string_with_package"):
- version_string_with_package = self.version_obj.\
- version_string_with_package()
- else:
- version_string_with_package = None
-
- return vm.PackageModel(vendor_string, product_string,
- version_string_with_package)
diff --git a/openstack/common/report/guru_meditation_report.py b/openstack/common/report/guru_meditation_report.py
deleted file mode 100644
index bff9234f..00000000
--- a/openstack/common/report/guru_meditation_report.py
+++ /dev/null
@@ -1,227 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides Guru Meditation Report
-
-This module defines the actual OpenStack Guru Meditation
-Report class.
-
-This can be used in the OpenStack command definition files.
-For example, in a nova command module (under nova/cmd):
-
-.. code-block:: python
- :emphasize-lines: 8,9,10
-
- CONF = cfg.CONF
- # maybe import some options here...
-
- def main():
- config.parse_args(sys.argv)
- logging.setup('blah')
-
- TextGuruMeditation.register_section('Some Special Section',
- special_section_generator)
- TextGuruMeditation.setup_autorun(version_object)
-
- server = service.Service.create(binary='some-service',
- topic=CONF.some_service_topic)
- service.serve(server)
- service.wait()
-
-Then, you can do
-
-.. code-block:: bash
-
- $ kill -USR1 $SERVICE_PID
-
-and get a Guru Meditation Report in the file or terminal
-where stderr is logged for that given service.
-"""
-
-from __future__ import print_function
-
-import inspect
-import os
-import signal
-import sys
-
-from oslo_utils import timeutils
-
-from openstack.common.report.generators import conf as cgen
-from openstack.common.report.generators import process as prgen
-from openstack.common.report.generators import threading as tgen
-from openstack.common.report.generators import version as pgen
-from openstack.common.report import report
-
-
-class GuruMeditation(object):
- """A Guru Meditation Report Mixin/Base Class
-
- This class is a base class for Guru Meditation Reports.
- It provides facilities for registering sections and
- setting up functionality to auto-run the report on
- a certain signal.
-
- This class should always be used in conjunction with
- a Report class via multiple inheritance. It should
- always come first in the class list to ensure the
- MRO is correct.
- """
-
- timestamp_fmt = "%Y%m%d%H%M%S"
-
- def __init__(self, version_obj, sig_handler_tb=None, *args, **kwargs):
- self.version_obj = version_obj
- self.traceback = sig_handler_tb
-
- super(GuruMeditation, self).__init__(*args, **kwargs)
- self.start_section_index = len(self.sections)
-
- @classmethod
- def register_section(cls, section_title, generator):
- """Register a New Section
-
- This method registers a persistent section for the current
- class.
-
- :param str section_title: the title of the section
- :param generator: the generator for the section
- """
-
- try:
- cls.persistent_sections.append([section_title, generator])
- except AttributeError:
- cls.persistent_sections = [[section_title, generator]]
-
- @classmethod
- def setup_autorun(cls, version, service_name=None,
- log_dir=None, signum=None):
- """Set Up Auto-Run
-
- This method sets up the Guru Meditation Report to automatically
- get dumped to stderr or a file in a given dir when the given signal
- is received.
-
- :param version: the version object for the current product
- :param service_name: this program name used to construct logfile name
- :param logdir: path to a log directory where to create a file
- :param signum: the signal to associate with running the report
- """
-
- if not signum and hasattr(signal, 'SIGUSR1'):
- # SIGUSR1 is not supported on all platforms
- signum = signal.SIGUSR1
-
- if signum:
- signal.signal(signum,
- lambda sn, tb: cls.handle_signal(
- version, service_name, log_dir, tb))
-
- @classmethod
- def handle_signal(cls, version, service_name, log_dir, traceback):
- """The Signal Handler
-
- This method (indirectly) handles receiving a registered signal and
- dumping the Guru Meditation Report to stderr or a file in a given dir.
- If service name and log dir are not None, the report will be dumped to
- a file named $service_name_gurumeditation_$current_time in the log_dir
- directory.
- This method is designed to be curried into a proper signal handler by
- currying out the version
- parameter.
-
- :param version: the version object for the current product
- :param service_name: this program name used to construct logfile name
- :param logdir: path to a log directory where to create a file
- :param traceback: the traceback provided to the signal handler
- """
-
- try:
- res = cls(version, traceback).run()
- except Exception:
- print("Unable to run Guru Meditation Report!",
- file=sys.stderr)
- else:
- if log_dir:
- service_name = service_name or os.path.basename(
- inspect.stack()[-1][1])
- filename = "%s_gurumeditation_%s" % (
- service_name, timeutils.utcnow().strftime(
- cls.timestamp_fmt))
- filepath = os.path.join(log_dir, filename)
- try:
- with open(filepath, "w") as dumpfile:
- dumpfile.write(res)
- except Exception:
- print("Unable to dump Guru Meditation Report to file %s" %
- (filepath,), file=sys.stderr)
- else:
- print(res, file=sys.stderr)
-
- def _readd_sections(self):
- del self.sections[self.start_section_index:]
-
- self.add_section('Package',
- pgen.PackageReportGenerator(self.version_obj))
-
- self.add_section('Threads',
- tgen.ThreadReportGenerator(self.traceback))
-
- self.add_section('Green Threads',
- tgen.GreenThreadReportGenerator())
-
- self.add_section('Processes',
- prgen.ProcessReportGenerator())
-
- self.add_section('Configuration',
- cgen.ConfigReportGenerator())
-
- try:
- for section_title, generator in self.persistent_sections:
- self.add_section(section_title, generator)
- except AttributeError:
- pass
-
- def run(self):
- self._readd_sections()
- return super(GuruMeditation, self).run()
-
-
-# GuruMeditation must come first to get the correct MRO
-class TextGuruMeditation(GuruMeditation, report.TextReport):
- """A Text Guru Meditation Report
-
- This report is the basic human-readable Guru Meditation Report
-
- It contains the following sections by default
- (in addition to any registered persistent sections):
-
- - Package Information
-
- - Threads List
-
- - Green Threads List
-
- - Process List
-
- - Configuration Options
-
- :param version_obj: the version object for the current product
- :param traceback: an (optional) frame object providing the actual
- traceback for the current thread
- """
-
- def __init__(self, version_obj, traceback=None):
- super(TextGuruMeditation, self).__init__(version_obj, traceback,
- 'Guru Meditation')
diff --git a/openstack/common/report/models/__init__.py b/openstack/common/report/models/__init__.py
deleted file mode 100644
index 7bfed3d8..00000000
--- a/openstack/common/report/models/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides data models
-
-This module provides both the base data model,
-as well as several predefined specific data models
-to be used in reports.
-"""
diff --git a/openstack/common/report/models/base.py b/openstack/common/report/models/base.py
deleted file mode 100644
index d840c5b5..00000000
--- a/openstack/common/report/models/base.py
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides the base report model
-
-This module defines a class representing the basic report
-data model from which all data models should inherit (or
-at least implement similar functionality). Data models
-store unserialized data generated by generators during
-the report serialization process.
-"""
-
-import collections as col
-import copy
-
-import six
-
-
-class ReportModel(col.MutableMapping):
- """A Report Data Model
-
- A report data model contains data generated by some
- generator method or class. Data may be read or written
- using dictionary-style access, and may be read (but not
- written) using object-member-style access. Additionally,
- a data model may have an associated view. This view is
- used to serialize the model when str() is called on the
- model. An appropriate object for a view is callable with
- a single parameter: the model to be serialized.
-
- If present, the object passed in as data will be transformed
- into a standard python dict. For mappings, this is fairly
- straightforward. For sequences, the indices become keys
- and the items become values.
-
- :param data: a sequence or mapping of data to associate with the model
- :param attached_view: a view object to attach to this model
- """
-
- def __init__(self, data=None, attached_view=None):
- self.attached_view = attached_view
-
- if data is not None:
- if isinstance(data, col.Mapping):
- self.data = dict(data)
- elif isinstance(data, col.Sequence):
- # convert a list [a, b, c] to a dict {0: a, 1: b, 2: c}
- self.data = dict(enumerate(data))
- else:
- raise TypeError('Data for the model must be a sequence '
- 'or mapping.')
- else:
- self.data = {}
-
- def __str__(self):
- self_cpy = copy.deepcopy(self)
- for key in self_cpy:
- if getattr(self_cpy[key], 'attached_view', None) is not None:
- self_cpy[key] = str(self_cpy[key])
-
- if self.attached_view is not None:
- return self.attached_view(self_cpy)
- else:
- raise Exception("Cannot stringify model: no attached view")
-
- def __repr__(self):
- if self.attached_view is not None:
- return ("<Model {cl.__module__}.{cl.__name__} {dt}"
- " with view {vw.__module__}."
- "{vw.__name__}>").format(cl=type(self),
- dt=self.data,
- vw=type(self.attached_view))
- else:
- return ("<Model {cl.__module__}.{cl.__name__} {dt}"
- " with no view>").format(cl=type(self),
- dt=self.data)
-
- def __getitem__(self, attrname):
- return self.data[attrname]
-
- def __setitem__(self, attrname, attrval):
- self.data[attrname] = attrval
-
- def __delitem__(self, attrname):
- del self.data[attrname]
-
- def __contains__(self, key):
- return self.data.__contains__(key)
-
- def __getattr__(self, attrname):
- # Needed for deepcopy in Python3. That will avoid an infinite loop
- # in __getattr__ .
- if 'data' not in self.__dict__:
- self.data = {}
-
- try:
- return self.data[attrname]
- except KeyError:
- # we don't have that key in data, and the
- # model class doesn't have that attribute
- raise AttributeError(
- "'{cl}' object has no attribute '{an}'".format(
- cl=type(self).__name__, an=attrname
- )
- )
-
- def __len__(self):
- return len(self.data)
-
- def __iter__(self):
- return self.data.__iter__()
-
- def set_current_view_type(self, tp, visited=None):
- """Set the current view type
-
- This method attempts to set the current view
- type for this model and all submodels by calling
- itself recursively on all values, traversing
- intervening sequences and mappings when possible,
- and ignoring all other objects.
-
- :param tp: the type of the view ('text', 'json', 'xml', etc)
- :param visited: a set of object ids for which the corresponding objects
- have already had their view type set
- """
-
- if visited is None:
- visited = set()
-
- def traverse_obj(obj):
- oid = id(obj)
-
- # don't die on recursive structures,
- # and don't treat strings like sequences
- if oid in visited or isinstance(obj, six.string_types):
- return
-
- visited.add(oid)
-
- if hasattr(obj, 'set_current_view_type'):
- obj.set_current_view_type(tp, visited=visited)
-
- if isinstance(obj, col.Sequence):
- for item in obj:
- traverse_obj(item)
-
- elif isinstance(obj, col.Mapping):
- for val in six.itervalues(obj):
- traverse_obj(val)
-
- traverse_obj(self)
diff --git a/openstack/common/report/models/conf.py b/openstack/common/report/models/conf.py
deleted file mode 100644
index 23429373..00000000
--- a/openstack/common/report/models/conf.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides OpenStack Configuration Model
-
-This module defines a class representing the data
-model for :mod:`oslo_config` configuration options
-"""
-
-from openstack.common.report.models import with_default_views as mwdv
-from openstack.common.report.views.text import generic as generic_text_views
-
-
-class ConfigModel(mwdv.ModelWithDefaultViews):
- """A Configuration Options Model
-
- This model holds data about a set of configuration options
- from :mod:`oslo_config`. It supports both the default group
- of options and named option groups.
-
- :param conf_obj: a configuration object
- :type conf_obj: :class:`oslo_config.cfg.ConfigOpts`
- """
-
- def __init__(self, conf_obj):
- kv_view = generic_text_views.KeyValueView(dict_sep=": ",
- before_dict='')
- super(ConfigModel, self).__init__(text_view=kv_view)
-
- def opt_title(optname, co):
- return co._opts[optname]['opt'].name
-
- def opt_value(opt_obj, value):
- if opt_obj['opt'].secret:
- return '***'
- else:
- return value
-
- self['default'] = dict(
- (opt_title(optname, conf_obj),
- opt_value(conf_obj._opts[optname], conf_obj[optname]))
- for optname in conf_obj._opts
- )
-
- groups = {}
- for groupname in conf_obj._groups:
- group_obj = conf_obj._groups[groupname]
- curr_group_opts = dict(
- (opt_title(optname, group_obj),
- opt_value(group_obj._opts[optname],
- conf_obj[groupname][optname]))
- for optname in group_obj._opts)
- groups[group_obj.name] = curr_group_opts
-
- self.update(groups)
diff --git a/openstack/common/report/models/process.py b/openstack/common/report/models/process.py
deleted file mode 100644
index d953b942..00000000
--- a/openstack/common/report/models/process.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2014 Red Hat, 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.
-
-"""Provides a process model
-
-This module defines a class representing a process,
-potentially with subprocesses.
-"""
-
-import openstack.common.report.models.with_default_views as mwdv
-import openstack.common.report.views.text.process as text_views
-
-
-class ProcessModel(mwdv.ModelWithDefaultViews):
- """A Process Model
-
- This model holds data about a process,
- including references to any subprocesses
-
- :param process: a :class:`psutil.Process` object
- """
-
- def __init__(self, process):
- super(ProcessModel, self).__init__(
- text_view=text_views.ProcessView())
-
- self['pid'] = process.pid
- self['parent_pid'] = process.ppid
- if hasattr(process, 'uids'):
- self['uids'] = {'real': process.uids.real,
- 'effective': process.uids.effective,
- 'saved': process.uids.saved}
- else:
- self['uids'] = {'real': None,
- 'effective': None,
- 'saved': None}
-
- if hasattr(process, 'gids'):
- self['gids'] = {'real': process.gids.real,
- 'effective': process.gids.effective,
- 'saved': process.gids.saved}
- else:
- self['gids'] = {'real': None,
- 'effective': None,
- 'saved': None}
-
- self['username'] = process.username
- self['command'] = process.cmdline
- self['state'] = process.status
-
- self['children'] = [ProcessModel(pr) for pr in process.get_children()]
diff --git a/openstack/common/report/models/threading.py b/openstack/common/report/models/threading.py
deleted file mode 100644
index a3ffc861..00000000
--- a/openstack/common/report/models/threading.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides threading and stack-trace models
-
-This module defines classes representing thread, green
-thread, and stack trace data models
-"""
-
-import traceback
-
-from openstack.common.report.models import with_default_views as mwdv
-from openstack.common.report.views.text import threading as text_views
-
-
-class StackTraceModel(mwdv.ModelWithDefaultViews):
- """A Stack Trace Model
-
- This model holds data from a python stack trace,
- commonly extracted from running thread information
-
- :param stack_state: the python stack_state object
- """
-
- def __init__(self, stack_state):
- super(StackTraceModel, self).__init__(
- text_view=text_views.StackTraceView())
-
- if (stack_state is not None):
- self['lines'] = [
- {'filename': fn, 'line': ln, 'name': nm, 'code': cd}
- for fn, ln, nm, cd in traceback.extract_stack(stack_state)
- ]
- # FIXME(flepied): under Python3 f_exc_type doesn't exist
- # anymore so we lose information about exceptions
- if getattr(stack_state, 'f_exc_type', None) is not None:
- self['root_exception'] = {
- 'type': stack_state.f_exc_type,
- 'value': stack_state.f_exc_value}
- else:
- self['root_exception'] = None
- else:
- self['lines'] = []
- self['root_exception'] = None
-
-
-class ThreadModel(mwdv.ModelWithDefaultViews):
- """A Thread Model
-
- This model holds data for information about an
- individual thread. It holds both a thread id,
- as well as a stack trace for the thread
-
- .. seealso::
-
- Class :class:`StackTraceModel`
-
- :param int thread_id: the id of the thread
- :param stack: the python stack state for the current thread
- """
-
- # threadId, stack in sys._current_frams().items()
- def __init__(self, thread_id, stack):
- super(ThreadModel, self).__init__(text_view=text_views.ThreadView())
-
- self['thread_id'] = thread_id
- self['stack_trace'] = StackTraceModel(stack)
-
-
-class GreenThreadModel(mwdv.ModelWithDefaultViews):
- """A Green Thread Model
-
- This model holds data for information about an
- individual thread. Unlike the thread model,
- it holds just a stack trace, since green threads
- do not have thread ids.
-
- .. seealso::
-
- Class :class:`StackTraceModel`
-
- :param stack: the python stack state for the green thread
- """
-
- # gr in greenpool.coroutines_running --> gr.gr_frame
- def __init__(self, stack):
- super(GreenThreadModel, self).__init__(
- {'stack_trace': StackTraceModel(stack)},
- text_view=text_views.GreenThreadView())
diff --git a/openstack/common/report/models/version.py b/openstack/common/report/models/version.py
deleted file mode 100644
index 89e73d42..00000000
--- a/openstack/common/report/models/version.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides OpenStack Version Info Model
-
-This module defines a class representing the data
-model for OpenStack package and version information
-"""
-
-from openstack.common.report.models import with_default_views as mwdv
-from openstack.common.report.views.text import generic as generic_text_views
-
-
-class PackageModel(mwdv.ModelWithDefaultViews):
- """A Package Information Model
-
- This model holds information about the current
- package. It contains vendor, product, and version
- information.
-
- :param str vendor: the product vendor
- :param str product: the product name
- :param str version: the product version
- """
-
- def __init__(self, vendor, product, version):
- super(PackageModel, self).__init__(
- text_view=generic_text_views.KeyValueView()
- )
-
- self['vendor'] = vendor
- self['product'] = product
- self['version'] = version
diff --git a/openstack/common/report/models/with_default_views.py b/openstack/common/report/models/with_default_views.py
deleted file mode 100644
index 058fbb21..00000000
--- a/openstack/common/report/models/with_default_views.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-import copy
-
-from openstack.common.report.models import base as base_model
-from openstack.common.report.views.json import generic as jsonviews
-from openstack.common.report.views.text import generic as textviews
-from openstack.common.report.views.xml import generic as xmlviews
-
-
-class ModelWithDefaultViews(base_model.ReportModel):
- """A Model With Default Views of Various Types
-
- A model with default views has several predefined views,
- each associated with a given type. This is often used for
- when a submodel should have an attached view, but the view
- differs depending on the serialization format
-
- Parameters are as the superclass, except for any
- parameters ending in '_view': these parameters
- get stored as default views.
-
- The default 'default views' are
-
- text
- :class:`openstack.common.report.views.text.generic.KeyValueView`
- xml
- :class:`openstack.common.report.views.xml.generic.KeyValueView`
- json
- :class:`openstack.common.report.views.json.generic.KeyValueView`
-
- .. function:: to_type()
-
- ('type' is one of the 'default views' defined for this model)
- Serializes this model using the default view for 'type'
-
- :rtype: str
- :returns: this model serialized as 'type'
- """
-
- def __init__(self, *args, **kwargs):
- self.views = {
- 'text': textviews.KeyValueView(),
- 'json': jsonviews.KeyValueView(),
- 'xml': xmlviews.KeyValueView()
- }
-
- newargs = copy.copy(kwargs)
- for k in kwargs:
- if k.endswith('_view'):
- self.views[k[:-5]] = kwargs[k]
- del newargs[k]
- super(ModelWithDefaultViews, self).__init__(*args, **newargs)
-
- def set_current_view_type(self, tp, visited=None):
- self.attached_view = self.views[tp]
- super(ModelWithDefaultViews, self).set_current_view_type(tp, visited)
-
- def __getattr__(self, attrname):
- if attrname[:3] == 'to_':
- if self.views[attrname[3:]] is not None:
- return lambda: self.views[attrname[3:]](self)
- else:
- raise NotImplementedError((
- "Model {cn.__module__}.{cn.__name__} does not have" +
- " a default view for "
- "{tp}").format(cn=type(self), tp=attrname[3:]))
- else:
- return super(ModelWithDefaultViews, self).__getattr__(attrname)
diff --git a/openstack/common/report/report.py b/openstack/common/report/report.py
deleted file mode 100644
index 1eb937b5..00000000
--- a/openstack/common/report/report.py
+++ /dev/null
@@ -1,187 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides Report classes
-
-This module defines various classes representing reports and report sections.
-All reports take the form of a report class containing various report
-sections.
-"""
-
-from openstack.common.report.views.text import header as header_views
-
-
-class BasicReport(object):
- """A Basic Report
-
- A Basic Report consists of a collection of :class:`ReportSection`
- objects, each of which contains a top-level model and generator.
- It collects these sections into a cohesive report which may then
- be serialized by calling :func:`run`.
- """
-
- def __init__(self):
- self.sections = []
- self._state = 0
-
- def add_section(self, view, generator, index=None):
- """Add a section to the report
-
- This method adds a section with the given view and
- generator to the report. An index may be specified to
- insert the section at a given location in the list;
- If no index is specified, the section is appended to the
- list. The view is called on the model which results from
- the generator when the report is run. A generator is simply
- a method or callable object which takes no arguments and
- returns a :class:`openstack.common.report.models.base.ReportModel`
- or similar object.
-
- :param view: the top-level view for the section
- :param generator: the method or class which generates the model
- :param index: the index at which to insert the section
- (or None to append it)
- :type index: int or None
- """
-
- if index is None:
- self.sections.append(ReportSection(view, generator))
- else:
- self.sections.insert(index, ReportSection(view, generator))
-
- def run(self):
- """Run the report
-
- This method runs the report, having each section generate
- its data and serialize itself before joining the sections
- together. The BasicReport accomplishes the joining
- by joining the serialized sections together with newlines.
-
- :rtype: str
- :returns: the serialized report
- """
-
- return "\n".join(str(sect) for sect in self.sections)
-
-
-class ReportSection(object):
- """A Report Section
-
- A report section contains a generator and a top-level view. When something
- attempts to serialize the section by calling str() on it, the section runs
- the generator and calls the view on the resulting model.
-
- .. seealso::
-
- Class :class:`BasicReport`
- :func:`BasicReport.add_section`
-
- :param view: the top-level view for this section
- :param generator: the generator for this section
- (any callable object which takes no parameters and returns a data model)
- """
-
- def __init__(self, view, generator):
- self.view = view
- self.generator = generator
-
- def __str__(self):
- return self.view(self.generator())
-
-
-class ReportOfType(BasicReport):
- """A Report of a Certain Type
-
- A ReportOfType has a predefined type associated with it.
- This type is automatically propagated down to the each of
- the sections upon serialization by wrapping the generator
- for each section.
-
- .. seealso::
-
- Class :class:`openstack.common.report.models.with_default_view.ModelWithDefaultView` # noqa
- (the entire class)
-
- Class :class:`openstack.common.report.models.base.ReportModel`
- :func:`openstack.common.report.models.base.ReportModel.set_current_view_type` # noqa
-
- :param str tp: the type of the report
- """
-
- def __init__(self, tp):
- self.output_type = tp
- super(ReportOfType, self).__init__()
-
- def add_section(self, view, generator, index=None):
- def with_type(gen):
- def newgen():
- res = gen()
- try:
- res.set_current_view_type(self.output_type)
- except AttributeError:
- pass
-
- return res
- return newgen
-
- super(ReportOfType, self).add_section(
- view,
- with_type(generator),
- index
- )
-
-
-class TextReport(ReportOfType):
- """A Human-Readable Text Report
-
- This class defines a report that is designed to be read by a human
- being. It has nice section headers, and a formatted title.
-
- :param str name: the title of the report
- """
-
- def __init__(self, name):
- super(TextReport, self).__init__('text')
- self.name = name
- # add a title with a generator that creates an empty result model
- self.add_section(name, lambda: ('|' * 72) + "\n\n")
-
- def add_section(self, heading, generator, index=None):
- """Add a section to the report
-
- This method adds a section with the given title, and
- generator to the report. An index may be specified to
- insert the section at a given location in the list;
- If no index is specified, the section is appended to the
- list. The view is called on the model which results from
- the generator when the report is run. A generator is simply
- a method or callable object which takes no arguments and
- returns a :class:`openstack.common.report.models.base.ReportModel`
- or similar object.
-
- The model is told to serialize as text (if possible) at serialization
- time by wrapping the generator. The view model's attached view
- (if any) is wrapped in a
- :class:`openstack.common.report.views.text.header.TitledView`
-
- :param str heading: the title for the section
- :param generator: the method or class which generates the model
- :param index: the index at which to insert the section
- (or None to append)
- :type index: int or None
- """
-
- super(TextReport, self).add_section(header_views.TitledView(heading),
- generator,
- index)
diff --git a/openstack/common/report/utils.py b/openstack/common/report/utils.py
deleted file mode 100644
index fb71e36a..00000000
--- a/openstack/common/report/utils.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Various utilities for report generation
-
-This module includes various utilities
-used in generating reports.
-"""
-
-import gc
-
-
-class StringWithAttrs(str):
- """A String that can have arbitrary attributes
- """
-
- pass
-
-
-def _find_objects(t):
- """Find Objects in the GC State
-
- This horribly hackish method locates objects of a
- given class in the current python instance's garbage
- collection state. In case you couldn't tell, this is
- horribly hackish, but is necessary for locating all
- green threads, since they don't keep track of themselves
- like normal threads do in python.
-
- :param class t: the class of object to locate
- :rtype: list
- :returns: a list of objects of the given type
- """
-
- return [o for o in gc.get_objects() if isinstance(o, t)]
diff --git a/openstack/common/report/views/__init__.py b/openstack/common/report/views/__init__.py
deleted file mode 100644
index 612959b2..00000000
--- a/openstack/common/report/views/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides predefined views
-
-This module provides a collection of predefined views
-for use in reports. It is separated by type (xml, json, or text).
-Each type contains a submodule called 'generic' containing
-several basic, universal views for that type. There is also
-a predefined view that utilizes Jinja.
-"""
diff --git a/openstack/common/report/views/jinja_view.py b/openstack/common/report/views/jinja_view.py
deleted file mode 100644
index 5f57dc34..00000000
--- a/openstack/common/report/views/jinja_view.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides Jinja Views
-
-This module provides views that utilize the Jinja templating
-system for serialization. For more information on Jinja, please
-see http://jinja.pocoo.org/ .
-"""
-
-import copy
-
-import jinja2
-
-
-class JinjaView(object):
- """A Jinja View
-
- This view renders the given model using the provided Jinja
- template. The template can be given in various ways.
- If the `VIEw_TEXT` property is defined, that is used as template.
- Othewise, if a `path` parameter is passed to the constructor, that
- is used to load a file containing the template. If the `path`
- parameter is None, the `text` parameter is used as the template.
-
- The leading newline character and trailing newline character are stripped
- from the template (provided they exist). Baseline indentation is
- also stripped from each line. The baseline indentation is determined by
- checking the indentation of the first line, after stripping off the leading
- newline (if any).
-
- :param str path: the path to the Jinja template
- :param str text: the text of the Jinja template
- """
-
- def __init__(self, path=None, text=None):
- try:
- self._text = self.VIEW_TEXT
- except AttributeError:
- if path is not None:
- with open(path, 'r') as f:
- self._text = f.read()
- elif text is not None:
- self._text = text
- else:
- self._text = ""
-
- if self._text[0] == "\n":
- self._text = self._text[1:]
-
- newtext = self._text.lstrip()
- amt = len(self._text) - len(newtext)
- if (amt > 0):
- base_indent = self._text[0:amt]
- lines = self._text.splitlines()
- newlines = []
- for line in lines:
- if line.startswith(base_indent):
- newlines.append(line[amt:])
- else:
- newlines.append(line)
- self._text = "\n".join(newlines)
-
- if self._text[-1] == "\n":
- self._text = self._text[:-1]
-
- self._regentemplate = True
- self._templatecache = None
-
- def __call__(self, model):
- return self.template.render(**model)
-
- def __deepcopy__(self, memodict):
- res = object.__new__(JinjaView)
- res._text = copy.deepcopy(self._text, memodict)
-
- # regenerate the template on a deepcopy
- res._regentemplate = True
- res._templatecache = None
-
- return res
-
- @property
- def template(self):
- """Get the Compiled Template
-
- Gets the compiled template, using a cached copy if possible
- (stored in attr:`_templatecache`) or otherwise recompiling
- the template if the compiled template is not present or is
- invalid (due to attr:`_regentemplate` being set to True).
-
- :returns: the compiled Jinja template
- :rtype: :class:`jinja2.Template`
- """
-
- if self._templatecache is None or self._regentemplate:
- self._templatecache = jinja2.Template(self._text)
- self._regentemplate = False
-
- return self._templatecache
-
- def _gettext(self):
- """Get the Template Text
-
- Gets the text of the current template
-
- :returns: the text of the Jinja template
- :rtype: str
- """
-
- return self._text
-
- def _settext(self, textval):
- """Set the Template Text
-
- Sets the text of the current template, marking it
- for recompilation next time the compiled template
- is retrived via attr:`template` .
-
- :param str textval: the new text of the Jinja template
- """
-
- self._text = textval
- self.regentemplate = True
-
- text = property(_gettext, _settext)
diff --git a/openstack/common/report/views/json/__init__.py b/openstack/common/report/views/json/__init__.py
deleted file mode 100644
index 47bd33b6..00000000
--- a/openstack/common/report/views/json/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides basic JSON views
-
-This module provides several basic views which serialize
-models into JSON.
-"""
diff --git a/openstack/common/report/views/json/generic.py b/openstack/common/report/views/json/generic.py
deleted file mode 100644
index a8814ea7..00000000
--- a/openstack/common/report/views/json/generic.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides generic JSON views
-
-This modules defines several basic views for serializing
-data to JSON. Submodels that have already been serialized
-as JSON may have their string values marked with `__is_json__
-= True` using :class:`openstack.common.report.utils.StringWithAttrs`
-(each of the classes within this module does this automatically,
-and non-naive serializers check for this attribute and handle
-such strings specially)
-"""
-
-import copy
-
-from oslo_serialization import jsonutils as json
-
-from openstack.common.report import utils as utils
-
-
-class BasicKeyValueView(object):
- """A Basic Key-Value JSON View
-
- This view performs a naive serialization of a model
- into JSON by simply calling :func:`json.dumps` on the model
- """
-
- def __call__(self, model):
- res = utils.StringWithAttrs(json.dumps(model.data))
- res.__is_json__ = True
- return res
-
-
-class KeyValueView(object):
- """A Key-Value JSON View
-
- This view performs advanced serialization to a model
- into JSON. It does so by first checking all values to
- see if they are marked as JSON. If so, they are deserialized
- using :func:`json.loads`. Then, the copy of the model with all
- JSON deserialized is reserialized into proper nested JSON using
- :func:`json.dumps`.
- """
-
- def __call__(self, model):
- # this part deals with subviews that were already serialized
- cpy = copy.deepcopy(model)
- for key in model.keys():
- if getattr(model[key], '__is_json__', False):
- cpy[key] = json.loads(model[key])
-
- res = utils.StringWithAttrs(json.dumps(cpy.data, sort_keys=True))
- res.__is_json__ = True
- return res
diff --git a/openstack/common/report/views/text/__init__.py b/openstack/common/report/views/text/__init__.py
deleted file mode 100644
index c0974844..00000000
--- a/openstack/common/report/views/text/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides basic text views
-
-This module provides several basic views which serialize
-models into human-readable text.
-"""
diff --git a/openstack/common/report/views/text/generic.py b/openstack/common/report/views/text/generic.py
deleted file mode 100644
index 3b30a070..00000000
--- a/openstack/common/report/views/text/generic.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides generic text views
-
-This modules provides several generic views for
-serializing models into human-readable text.
-"""
-
-import collections as col
-
-import six
-
-
-class MultiView(object):
- """A Text View Containing Multiple Views
-
- This view simply serializes each
- value in the data model, and then
- joins them with newlines (ignoring
- the key values altogether). This is
- useful for serializing lists of models
- (as array-like dicts).
- """
-
- def __call__(self, model):
- res = [str(model[key]) for key in model]
- return "\n".join(res)
-
-
-class BasicKeyValueView(object):
- """A Basic Key-Value Text View
-
- This view performs a naive serialization of a model into
- text using a basic key-value method, where each
- key-value pair is rendered as "key = str(value)"
- """
-
- def __call__(self, model):
- res = ""
- for key in model:
- res += "{key} = {value}\n".format(key=key, value=model[key])
-
- return res
-
-
-class KeyValueView(object):
- """A Key-Value Text View
-
- This view performs an advanced serialization of a model
- into text by following the following set of rules:
-
- key : text
- key = text
-
- rootkey : Mapping
- ::
-
- rootkey =
- serialize(key, value)
-
- key : Sequence
- ::
-
- key =
- serialize(item)
-
- :param str indent_str: the string used to represent one "indent"
- :param str key_sep: the separator to use between keys and values
- :param str dict_sep: the separator to use after a dictionary root key
- :param str list_sep: the separator to use after a list root key
- :param str anon_dict: the "key" to use when there is a dict in a list
- (does not automatically use the dict separator)
- :param before_dict: content to place on the line(s) before the a dict
- root key (use None to avoid inserting an extra line)
- :type before_dict: str or None
- :param before_list: content to place on the line(s) before the a list
- root key (use None to avoid inserting an extra line)
- :type before_list: str or None
- """
-
- def __init__(self,
- indent_str=' ',
- key_sep=' = ',
- dict_sep=' = ',
- list_sep=' = ',
- anon_dict='[dict]',
- before_dict=None,
- before_list=None):
- self.indent_str = indent_str
- self.key_sep = key_sep
- self.dict_sep = dict_sep
- self.list_sep = list_sep
- self.anon_dict = anon_dict
- self.before_dict = before_dict
- self.before_list = before_list
-
- def __call__(self, model):
- def serialize(root, rootkey, indent):
- res = []
- if rootkey is not None:
- res.append((self.indent_str * indent) + rootkey)
-
- if isinstance(root, col.Mapping):
- if rootkey is None and indent > 0:
- res.append((self.indent_str * indent) + self.anon_dict)
- elif rootkey is not None:
- res[0] += self.dict_sep
- if self.before_dict is not None:
- res.insert(0, self.before_dict)
-
- for key in sorted(root):
- res.extend(serialize(root[key], key, indent + 1))
- elif (isinstance(root, col.Sequence) and
- not isinstance(root, six.string_types)):
- if rootkey is not None:
- res[0] += self.list_sep
- if self.before_list is not None:
- res.insert(0, self.before_list)
-
- for val in sorted(root, key=str):
- res.extend(serialize(val, None, indent + 1))
- else:
- str_root = str(root)
- if '\n' in str_root:
- # we are in a submodel
- if rootkey is not None:
- res[0] += self.dict_sep
-
- list_root = [(self.indent_str * (indent + 1)) + line
- for line in str_root.split('\n')]
- res.extend(list_root)
- else:
- # just a normal key or list entry
- try:
- res[0] += self.key_sep + str_root
- except IndexError:
- res = [(self.indent_str * indent) + str_root]
-
- return res
-
- return "\n".join(serialize(model, None, -1))
-
-
-class TableView(object):
- """A Basic Table Text View
-
- This view performs serialization of data into a basic table with
- predefined column names and mappings. Column width is auto-calculated
- evenly, column values are automatically truncated accordingly. Values
- are centered in the columns.
-
- :param [str] column_names: the headers for each of the columns
- :param [str] column_values: the item name to match each column to in
- each row
- :param str table_prop_name: the name of the property within the model
- containing the row models
- """
-
- def __init__(self, column_names, column_values, table_prop_name):
- self.table_prop_name = table_prop_name
- self.column_names = column_names
- self.column_values = column_values
- self.column_width = (72 - len(column_names) + 1) // len(column_names)
-
- column_headers = "|".join(
- "{ch[" + str(n) + "]: ^" + str(self.column_width) + "}"
- for n in range(len(column_names))
- )
-
- # correct for float-to-int roundoff error
- test_fmt = column_headers.format(ch=column_names)
- if len(test_fmt) < 72:
- column_headers += ' ' * (72 - len(test_fmt))
-
- vert_divider = '-' * 72
- self.header_fmt_str = column_headers + "\n" + vert_divider + "\n"
-
- self.row_fmt_str = "|".join(
- "{cv[" + str(n) + "]: ^" + str(self.column_width) + "}"
- for n in range(len(column_values))
- )
-
- def __call__(self, model):
- res = self.header_fmt_str.format(ch=self.column_names)
- for raw_row in model[self.table_prop_name]:
- row = [str(raw_row[prop_name]) for prop_name in self.column_values]
- # double format is in case we have roundoff error
- res += '{0: <72}\n'.format(self.row_fmt_str.format(cv=row))
-
- return res
diff --git a/openstack/common/report/views/text/header.py b/openstack/common/report/views/text/header.py
deleted file mode 100644
index 58d06c0d..00000000
--- a/openstack/common/report/views/text/header.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Text Views With Headers
-
-This package defines several text views with headers
-"""
-
-
-class HeaderView(object):
- """A Text View With a Header
-
- This view simply serializes the model and places the given
- header on top.
-
- :param header: the header (can be anything on which str() can be called)
- """
-
- def __init__(self, header):
- self.header = header
-
- def __call__(self, model):
- return str(self.header) + "\n" + str(model)
-
-
-class TitledView(HeaderView):
- """A Text View With a Title
-
- This view simply serializes the model, and places
- a preformatted header containing the given title
- text on top. The title text can be up to 64 characters
- long.
-
- :param str title: the title of the view
- """
-
- FORMAT_STR = ('=' * 72) + "\n===={0: ^64}====\n" + ('=' * 72)
-
- def __init__(self, title):
- super(TitledView, self).__init__(self.FORMAT_STR.format(title))
diff --git a/openstack/common/report/views/text/process.py b/openstack/common/report/views/text/process.py
deleted file mode 100644
index edd2be7c..00000000
--- a/openstack/common/report/views/text/process.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2014 Red Hat, 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.
-
-"""Provides process view
-
-This module provides a view for
-visualizing processes in human-readable formm
-"""
-
-import openstack.common.report.views.jinja_view as jv
-
-
-class ProcessView(jv.JinjaView):
- """A Process View
-
- This view displays process models defined by
- :class:`openstack.common.report.models.process.ProcessModel`
- """
-
- VIEW_TEXT = (
- "Process {{ pid }} (under {{ parent_pid }}) "
- "[ run by: {{ username }} ({{ uids.real|default('unknown uid') }}),"
- " state: {{ state }} ]\n"
- "{% for child in children %}"
- " {{ child }}"
- "{% endfor %}"
- )
diff --git a/openstack/common/report/views/text/threading.py b/openstack/common/report/views/text/threading.py
deleted file mode 100644
index f8b208d2..00000000
--- a/openstack/common/report/views/text/threading.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides thread and stack-trace views
-
-This module provides a collection of views for
-visualizing threads, green threads, and stack traces
-in human-readable form.
-"""
-
-from openstack.common.report.views import jinja_view as jv
-
-
-class StackTraceView(jv.JinjaView):
- """A Stack Trace View
-
- This view displays stack trace models defined by
- :class:`openstack.common.report.models.threading.StackTraceModel`
- """
-
- VIEW_TEXT = (
- "{% if root_exception is not none %}"
- "Exception: {{ root_exception }}\n"
- "------------------------------------\n"
- "\n"
- "{% endif %}"
- "{% for line in lines %}\n"
- "{{ line.filename }}:{{ line.line }} in {{ line.name }}\n"
- " {% if line.code is not none %}"
- "`{{ line.code }}`"
- "{% else %}"
- "(source not found)"
- "{% endif %}\n"
- "{% else %}\n"
- "No Traceback!\n"
- "{% endfor %}"
- )
-
-
-class GreenThreadView(object):
- """A Green Thread View
-
- This view displays a green thread provided by the data
- model :class:`openstack.common.report.models.threading.GreenThreadModel`
- """
-
- FORMAT_STR = "------{thread_str: ^60}------" + "\n" + "{stack_trace}"
-
- def __call__(self, model):
- return self.FORMAT_STR.format(
- thread_str=" Green Thread ",
- stack_trace=model.stack_trace
- )
-
-
-class ThreadView(object):
- """A Thread Collection View
-
- This view displays a python thread provided by the data
- model :class:`openstack.common.report.models.threading.ThreadModel` # noqa
- """
-
- FORMAT_STR = "------{thread_str: ^60}------" + "\n" + "{stack_trace}"
-
- def __call__(self, model):
- return self.FORMAT_STR.format(
- thread_str=" Thread #{0} ".format(model.thread_id),
- stack_trace=model.stack_trace
- )
diff --git a/openstack/common/report/views/xml/__init__.py b/openstack/common/report/views/xml/__init__.py
deleted file mode 100644
index a40fec98..00000000
--- a/openstack/common/report/views/xml/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides basic XML views
-
-This module provides several basic views which serialize
-models into XML.
-"""
diff --git a/openstack/common/report/views/xml/generic.py b/openstack/common/report/views/xml/generic.py
deleted file mode 100644
index 13b6a0ab..00000000
--- a/openstack/common/report/views/xml/generic.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-"""Provides generic XML views
-
-This modules defines several basic views for serializing
-data to XML. Submodels that have already been serialized
-as XML may have their string values marked with `__is_xml__
-= True` using :class:`openstack.common.report.utils.StringWithAttrs`
-(each of the classes within this module does this automatically,
-and non-naive serializers check for this attribute and handle
-such strings specially)
-"""
-
-import collections as col
-import copy
-import xml.etree.ElementTree as ET
-
-import six
-
-from openstack.common.report import utils as utils
-
-
-class KeyValueView(object):
- """A Key-Value XML View
-
- This view performs advanced serialization of a data model
- into XML. It first deserializes any values marked as XML so
- that they can be properly reserialized later. It then follows
- the following rules to perform serialization:
-
- key : text/xml
- The tag name is the key name, and the contents are the text or xml
- key : Sequence
- A wrapper tag is created with the key name, and each item is placed
- in an 'item' tag
- key : Mapping
- A wrapper tag is created with the key name, and the serialize is called
- on each key-value pair (such that each key gets its own tag)
-
- :param str wrapper_name: the name of the top-level element
- """
-
- def __init__(self, wrapper_name="model"):
- self.wrapper_name = wrapper_name
-
- def __call__(self, model):
- # this part deals with subviews that were already serialized
- cpy = copy.deepcopy(model)
- for key, valstr in model.items():
- if getattr(valstr, '__is_xml__', False):
- cpy[key] = ET.fromstring(valstr)
-
- def serialize(rootmodel, rootkeyname):
- res = ET.Element(rootkeyname)
-
- if isinstance(rootmodel, col.Mapping):
- for key in sorted(rootmodel):
- res.append(serialize(rootmodel[key], key))
- elif (isinstance(rootmodel, col.Sequence)
- and not isinstance(rootmodel, six.string_types)):
- for val in sorted(rootmodel, key=str):
- res.append(serialize(val, 'item'))
- elif ET.iselement(rootmodel):
- res.append(rootmodel)
- else:
- res.text = str(rootmodel)
-
- return res
-
- str_ = ET.tostring(serialize(cpy,
- self.wrapper_name),
- encoding="utf-8").decode("utf-8")
- res = utils.StringWithAttrs(str_)
- res.__is_xml__ = True
- return res
diff --git a/tests/unit/reports/__init__.py b/tests/unit/reports/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/unit/reports/__init__.py
+++ /dev/null
diff --git a/tests/unit/reports/test_base_report.py b/tests/unit/reports/test_base_report.py
deleted file mode 100644
index db655fce..00000000
--- a/tests/unit/reports/test_base_report.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-import collections as col
-import re
-
-from oslotest import base
-
-from openstack.common.report.models import base as base_model
-from openstack.common.report import report
-
-
-class BasicView(object):
- def __call__(self, model):
- res = ""
- for k in sorted(model.keys()):
- res += str(k) + ": " + str(model[k]) + ";"
- return res
-
-
-def basic_generator():
- return base_model.ReportModel(data={'string': 'value', 'int': 1})
-
-
-class TestBasicReport(base.BaseTestCase):
- def setUp(self):
- super(TestBasicReport, self).setUp()
-
- self.report = report.BasicReport()
-
- def test_add_section(self):
- self.report.add_section(BasicView(), basic_generator)
- self.assertEqual(len(self.report.sections), 1)
-
- def test_append_section(self):
- self.report.add_section(BasicView(), lambda: {'a': 1})
- self.report.add_section(BasicView(), basic_generator)
-
- self.assertEqual(len(self.report.sections), 2)
- self.assertEqual(self.report.sections[1].generator, basic_generator)
-
- def test_insert_section(self):
- self.report.add_section(BasicView(), lambda: {'a': 1})
- self.report.add_section(BasicView(), basic_generator, 0)
-
- self.assertEqual(len(self.report.sections), 2)
- self.assertEqual(self.report.sections[0].generator, basic_generator)
-
- def test_basic_render(self):
- self.report.add_section(BasicView(), basic_generator)
- self.assertEqual(self.report.run(), "int: 1;string: value;")
-
-
-class TestBaseModel(base.BaseTestCase):
- def test_submodel_attached_view(self):
- class TmpView(object):
- def __call__(self, model):
- return '{len: ' + str(len(model.c)) + '}'
-
- def generate_model_with_submodel():
- base_m = basic_generator()
- tv = TmpView()
- base_m['submodel'] = base_model.ReportModel(data={'c': [1, 2, 3]},
- attached_view=tv)
- return base_m
-
- self.assertEqual(BasicView()(generate_model_with_submodel()),
- 'int: 1;string: value;submodel: {len: 3};')
-
- def test_str_throws_error_with_no_attached_view(self):
- model = base_model.ReportModel(data={'c': [1, 2, 3]})
-
- # ugly code for python 2.6 compat, since python 2.6
- # does not have assertRaisesRegexp
- try:
- str(model)
- except Exception as e:
- err_str = 'Cannot stringify model: no attached view'
- self.assertEqual(str(e), err_str)
- else:
- self.assertTrue(False)
-
- def test_str_returns_string_with_attached_view(self):
- model = base_model.ReportModel(data={'a': 1, 'b': 2},
- attached_view=BasicView())
-
- self.assertEqual(str(model), 'a: 1;b: 2;')
-
- def test_model_repr(self):
- model1 = base_model.ReportModel(data={'a': 1, 'b': 2},
- attached_view=BasicView())
-
- model2 = base_model.ReportModel(data={'a': 1, 'b': 2})
-
- base_re = r"<Model [^ ]+\.[^ ]+ \{.+\} with "
- with_view_re = base_re + r"view [^ ]+\.[^ ]+>"
- without_view_re = base_re + r"no view>"
-
- self.assertTrue(re.match(with_view_re, repr(model1)))
- self.assertTrue(re.match(without_view_re, repr(model2)))
-
- def test_getattr(self):
- model = base_model.ReportModel(data={'a': 1})
-
- self.assertEqual(model.a, 1)
-
- self.assertRaises(AttributeError, getattr, model, 'b')
-
- def test_data_as_sequence_is_handled_properly(self):
- model = base_model.ReportModel(data=['a', 'b'])
- model.attached_view = BasicView()
-
- # if we don't handle lists properly, we'll get a TypeError here
- self.assertEqual('0: a;1: b;', str(model))
-
- def test_immutable_mappings_produce_mutable_models(self):
- class SomeImmutableMapping(col.Mapping):
- def __init__(self):
- self.data = {'a': 2, 'b': 4, 'c': 8}
-
- def __getitem__(self, key):
- return self.data[key]
-
- def __len__(self):
- return len(self.data)
-
- def __iter__(self):
- return iter(self.data)
-
- mp = SomeImmutableMapping()
- model = base_model.ReportModel(data=mp)
- model.attached_view = BasicView()
-
- self.assertEqual('a: 2;b: 4;c: 8;', str(model))
-
- model['d'] = 16
-
- self.assertEqual('a: 2;b: 4;c: 8;d: 16;', str(model))
- self.assertEqual({'a': 2, 'b': 4, 'c': 8}, mp.data)
diff --git a/tests/unit/reports/test_guru_meditation_report.py b/tests/unit/reports/test_guru_meditation_report.py
deleted file mode 100644
index 68e8ea57..00000000
--- a/tests/unit/reports/test_guru_meditation_report.py
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright 2013 Red Hat, 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 __future__ import print_function
-
-import datetime
-import os
-import re
-import signal
-import sys
-
-# needed to get greenthreads
-import fixtures
-import greenlet
-import mock
-from oslotest import base
-import six
-
-from openstack.common.report import guru_meditation_report as gmr
-from openstack.common.report.models import with_default_views as mwdv
-
-
-class FakeVersionObj(object):
- def vendor_string(self):
- return 'Cheese Shoppe'
-
- def product_string(self):
- return 'Sharp Cheddar'
-
- def version_string_with_package(self):
- return '1.0.0'
-
-
-def skip_body_lines(start_line, report_lines):
- curr_line = start_line
- while (len(report_lines[curr_line]) == 0
- or report_lines[curr_line][0] != '='):
- curr_line += 1
-
- return curr_line
-
-
-class TestGuruMeditationReport(base.BaseTestCase):
- def setUp(self):
- super(TestGuruMeditationReport, self).setUp()
-
- self.curr_g = greenlet.getcurrent()
-
- self.report = gmr.TextGuruMeditation(FakeVersionObj())
-
- self.old_stderr = None
-
- def test_basic_report(self):
- report_lines = self.report.run().split('\n')
-
- target_str_header = ['========================================================================', # noqa
- '==== Guru Meditation ====', # noqa
- '========================================================================', # noqa
- '||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||', # noqa
- '',
- '',
- '========================================================================', # noqa
- '==== Package ====', # noqa
- '========================================================================', # noqa
- 'product = Sharp Cheddar',
- 'vendor = Cheese Shoppe',
- 'version = 1.0.0',
- '========================================================================', # noqa
- '==== Threads ====', # noqa
- '========================================================================'] # noqa
-
- # first the header and version info...
- self.assertEqual(target_str_header,
- report_lines[0:len(target_str_header)])
-
- # followed by at least one thread...
- # NOTE(zqfan): add an optional '-' because sys._current_frames()
- # may return a negative thread id on 32 bit operating system.
- self.assertTrue(re.match(r'------(\s+)Thread #-?\d+\1\s?------',
- report_lines[len(target_str_header)]))
- self.assertEqual('', report_lines[len(target_str_header) + 1])
-
- # followed by more thread stuff stuff...
- curr_line = skip_body_lines(len(target_str_header) + 2, report_lines)
-
- # followed by at least one green thread
- target_str_gt = ['========================================================================', # noqa
- '==== Green Threads ====', # noqa
- '========================================================================', # noqa
- '------ Green Thread ------', # noqa
- '']
- end_bound = curr_line + len(target_str_gt)
- self.assertEqual(target_str_gt,
- report_lines[curr_line:end_bound])
-
- # followed by some more green thread stuff
- curr_line = skip_body_lines(curr_line + len(target_str_gt),
- report_lines)
-
- # followed by the processes header
- target_str_p_head = ['========================================================================', # noqa
- '==== Processes ====', # noqa
- '========================================================================'] # noqa
- end_bound = curr_line + len(target_str_p_head)
- self.assertEqual(target_str_p_head,
- report_lines[curr_line:end_bound])
-
- curr_line += len(target_str_p_head)
-
- # followed by at least one process
- self.assertTrue(re.match("Process \d+ \(under \d+\)",
- report_lines[curr_line]))
-
- # followed by some more process stuff
- curr_line = skip_body_lines(curr_line + 1, report_lines)
-
- # followed finally by the configuration
- target_str_config = ['========================================================================', # noqa
- '==== Configuration ====', # noqa
- '========================================================================', # noqa
- '']
- end_bound = curr_line + len(target_str_config)
- self.assertEqual(target_str_config,
- report_lines[curr_line:end_bound])
-
- def test_reg_persistent_section(self):
- def fake_gen():
- fake_data = {'cheddar': ['sharp', 'mild'],
- 'swiss': ['with holes', 'with lots of holes'],
- 'american': ['orange', 'yellow']}
-
- return mwdv.ModelWithDefaultViews(data=fake_data)
-
- gmr.TextGuruMeditation.register_section('Cheese Types', fake_gen)
-
- report_lines = self.report.run()
- target_lst = ['========================================================================', # noqa
- '==== Cheese Types ====', # noqa
- '========================================================================', # noqa
- 'american = ',
- ' orange',
- ' yellow',
- 'cheddar = ',
- ' mild',
- ' sharp',
- 'swiss = ',
- ' with holes',
- ' with lots of holes']
- target_str = '\n'.join(target_lst)
- self.assertIn(target_str, report_lines)
-
- def test_register_autorun(self):
- gmr.TextGuruMeditation.setup_autorun(FakeVersionObj())
- self.old_stderr = sys.stderr
- sys.stderr = six.StringIO()
-
- os.kill(os.getpid(), signal.SIGUSR1)
- self.assertIn('Guru Meditation', sys.stderr.getvalue())
-
- @mock.patch('oslo_utils.timeutils.utcnow',
- return_value=datetime.datetime(2014, 1, 1, 12, 0, 0))
- def test_register_autorun_log_dir(self, mock_strtime):
- log_dir = self.useFixture(fixtures.TempDir()).path
- gmr.TextGuruMeditation.setup_autorun(
- FakeVersionObj(), "fake-service", log_dir)
-
- os.kill(os.getpid(), signal.SIGUSR1)
- with open(os.path.join(
- log_dir, "fake-service_gurumeditation_20140101120000")) as df:
- self.assertIn('Guru Meditation', df.read())
-
- def tearDown(self):
- super(TestGuruMeditationReport, self).tearDown()
- if self.old_stderr is not None:
- sys.stderr = self.old_stderr
diff --git a/tests/unit/reports/test_openstack_generators.py b/tests/unit/reports/test_openstack_generators.py
deleted file mode 100644
index 7b98c2e1..00000000
--- a/tests/unit/reports/test_openstack_generators.py
+++ /dev/null
@@ -1,140 +0,0 @@
-# Copyright 2011 OpenStack Foundation.
-# 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.
-
-import threading
-
-import greenlet
-import mock
-from oslo_config import cfg
-from oslotest import base
-
-from openstack.common.report.generators import conf as os_cgen
-from openstack.common.report.generators import threading as os_tgen
-from openstack.common.report.generators import version as os_pgen
-from openstack.common.report.models import threading as os_tmod
-
-
-class TestOpenstackGenerators(base.BaseTestCase):
- def test_thread_generator(self):
- model = os_tgen.ThreadReportGenerator()()
- # self.assertGreaterEqual(len(model.keys()), 1)
- self.assertTrue(len(model.keys()) >= 1)
- was_ok = False
- for val in model.values():
- self.assertIsInstance(val, os_tmod.ThreadModel)
- self.assertIsNotNone(val.stack_trace)
- if val.thread_id == threading.current_thread().ident:
- was_ok = True
- break
-
- self.assertTrue(was_ok)
-
- model.set_current_view_type('text')
- self.assertIsNotNone(str(model))
-
- def test_thread_generator_tb(self):
- class FakeModel(object):
- def __init__(self, thread_id, tb):
- self.traceback = tb
-
- with mock.patch('openstack.common.report.models'
- '.threading.ThreadModel', FakeModel):
- model = os_tgen.ThreadReportGenerator("fake traceback")()
- curr_thread = model.get(threading.current_thread().ident, None)
- self.assertIsNotNone(curr_thread, None)
- self.assertEqual("fake traceback", curr_thread.traceback)
-
- def test_green_thread_generator(self):
- curr_g = greenlet.getcurrent()
-
- model = os_tgen.GreenThreadReportGenerator()()
-
- # self.assertGreaterEqual(len(model.keys()), 1)
- self.assertTrue(len(model.keys()) >= 1)
-
- was_ok = False
- for tm in model.values():
- if tm.stack_trace == os_tmod.StackTraceModel(curr_g.gr_frame):
- was_ok = True
- break
- self.assertTrue(was_ok)
-
- model.set_current_view_type('text')
- self.assertIsNotNone(str(model))
-
- def test_config_model(self):
- conf = cfg.ConfigOpts()
- conf.register_opt(cfg.StrOpt('crackers', default='triscuit'))
- conf.register_opt(cfg.StrOpt('secrets', secret=True,
- default='should not show'))
- conf.register_group(cfg.OptGroup('cheese', title='Cheese Info'))
- conf.register_opt(cfg.IntOpt('sharpness', default=1),
- group='cheese')
- conf.register_opt(cfg.StrOpt('name', default='cheddar'),
- group='cheese')
- conf.register_opt(cfg.BoolOpt('from_cow', default=True),
- group='cheese')
- conf.register_opt(cfg.StrOpt('group_secrets', secret=True,
- default='should not show'),
- group='cheese')
-
- model = os_cgen.ConfigReportGenerator(conf)()
- model.set_current_view_type('text')
-
- target_str = ('\ncheese: \n'
- ' from_cow = True\n'
- ' group_secrets = ***\n'
- ' name = cheddar\n'
- ' sharpness = 1\n'
- '\n'
- 'default: \n'
- ' crackers = triscuit\n'
- ' secrets = ***')
- self.assertEqual(target_str, str(model))
-
- def test_package_report_generator(self):
- class VersionObj(object):
- def vendor_string(self):
- return 'Cheese Shoppe'
-
- def product_string(self):
- return 'Sharp Cheddar'
-
- def version_string_with_package(self):
- return '1.0.0'
-
- model = os_pgen.PackageReportGenerator(VersionObj())()
- model.set_current_view_type('text')
-
- target_str = ('product = Sharp Cheddar\n'
- 'vendor = Cheese Shoppe\n'
- 'version = 1.0.0')
- self.assertEqual(target_str, str(model))
-
- def test_package_report_generator_without_vendor_string(self):
- class VersionObj(object):
- def product_string(self):
- return 'Sharp Cheddar'
-
- def version_string_with_package(self):
- return '1.0.0'
-
- model = os_pgen.PackageReportGenerator(VersionObj())()
- model.set_current_view_type('text')
-
- target_str = ('product = Sharp Cheddar\n'
- 'vendor = None\n'
- 'version = 1.0.0')
- self.assertEqual(target_str, str(model))
diff --git a/tests/unit/reports/test_views.py b/tests/unit/reports/test_views.py
deleted file mode 100644
index fdc4fe35..00000000
--- a/tests/unit/reports/test_views.py
+++ /dev/null
@@ -1,420 +0,0 @@
-# Copyright 2013 Red Hat, 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.
-
-import copy
-
-import mock
-from oslotest import base
-
-from openstack.common.report.models import base as base_model
-from openstack.common.report.models import with_default_views as mwdv
-from openstack.common.report import report
-from openstack.common.report.views import jinja_view as jv
-from openstack.common.report.views.json import generic as json_generic
-from openstack.common.report.views.text import generic as text_generic
-
-
-def mwdv_generator():
- return mwdv.ModelWithDefaultViews(data={'string': 'value', 'int': 1})
-
-
-class TestModelReportType(base.BaseTestCase):
- def test_model_with_default_views(self):
- model = mwdv_generator()
-
- model.set_current_view_type('text')
- self.assertEqual('int = 1\nstring = value', str(model))
-
- model.set_current_view_type('json')
- self.assertEqual('{"int": 1, "string": "value"}', str(model))
-
- model.set_current_view_type('xml')
-
- self.assertEqual('<model><int>1</int><string>value</string></model>',
- str(model))
-
- def test_recursive_type_propagation_with_nested_models(self):
- model = mwdv_generator()
- model['submodel'] = mwdv_generator()
-
- model.set_current_view_type('json')
-
- self.assertEqual(model.submodel.views['json'],
- model.submodel.attached_view)
-
- def test_recursive_type_propagation_with_nested_dicts(self):
- nested_model = mwdv.ModelWithDefaultViews(json_view='abc')
- data = {'a': 1, 'b': {'c': nested_model}}
- top_model = base_model.ReportModel(data=data)
-
- top_model.set_current_view_type('json')
- self.assertEqual(nested_model.attached_view,
- nested_model.views['json'])
-
- def test_recursive_type_propagation_with_nested_lists(self):
- nested_model = mwdv_generator()
- data = {'a': 1, 'b': [nested_model]}
- top_model = base_model.ReportModel(data=data)
-
- top_model.set_current_view_type('json')
- self.assertEqual(nested_model.attached_view,
- nested_model.views['json'])
-
- def test_recursive_type_propogation_on_recursive_structures(self):
- nested_model = mwdv_generator()
- data = {'a': 1, 'b': [nested_model]}
- nested_model['c'] = data
- top_model = base_model.ReportModel(data=data)
-
- top_model.set_current_view_type('json')
- self.assertEqual(nested_model.attached_view,
- nested_model.views['json'])
- del nested_model['c']
-
- def test_report_of_type(self):
- rep = report.ReportOfType('json')
- rep.add_section(lambda x: str(x), mwdv_generator)
-
- self.assertEqual('{"int": 1, "string": "value"}', rep.run())
-
- # NOTE: this also tests views.text.header
- def test_text_report(self):
- rep = report.TextReport('Test Report')
- rep.add_section('An Important Section', mwdv_generator)
- rep.add_section('Another Important Section', mwdv_generator)
-
- target_str = ('========================================================================\n' # noqa
- '==== Test Report ====\n' # noqa
- '========================================================================\n' # noqa
- '||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n' # noqa
- '\n' # noqa
- '\n' # noqa
- '========================================================================\n' # noqa
- '==== An Important Section ====\n' # noqa
- '========================================================================\n' # noqa
- 'int = 1\n' # noqa
- 'string = value\n' # noqa
- '========================================================================\n' # noqa
- '==== Another Important Section ====\n' # noqa
- '========================================================================\n' # noqa
- 'int = 1\n' # noqa
- 'string = value') # noqa
- self.assertEqual(target_str, rep.run())
-
- def test_to_type(self):
- model = mwdv_generator()
-
- self.assertEqual('<model><int>1</int><string>value</string></model>',
- model.to_xml())
-
-
-class TestGenericXMLView(base.BaseTestCase):
- def setUp(self):
- super(TestGenericXMLView, self).setUp()
-
- self.model = mwdv_generator()
- self.model.set_current_view_type('xml')
-
- def test_dict_serialization(self):
- self.model['dt'] = {'a': 1, 'b': 2}
-
- target_str = ('<model>'
- '<dt><a>1</a><b>2</b></dt>'
- '<int>1</int>'
- '<string>value</string></model>')
- self.assertEqual(target_str, str(self.model))
-
- def test_list_serialization(self):
- self.model['lt'] = ['a', 'b']
-
- target_str = ('<model>'
- '<int>1</int>'
- '<lt><item>a</item><item>b</item></lt>'
- '<string>value</string></model>')
- self.assertEqual(target_str, str(self.model))
-
- def test_list_in_dict_serialization(self):
- self.model['dt'] = {'a': 1, 'b': [2, 3]}
-
- target_str = ('<model>'
- '<dt><a>1</a>'
- '<b><item>2</item><item>3</item></b></dt>'
- '<int>1</int>'
- '<string>value</string></model>')
- self.assertEqual(target_str, str(self.model))
-
- def test_dict_in_list_serialization(self):
- self.model['lt'] = [1, {'b': 2, 'c': 3}]
-
- target_str = ('<model>'
- '<int>1</int>'
- '<lt><item>1</item>'
- '<item><b>2</b><c>3</c></item></lt>'
- '<string>value</string></model>')
- self.assertEqual(target_str, str(self.model))
-
- def test_submodel_serialization(self):
- sm = mwdv_generator()
- sm.set_current_view_type('xml')
-
- self.model['submodel'] = sm
-
- target_str = ('<model>'
- '<int>1</int>'
- '<string>value</string>'
- '<submodel>'
- '<model><int>1</int><string>value</string></model>'
- '</submodel>'
- '</model>')
- self.assertEqual(target_str, str(self.model))
-
- def test_wrapper_name(self):
- self.model.attached_view.wrapper_name = 'cheese'
-
- target_str = ('<cheese>'
- '<int>1</int>'
- '<string>value</string>'
- '</cheese>')
- self.assertEqual(target_str, str(self.model))
-
-
-class TestGenericJSONViews(base.BaseTestCase):
- def setUp(self):
- super(TestGenericJSONViews, self).setUp()
-
- self.model = mwdv_generator()
- self.model.set_current_view_type('json')
-
- def test_basic_kv_view(self):
- attached_view = json_generic.BasicKeyValueView()
- self.model = base_model.ReportModel(data={'string': 'value', 'int': 1},
- attached_view=attached_view)
-
- self.assertEqual('{"int": 1, "string": "value"}', str(self.model))
-
- def test_dict_serialization(self):
- self.model['dt'] = {'a': 1, 'b': 2}
-
- target_str = ('{'
- '"dt": {"a": 1, "b": 2}, '
- '"int": 1, '
- '"string": "value"'
- '}')
- self.assertEqual(target_str, str(self.model))
-
- def test_list_serialization(self):
- self.model['lt'] = ['a', 'b']
-
- target_str = ('{'
- '"int": 1, '
- '"lt": ["a", "b"], '
- '"string": "value"'
- '}')
- self.assertEqual(target_str, str(self.model))
-
- def test_list_in_dict_serialization(self):
- self.model['dt'] = {'a': 1, 'b': [2, 3]}
-
- target_str = ('{'
- '"dt": {"a": 1, "b": [2, 3]}, '
- '"int": 1, '
- '"string": "value"'
- '}')
- self.assertEqual(target_str, str(self.model))
-
- def test_dict_in_list_serialization(self):
- self.model['lt'] = [1, {'b': 2, 'c': 3}]
-
- target_str = ('{'
- '"int": 1, '
- '"lt": [1, {"b": 2, "c": 3}], '
- '"string": "value"'
- '}')
- self.assertEqual(target_str, str(self.model))
-
- def test_submodel_serialization(self):
- sm = mwdv_generator()
- sm.set_current_view_type('json')
-
- self.model['submodel'] = sm
-
- target_str = ('{'
- '"int": 1, '
- '"string": "value", '
- '"submodel": {"int": 1, "string": "value"}'
- '}')
- self.assertEqual(target_str, str(self.model))
-
-
-class TestGenericTextViews(base.BaseTestCase):
- def setUp(self):
- super(TestGenericTextViews, self).setUp()
-
- self.model = mwdv_generator()
- self.model.set_current_view_type('text')
-
- def test_multi_view(self):
- attached_view = text_generic.MultiView()
- self.model = base_model.ReportModel(data={},
- attached_view=attached_view)
-
- self.model['1'] = mwdv_generator()
- self.model['2'] = mwdv_generator()
- self.model['2']['int'] = 2
- self.model.set_current_view_type('text')
-
- target_str = ('int = 1\n'
- 'string = value\n'
- 'int = 2\n'
- 'string = value')
- self.assertEqual(target_str, str(self.model))
-
- def test_basic_kv_view(self):
- attached_view = text_generic.BasicKeyValueView()
- self.model = base_model.ReportModel(data={'string': 'value', 'int': 1},
- attached_view=attached_view)
-
- self.assertEqual('int = 1\nstring = value\n', str(self.model))
-
- def test_table_view(self):
- column_names = ['Column A', 'Column B']
- column_values = ['a', 'b']
- attached_view = text_generic.TableView(column_names, column_values,
- 'table')
- self.model = base_model.ReportModel(data={},
- attached_view=attached_view)
-
- self.model['table'] = [{'a': 1, 'b': 2}, {'a': 3, 'b': 4}]
-
- target_str = (' Column A | Column B \n' # noqa
- '------------------------------------------------------------------------\n' # noqa
- ' 1 | 2 \n' # noqa
- ' 3 | 4 \n') # noqa
-
- self.assertEqual(target_str, str(self.model))
-
- def test_dict_serialization(self):
- self.model['dt'] = {'a': 1, 'b': 2}
-
- target_str = ('dt = \n'
- ' a = 1\n'
- ' b = 2\n'
- 'int = 1\n'
- 'string = value')
- self.assertEqual(target_str, str(self.model))
-
- def test_list_serialization(self):
- self.model['lt'] = ['a', 'b']
-
- target_str = ('int = 1\n'
- 'lt = \n'
- ' a\n'
- ' b\n'
- 'string = value')
- self.assertEqual(target_str, str(self.model))
-
- def test_list_in_dict_serialization(self):
- self.model['dt'] = {'a': 1, 'b': [2, 3]}
-
- target_str = ('dt = \n'
- ' a = 1\n'
- ' b = \n'
- ' 2\n'
- ' 3\n'
- 'int = 1\n'
- 'string = value')
-
- self.assertEqual(target_str, str(self.model))
-
- def test_dict_in_list_serialization(self):
- self.model['lt'] = [1, {'b': 2, 'c': 3}]
-
- target_str = ('int = 1\n'
- 'lt = \n'
- ' 1\n'
- ' [dict]\n'
- ' b = 2\n'
- ' c = 3\n'
- 'string = value')
- self.assertEqual(target_str, str(self.model))
-
- def test_submodel_serialization(self):
- sm = mwdv_generator()
- sm.set_current_view_type('text')
-
- self.model['submodel'] = sm
-
- target_str = ('int = 1\n'
- 'string = value\n'
- 'submodel = \n'
- ' int = 1\n'
- ' string = value')
- self.assertEqual(target_str, str(self.model))
-
- def test_custom_indent_string(self):
- view = text_generic.KeyValueView(indent_str='~~')
-
- self.model['lt'] = ['a', 'b']
- self.model.attached_view = view
-
- target_str = ('int = 1\n'
- 'lt = \n'
- '~~a\n'
- '~~b\n'
- 'string = value')
- self.assertEqual(target_str, str(self.model))
-
-
-def get_open_mocks(rv):
- file_mock = mock.MagicMock(name='file_obj')
- file_mock.read.return_value = rv
- open_mock = mock.MagicMock(name='open')
- open_mock().__enter__.return_value = file_mock
- return (open_mock, file_mock)
-
-
-class TestJinjaView(base.BaseTestCase):
-
- TEMPL_STR = "int is {{ int }}, string is {{ string }}"
- MM_OPEN, MM_FILE = get_open_mocks(TEMPL_STR)
-
- def setUp(self):
- super(TestJinjaView, self).setUp()
- self.model = base_model.ReportModel(data={'int': 1, 'string': 'value'})
-
- @mock.mock_open(MM_OPEN)
- def test_load_from_file(self):
- self.model.attached_view = jv.JinjaView(path='a/b/c/d.jinja.txt')
-
- self.assertEqual('int is 1, string is value', str(self.model))
- self.MM_FILE.assert_called_with_once('a/b/c/d.jinja.txt')
-
- def test_direct_pass(self):
- self.model.attached_view = jv.JinjaView(text=self.TEMPL_STR)
-
- self.assertEqual('int is 1, string is value', str(self.model))
-
- def test_load_from_class(self):
- class TmpJinjaView(jv.JinjaView):
- VIEW_TEXT = TestJinjaView.TEMPL_STR
-
- self.model.attached_view = TmpJinjaView()
-
- self.assertEqual('int is 1, string is value', str(self.model))
-
- def test_is_deepcopiable(self):
- view_orig = jv.JinjaView(text=self.TEMPL_STR)
- view_cpy = copy.deepcopy(view_orig)
-
- self.assertIsNot(view_orig, view_cpy)