mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 01:08:39 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
583
python/mock-1.0.0/docs/helpers.txt
Normal file
583
python/mock-1.0.0/docs/helpers.txt
Normal file
|
|
@ -0,0 +1,583 @@
|
|||
=========
|
||||
Helpers
|
||||
=========
|
||||
|
||||
.. currentmodule:: mock
|
||||
|
||||
.. testsetup::
|
||||
|
||||
mock.FILTER_DIR = True
|
||||
from pprint import pprint as pp
|
||||
original_dir = dir
|
||||
def dir(obj):
|
||||
print pp(original_dir(obj))
|
||||
|
||||
import urllib2
|
||||
__main__.urllib2 = urllib2
|
||||
|
||||
.. testcleanup::
|
||||
|
||||
dir = original_dir
|
||||
mock.FILTER_DIR = True
|
||||
|
||||
|
||||
|
||||
call
|
||||
====
|
||||
|
||||
.. function:: call(*args, **kwargs)
|
||||
|
||||
`call` is a helper object for making simpler assertions, for comparing
|
||||
with :attr:`~Mock.call_args`, :attr:`~Mock.call_args_list`,
|
||||
:attr:`~Mock.mock_calls` and :attr: `~Mock.method_calls`. `call` can also be
|
||||
used with :meth:`~Mock.assert_has_calls`.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> m = MagicMock(return_value=None)
|
||||
>>> m(1, 2, a='foo', b='bar')
|
||||
>>> m()
|
||||
>>> m.call_args_list == [call(1, 2, a='foo', b='bar'), call()]
|
||||
True
|
||||
|
||||
.. method:: call.call_list()
|
||||
|
||||
For a call object that represents multiple calls, `call_list`
|
||||
returns a list of all the intermediate calls as well as the
|
||||
final call.
|
||||
|
||||
`call_list` is particularly useful for making assertions on "chained calls". A
|
||||
chained call is multiple calls on a single line of code. This results in
|
||||
multiple entries in :attr:`~Mock.mock_calls` on a mock. Manually constructing
|
||||
the sequence of calls can be tedious.
|
||||
|
||||
:meth:`~call.call_list` can construct the sequence of calls from the same
|
||||
chained call:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> m = MagicMock()
|
||||
>>> m(1).method(arg='foo').other('bar')(2.0)
|
||||
<MagicMock name='mock().method().other()()' id='...'>
|
||||
>>> kall = call(1).method(arg='foo').other('bar')(2.0)
|
||||
>>> kall.call_list()
|
||||
[call(1),
|
||||
call().method(arg='foo'),
|
||||
call().method().other('bar'),
|
||||
call().method().other()(2.0)]
|
||||
>>> m.mock_calls == kall.call_list()
|
||||
True
|
||||
|
||||
.. _calls-as-tuples:
|
||||
|
||||
A `call` object is either a tuple of (positional args, keyword args) or
|
||||
(name, positional args, keyword args) depending on how it was constructed. When
|
||||
you construct them yourself this isn't particularly interesting, but the `call`
|
||||
objects that are in the :attr:`Mock.call_args`, :attr:`Mock.call_args_list` and
|
||||
:attr:`Mock.mock_calls` attributes can be introspected to get at the individual
|
||||
arguments they contain.
|
||||
|
||||
The `call` objects in :attr:`Mock.call_args` and :attr:`Mock.call_args_list`
|
||||
are two-tuples of (positional args, keyword args) whereas the `call` objects
|
||||
in :attr:`Mock.mock_calls`, along with ones you construct yourself, are
|
||||
three-tuples of (name, positional args, keyword args).
|
||||
|
||||
You can use their "tupleness" to pull out the individual arguments for more
|
||||
complex introspection and assertions. The positional arguments are a tuple
|
||||
(an empty tuple if there are no positional arguments) and the keyword
|
||||
arguments are a dictionary:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> m = MagicMock(return_value=None)
|
||||
>>> m(1, 2, 3, arg='one', arg2='two')
|
||||
>>> kall = m.call_args
|
||||
>>> args, kwargs = kall
|
||||
>>> args
|
||||
(1, 2, 3)
|
||||
>>> kwargs
|
||||
{'arg2': 'two', 'arg': 'one'}
|
||||
>>> args is kall[0]
|
||||
True
|
||||
>>> kwargs is kall[1]
|
||||
True
|
||||
|
||||
>>> m = MagicMock()
|
||||
>>> m.foo(4, 5, 6, arg='two', arg2='three')
|
||||
<MagicMock name='mock.foo()' id='...'>
|
||||
>>> kall = m.mock_calls[0]
|
||||
>>> name, args, kwargs = kall
|
||||
>>> name
|
||||
'foo'
|
||||
>>> args
|
||||
(4, 5, 6)
|
||||
>>> kwargs
|
||||
{'arg2': 'three', 'arg': 'two'}
|
||||
>>> name is m.mock_calls[0][0]
|
||||
True
|
||||
|
||||
|
||||
create_autospec
|
||||
===============
|
||||
|
||||
.. function:: create_autospec(spec, spec_set=False, instance=False, **kwargs)
|
||||
|
||||
Create a mock object using another object as a spec. Attributes on the
|
||||
mock will use the corresponding attribute on the `spec` object as their
|
||||
spec.
|
||||
|
||||
Functions or methods being mocked will have their arguments checked to
|
||||
ensure that they are called with the correct signature.
|
||||
|
||||
If `spec_set` is `True` then attempting to set attributes that don't exist
|
||||
on the spec object will raise an `AttributeError`.
|
||||
|
||||
If a class is used as a spec then the return value of the mock (the
|
||||
instance of the class) will have the same spec. You can use a class as the
|
||||
spec for an instance object by passing `instance=True`. The returned mock
|
||||
will only be callable if instances of the mock are callable.
|
||||
|
||||
`create_autospec` also takes arbitrary keyword arguments that are passed to
|
||||
the constructor of the created mock.
|
||||
|
||||
See :ref:`auto-speccing` for examples of how to use auto-speccing with
|
||||
`create_autospec` and the `autospec` argument to :func:`patch`.
|
||||
|
||||
|
||||
ANY
|
||||
===
|
||||
|
||||
.. data:: ANY
|
||||
|
||||
Sometimes you may need to make assertions about *some* of the arguments in a
|
||||
call to mock, but either not care about some of the arguments or want to pull
|
||||
them individually out of :attr:`~Mock.call_args` and make more complex
|
||||
assertions on them.
|
||||
|
||||
To ignore certain arguments you can pass in objects that compare equal to
|
||||
*everything*. Calls to :meth:`~Mock.assert_called_with` and
|
||||
:meth:`~Mock.assert_called_once_with` will then succeed no matter what was
|
||||
passed in.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> mock = Mock(return_value=None)
|
||||
>>> mock('foo', bar=object())
|
||||
>>> mock.assert_called_once_with('foo', bar=ANY)
|
||||
|
||||
`ANY` can also be used in comparisons with call lists like
|
||||
:attr:`~Mock.mock_calls`:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> m = MagicMock(return_value=None)
|
||||
>>> m(1)
|
||||
>>> m(1, 2)
|
||||
>>> m(object())
|
||||
>>> m.mock_calls == [call(1), call(1, 2), ANY]
|
||||
True
|
||||
|
||||
|
||||
|
||||
FILTER_DIR
|
||||
==========
|
||||
|
||||
.. data:: FILTER_DIR
|
||||
|
||||
`FILTER_DIR` is a module level variable that controls the way mock objects
|
||||
respond to `dir` (only for Python 2.6 or more recent). The default is `True`,
|
||||
which uses the filtering described below, to only show useful members. If you
|
||||
dislike this filtering, or need to switch it off for diagnostic purposes, then
|
||||
set `mock.FILTER_DIR = False`.
|
||||
|
||||
With filtering on, `dir(some_mock)` shows only useful attributes and will
|
||||
include any dynamically created attributes that wouldn't normally be shown.
|
||||
If the mock was created with a `spec` (or `autospec` of course) then all the
|
||||
attributes from the original are shown, even if they haven't been accessed
|
||||
yet:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> dir(Mock())
|
||||
['assert_any_call',
|
||||
'assert_called_once_with',
|
||||
'assert_called_with',
|
||||
'assert_has_calls',
|
||||
'attach_mock',
|
||||
...
|
||||
>>> import urllib2
|
||||
>>> dir(Mock(spec=urllib2))
|
||||
['AbstractBasicAuthHandler',
|
||||
'AbstractDigestAuthHandler',
|
||||
'AbstractHTTPHandler',
|
||||
'BaseHandler',
|
||||
...
|
||||
|
||||
Many of the not-very-useful (private to `Mock` rather than the thing being
|
||||
mocked) underscore and double underscore prefixed attributes have been
|
||||
filtered from the result of calling `dir` on a `Mock`. If you dislike this
|
||||
behaviour you can switch it off by setting the module level switch
|
||||
`FILTER_DIR`:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> import mock
|
||||
>>> mock.FILTER_DIR = False
|
||||
>>> dir(mock.Mock())
|
||||
['_NonCallableMock__get_return_value',
|
||||
'_NonCallableMock__get_side_effect',
|
||||
'_NonCallableMock__return_value_doc',
|
||||
'_NonCallableMock__set_return_value',
|
||||
'_NonCallableMock__set_side_effect',
|
||||
'__call__',
|
||||
'__class__',
|
||||
...
|
||||
|
||||
Alternatively you can just use `vars(my_mock)` (instance members) and
|
||||
`dir(type(my_mock))` (type members) to bypass the filtering irrespective of
|
||||
`mock.FILTER_DIR`.
|
||||
|
||||
|
||||
mock_open
|
||||
=========
|
||||
|
||||
.. function:: mock_open(mock=None, read_data=None)
|
||||
|
||||
A helper function to create a mock to replace the use of `open`. It works
|
||||
for `open` called directly or used as a context manager.
|
||||
|
||||
The `mock` argument is the mock object to configure. If `None` (the
|
||||
default) then a `MagicMock` will be created for you, with the API limited
|
||||
to methods or attributes available on standard file handles.
|
||||
|
||||
`read_data` is a string for the `read` method of the file handle to return.
|
||||
This is an empty string by default.
|
||||
|
||||
Using `open` as a context manager is a great way to ensure your file handles
|
||||
are closed properly and is becoming common::
|
||||
|
||||
with open('/some/path', 'w') as f:
|
||||
f.write('something')
|
||||
|
||||
The issue is that even if you mock out the call to `open` it is the
|
||||
*returned object* that is used as a context manager (and has `__enter__` and
|
||||
`__exit__` called).
|
||||
|
||||
Mocking context managers with a :class:`MagicMock` is common enough and fiddly
|
||||
enough that a helper function is useful.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> from mock import mock_open
|
||||
>>> m = mock_open()
|
||||
>>> with patch('__main__.open', m, create=True):
|
||||
... with open('foo', 'w') as h:
|
||||
... h.write('some stuff')
|
||||
...
|
||||
>>> m.mock_calls
|
||||
[call('foo', 'w'),
|
||||
call().__enter__(),
|
||||
call().write('some stuff'),
|
||||
call().__exit__(None, None, None)]
|
||||
>>> m.assert_called_once_with('foo', 'w')
|
||||
>>> handle = m()
|
||||
>>> handle.write.assert_called_once_with('some stuff')
|
||||
|
||||
And for reading files:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> with patch('__main__.open', mock_open(read_data='bibble'), create=True) as m:
|
||||
... with open('foo') as h:
|
||||
... result = h.read()
|
||||
...
|
||||
>>> m.assert_called_once_with('foo')
|
||||
>>> assert result == 'bibble'
|
||||
|
||||
|
||||
.. _auto-speccing:
|
||||
|
||||
Autospeccing
|
||||
============
|
||||
|
||||
Autospeccing is based on the existing `spec` feature of mock. It limits the
|
||||
api of mocks to the api of an original object (the spec), but it is recursive
|
||||
(implemented lazily) so that attributes of mocks only have the same api as
|
||||
the attributes of the spec. In addition mocked functions / methods have the
|
||||
same call signature as the original so they raise a `TypeError` if they are
|
||||
called incorrectly.
|
||||
|
||||
Before I explain how auto-speccing works, here's why it is needed.
|
||||
|
||||
`Mock` is a very powerful and flexible object, but it suffers from two flaws
|
||||
when used to mock out objects from a system under test. One of these flaws is
|
||||
specific to the `Mock` api and the other is a more general problem with using
|
||||
mock objects.
|
||||
|
||||
First the problem specific to `Mock`. `Mock` has two assert methods that are
|
||||
extremely handy: :meth:`~Mock.assert_called_with` and
|
||||
:meth:`~Mock.assert_called_once_with`.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> mock = Mock(name='Thing', return_value=None)
|
||||
>>> mock(1, 2, 3)
|
||||
>>> mock.assert_called_once_with(1, 2, 3)
|
||||
>>> mock(1, 2, 3)
|
||||
>>> mock.assert_called_once_with(1, 2, 3)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AssertionError: Expected to be called once. Called 2 times.
|
||||
|
||||
Because mocks auto-create attributes on demand, and allow you to call them
|
||||
with arbitrary arguments, if you misspell one of these assert methods then
|
||||
your assertion is gone:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> mock = Mock(name='Thing', return_value=None)
|
||||
>>> mock(1, 2, 3)
|
||||
>>> mock.assret_called_once_with(4, 5, 6)
|
||||
|
||||
Your tests can pass silently and incorrectly because of the typo.
|
||||
|
||||
The second issue is more general to mocking. If you refactor some of your
|
||||
code, rename members and so on, any tests for code that is still using the
|
||||
*old api* but uses mocks instead of the real objects will still pass. This
|
||||
means your tests can all pass even though your code is broken.
|
||||
|
||||
Note that this is another reason why you need integration tests as well as
|
||||
unit tests. Testing everything in isolation is all fine and dandy, but if you
|
||||
don't test how your units are "wired together" there is still lots of room
|
||||
for bugs that tests might have caught.
|
||||
|
||||
`mock` already provides a feature to help with this, called speccing. If you
|
||||
use a class or instance as the `spec` for a mock then you can only access
|
||||
attributes on the mock that exist on the real class:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> import urllib2
|
||||
>>> mock = Mock(spec=urllib2.Request)
|
||||
>>> mock.assret_called_with
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AttributeError: Mock object has no attribute 'assret_called_with'
|
||||
|
||||
The spec only applies to the mock itself, so we still have the same issue
|
||||
with any methods on the mock:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> mock.has_data()
|
||||
<mock.Mock object at 0x...>
|
||||
>>> mock.has_data.assret_called_with()
|
||||
|
||||
Auto-speccing solves this problem. You can either pass `autospec=True` to
|
||||
`patch` / `patch.object` or use the `create_autospec` function to create a
|
||||
mock with a spec. If you use the `autospec=True` argument to `patch` then the
|
||||
object that is being replaced will be used as the spec object. Because the
|
||||
speccing is done "lazily" (the spec is created as attributes on the mock are
|
||||
accessed) you can use it with very complex or deeply nested objects (like
|
||||
modules that import modules that import modules) without a big performance
|
||||
hit.
|
||||
|
||||
Here's an example of it in use:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> import urllib2
|
||||
>>> patcher = patch('__main__.urllib2', autospec=True)
|
||||
>>> mock_urllib2 = patcher.start()
|
||||
>>> urllib2 is mock_urllib2
|
||||
True
|
||||
>>> urllib2.Request
|
||||
<MagicMock name='urllib2.Request' spec='Request' id='...'>
|
||||
|
||||
You can see that `urllib2.Request` has a spec. `urllib2.Request` takes two
|
||||
arguments in the constructor (one of which is `self`). Here's what happens if
|
||||
we try to call it incorrectly:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> req = urllib2.Request()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: <lambda>() takes at least 2 arguments (1 given)
|
||||
|
||||
The spec also applies to instantiated classes (i.e. the return value of
|
||||
specced mocks):
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> req = urllib2.Request('foo')
|
||||
>>> req
|
||||
<NonCallableMagicMock name='urllib2.Request()' spec='Request' id='...'>
|
||||
|
||||
`Request` objects are not callable, so the return value of instantiating our
|
||||
mocked out `urllib2.Request` is a non-callable mock. With the spec in place
|
||||
any typos in our asserts will raise the correct error:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> req.add_header('spam', 'eggs')
|
||||
<MagicMock name='urllib2.Request().add_header()' id='...'>
|
||||
>>> req.add_header.assret_called_with
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AttributeError: Mock object has no attribute 'assret_called_with'
|
||||
>>> req.add_header.assert_called_with('spam', 'eggs')
|
||||
|
||||
In many cases you will just be able to add `autospec=True` to your existing
|
||||
`patch` calls and then be protected against bugs due to typos and api
|
||||
changes.
|
||||
|
||||
As well as using `autospec` through `patch` there is a
|
||||
:func:`create_autospec` for creating autospecced mocks directly:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> import urllib2
|
||||
>>> mock_urllib2 = create_autospec(urllib2)
|
||||
>>> mock_urllib2.Request('foo', 'bar')
|
||||
<NonCallableMagicMock name='mock.Request()' spec='Request' id='...'>
|
||||
|
||||
This isn't without caveats and limitations however, which is why it is not
|
||||
the default behaviour. In order to know what attributes are available on the
|
||||
spec object, autospec has to introspect (access attributes) the spec. As you
|
||||
traverse attributes on the mock a corresponding traversal of the original
|
||||
object is happening under the hood. If any of your specced objects have
|
||||
properties or descriptors that can trigger code execution then you may not be
|
||||
able to use autospec. On the other hand it is much better to design your
|
||||
objects so that introspection is safe [#]_.
|
||||
|
||||
A more serious problem is that it is common for instance attributes to be
|
||||
created in the `__init__` method and not to exist on the class at all.
|
||||
`autospec` can't know about any dynamically created attributes and restricts
|
||||
the api to visible attributes.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> class Something(object):
|
||||
... def __init__(self):
|
||||
... self.a = 33
|
||||
...
|
||||
>>> with patch('__main__.Something', autospec=True):
|
||||
... thing = Something()
|
||||
... thing.a
|
||||
...
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AttributeError: Mock object has no attribute 'a'
|
||||
|
||||
There are a few different ways of resolving this problem. The easiest, but
|
||||
not necessarily the least annoying, way is to simply set the required
|
||||
attributes on the mock after creation. Just because `autospec` doesn't allow
|
||||
you to fetch attributes that don't exist on the spec it doesn't prevent you
|
||||
setting them:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> with patch('__main__.Something', autospec=True):
|
||||
... thing = Something()
|
||||
... thing.a = 33
|
||||
...
|
||||
|
||||
There is a more aggressive version of both `spec` and `autospec` that *does*
|
||||
prevent you setting non-existent attributes. This is useful if you want to
|
||||
ensure your code only *sets* valid attributes too, but obviously it prevents
|
||||
this particular scenario:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> with patch('__main__.Something', autospec=True, spec_set=True):
|
||||
... thing = Something()
|
||||
... thing.a = 33
|
||||
...
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AttributeError: Mock object has no attribute 'a'
|
||||
|
||||
Probably the best way of solving the problem is to add class attributes as
|
||||
default values for instance members initialised in `__init__`. Note that if
|
||||
you are only setting default attributes in `__init__` then providing them via
|
||||
class attributes (shared between instances of course) is faster too. e.g.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class Something(object):
|
||||
a = 33
|
||||
|
||||
This brings up another issue. It is relatively common to provide a default
|
||||
value of `None` for members that will later be an object of a different type.
|
||||
`None` would be useless as a spec because it wouldn't let you access *any*
|
||||
attributes or methods on it. As `None` is *never* going to be useful as a
|
||||
spec, and probably indicates a member that will normally of some other type,
|
||||
`autospec` doesn't use a spec for members that are set to `None`. These will
|
||||
just be ordinary mocks (well - `MagicMocks`):
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> class Something(object):
|
||||
... member = None
|
||||
...
|
||||
>>> mock = create_autospec(Something)
|
||||
>>> mock.member.foo.bar.baz()
|
||||
<MagicMock name='mock.member.foo.bar.baz()' id='...'>
|
||||
|
||||
If modifying your production classes to add defaults isn't to your liking
|
||||
then there are more options. One of these is simply to use an instance as the
|
||||
spec rather than the class. The other is to create a subclass of the
|
||||
production class and add the defaults to the subclass without affecting the
|
||||
production class. Both of these require you to use an alternative object as
|
||||
the spec. Thankfully `patch` supports this - you can simply pass the
|
||||
alternative object as the `autospec` argument:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> class Something(object):
|
||||
... def __init__(self):
|
||||
... self.a = 33
|
||||
...
|
||||
>>> class SomethingForTest(Something):
|
||||
... a = 33
|
||||
...
|
||||
>>> p = patch('__main__.Something', autospec=SomethingForTest)
|
||||
>>> mock = p.start()
|
||||
>>> mock.a
|
||||
<NonCallableMagicMock name='Something.a' spec='int' id='...'>
|
||||
|
||||
.. note::
|
||||
|
||||
An additional limitation (currently) with `autospec` is that unbound
|
||||
methods on mocked classes *don't* take an "explicit self" as the first
|
||||
argument - so this usage will fail with `autospec`.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> class Foo(object):
|
||||
... def foo(self):
|
||||
... pass
|
||||
...
|
||||
>>> Foo.foo(Foo())
|
||||
>>> MockFoo = create_autospec(Foo)
|
||||
>>> MockFoo.foo(MockFoo())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: <lambda>() takes exactly 1 argument (2 given)
|
||||
|
||||
The reason is that its very hard to tell the difference between functions,
|
||||
unbound methods and staticmethods across Python 2 & 3 and the alternative
|
||||
implementations. This restriction may be fixed in future versions.
|
||||
|
||||
|
||||
------
|
||||
|
||||
.. [#] This only applies to classes or already instantiated objects. Calling
|
||||
a mocked class to create a mock instance *does not* create a real instance.
|
||||
It is only attribute lookups - along with calls to `dir` - that are done. A
|
||||
way round this problem would have been to use `getattr_static
|
||||
<http://docs.python.org/dev/library/inspect.html#inspect.getattr_static>`_,
|
||||
which can fetch attributes without triggering code execution. Descriptors
|
||||
like `classmethod` and `staticmethod` *need* to be fetched correctly though,
|
||||
so that their signatures can be mocked correctly.
|
||||
Loading…
Add table
Add a link
Reference in a new issue