如何模拟导入

发布于 2024-12-23 00:05:49 字数 537 浏览 1 评论 0原文

模块 A 在其顶部包含 import B。但是,在测试条件下,我想 mock BA(模拟AB)中并完全避免导入B

事实上,B 并不是故意安装在测试环境中的。

A 是被测单元。我必须导入 A 及其所有功能。 B 是我需要模拟的模块。但是我如何在 A 中模拟 B 并阻止 A 导入真正的 B,如果第一件事 < code>A 是否导入 B

(未安装 B 的原因是我使用 pypy 进行快速测试,不幸的是 B 尚未与 pypy 兼容。)

这怎么办?

Module A includes import B at its top. However under test conditions I'd like to mock B in A (mock A.B) and completely refrain from importing B.

In fact, B isn't installed in the test environment on purpose.

A is the unit under test. I have to import A with all its functionality. B is the module I need to mock. But how can I mock B within A and stop A from importing the real B, if the first thing A does is import B?

(The reason B isn't installed is that I use pypy for quick testing and unfortunately B isn't compatible with pypy yet.)

How could this be done?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

青衫负雪 2024-12-30 00:05:49

您可以在导入 A 之前分配给 sys.modules['B'] 以获得您想要的:

test.py:

import sys
sys.modules['B'] = __import__('mock_B')
import A

print(A.B.__name__)

A .py

import B

注意 B.py 不存在,但是运行 test.py 时不会返回错误,并且 print(AB__name__) 打印 mock_B< /代码>。您仍然需要创建一个 mock_B.py 来模拟 B 的实际函数/变量/等。或者你可以直接分配一个Mock()

test.py

import sys
sys.modules['B'] = Mock()
import A

You can assign to sys.modules['B'] before importing A to get what you want:

test.py:

import sys
sys.modules['B'] = __import__('mock_B')
import A

print(A.B.__name__)

A.py:

import B

Note B.py does not exist, but when running test.py no error is returned and print(A.B.__name__) prints mock_B. You still have to create a mock_B.py where you mock B's actual functions/variables/etc. Or you can just assign a Mock() directly:

test.py:

import sys
sys.modules['B'] = Mock()
import A
沙沙粒小 2024-12-30 00:05:49

内置的 __import__ 可以使用“mock”库进行模拟以获得更多控制:

# Store original __import__
orig_import = __import__
# This will be the B module
b_mock = mock.Mock()

def import_mock(name, *args):
    if name == 'B':
        return b_mock
    return orig_import(name, *args)

with mock.patch('__builtin__.__import__', side_effect=import_mock):
    import A

假设 A 看起来像:

import B

def a():
    return B.func()

Aa() 返回 b_mock .func() 也可以被模拟。

b_mock.func.return_value = 'spam'
A.a()  # returns 'spam'

Python 3 注释:
3.0 的变更日志中所述,__builtin__< /code> 现在命名为 builtins

将模块 __builtin__ 重命名为 builtins(删除下划线,添加“s”)。

如果将 Python 3 的 __builtin__ 替换为 builtins,则此答案中的代码可以正常工作。

The builtin __import__ can be mocked with the 'mock' library for more control:

# Store original __import__
orig_import = __import__
# This will be the B module
b_mock = mock.Mock()

def import_mock(name, *args):
    if name == 'B':
        return b_mock
    return orig_import(name, *args)

with mock.patch('__builtin__.__import__', side_effect=import_mock):
    import A

Say A looks like:

import B

def a():
    return B.func()

A.a() returns b_mock.func() which can be mocked also.

b_mock.func.return_value = 'spam'
A.a()  # returns 'spam'

Note for Python 3:
As stated in the changelog for 3.0, __builtin__ is now named builtins:

Renamed module __builtin__ to builtins (removing the underscores, adding an ‘s’).

The code in this answer works fine if you replace __builtin__ by builtins for Python 3.

逆夏时光 2024-12-30 00:05:49

如何模拟导入(模拟 AB)?

模块 A 在其顶部包含导入 B。

很简单,只需在导入之前在 sys.modules 中模拟该库:

if wrong_platform():
    sys.modules['B'] = mock.MagicMock()

然后,只要 A 不依赖于从 B 的对象返回的特定类型的数据:

import A

应该可以工作。

您还可以模拟import AB

即使您有子模块,这也可以工作,但您需要模拟每个模块。假设你有这个:

from foo import This, That, andTheOtherThing
from foo.bar import Yada, YadaYada
from foo.baz import Blah, getBlah, boink

要模拟,只需在导入包含上述内容的模块之前执行以下操作:(

sys.modules['foo'] = MagicMock()
sys.modules['foo.bar'] = MagicMock()
sys.modules['foo.baz'] = MagicMock()

我的经验:我有一个依赖项可以在一个平台 Windows 上工作,但不能在 Linux 上工作,我们在 Linux 上运行我们的日常测试。
所以我需要模拟我们测试的依赖关系。幸运的是,它是一个黑匣子,所以我不需要设置很多交互。)

模拟副作用

附录:实际上,我需要模拟一个需要一些时间的副作用。所以我需要一个对象的方法来休眠一秒钟。这会像这样工作:

sys.modules['foo'] = MagicMock()
sys.modules['foo.bar'] = MagicMock()
sys.modules['foo.baz'] = MagicMock()
# setup the side-effect:
from time import sleep

def sleep_one(*args): 
    sleep(1)

# this gives us the mock objects that will be used
from foo.bar import MyObject 
my_instance = MyObject()
# mock the method!
my_instance.method_that_takes_time = mock.MagicMock(side_effect=sleep_one)

然后代码需要一些时间来运行,就像真正的方法一样。

How to mock an import, (mock A.B)?

Module A includes import B at its top.

Easy, just mock the library in sys.modules before it gets imported:

if wrong_platform():
    sys.modules['B'] = mock.MagicMock()

and then, so long as A doesn't rely on specific types of data being returned from B's objects:

import A

should just work.

You can also mock import A.B:

This works even if you have submodules, but you'll want to mock each module. Say you have this:

from foo import This, That, andTheOtherThing
from foo.bar import Yada, YadaYada
from foo.baz import Blah, getBlah, boink

To mock, simply do the below before the module that contains the above is imported:

sys.modules['foo'] = MagicMock()
sys.modules['foo.bar'] = MagicMock()
sys.modules['foo.baz'] = MagicMock()

(My experience: I had a dependency that works on one platform, Windows, but didn't work on Linux, where we run our daily tests.
So I needed to mock the dependency for our tests. Luckily it was a black box, so I didn't need to set up a lot of interaction.)

Mocking Side Effects

Addendum: Actually, I needed to simulate a side-effect that took some time. So I needed an object's method to sleep for a second. That would work like this:

sys.modules['foo'] = MagicMock()
sys.modules['foo.bar'] = MagicMock()
sys.modules['foo.baz'] = MagicMock()
# setup the side-effect:
from time import sleep

def sleep_one(*args): 
    sleep(1)

# this gives us the mock objects that will be used
from foo.bar import MyObject 
my_instance = MyObject()
# mock the method!
my_instance.method_that_takes_time = mock.MagicMock(side_effect=sleep_one)

And then the code takes some time to run, just like the real method.

泡沫很甜 2024-12-30 00:05:49

亚伦·霍尔的答案对我有用。
只是想提一件重要的事情,

如果在 A.py 中你执行

from BCD import E

那么在 test.py 中你必须模拟每个模块沿着路径,否则你会得到ImportError

sys.modules['B'] = mock.MagicMock()
sys.modules['B.C'] = mock.MagicMock()
sys.modules['B.C.D'] = mock.MagicMock()

Aaron Hall's answer works for me.
Just want to mention one important thing,

if in A.py you do

from B.C.D import E

then in test.py you must mock every module along the path, otherwise you get ImportError

sys.modules['B'] = mock.MagicMock()
sys.modules['B.C'] = mock.MagicMock()
sys.modules['B.C.D'] = mock.MagicMock()
听风念你 2024-12-30 00:05:49

我意识到我在这里参加派对有点晚了,但是这里有一种有点疯狂的方法来使用 mock 库自动执行此操作:(

这是一个示例用法)

import contextlib
import collections
import mock
import sys

def fake_module(**args):
    return (collections.namedtuple('module', args.keys())(**args))

def get_patch_dict(dotted_module_path, module):
    patch_dict = {}
    module_splits = dotted_module_path.split('.')

    # Add our module to the patch dict
    patch_dict[dotted_module_path] = module

    # We add the rest of the fake modules in backwards
    while module_splits:
        # This adds the next level up into the patch dict which is a fake
        # module that points at the next level down
        patch_dict['.'.join(module_splits[:-1])] = fake_module(
            **{module_splits[-1]: patch_dict['.'.join(module_splits)]}
        )
        module_splits = module_splits[:-1]

    return patch_dict

with mock.patch.dict(
    sys.modules,
    get_patch_dict('herp.derp', fake_module(foo='bar'))
):
    import herp.derp
    # prints bar
    print herp.derp.foo

这如此复杂的原因是当导入发生 python 基本上就是这样做的(例如 from herp.derp import foo

  1. sys.modules['herp'] 存在吗?否则导入它。如果仍然不是 ImportError
  2. sys.modules['herp.derp'] 是否存在?否则导入它。如果仍然不是 ImportError
  3. 获取 sys.modules['herp.derp'] 的属性 foo。 Else ImportError
  4. foo = sys.modules['herp.derp'].foo

这个拼凑在一起的解决方案有一些缺点:如果其他东西依赖于模块中的其他东西路径这种螺丝把它搞砸了。此外,这适用于内联导入的内容,例如

def foo():
    import herp.derp

def foo():
    __import__('herp.derp')

I realize I'm a bit late to the party here, but here's a somewhat insane way to automate this with the mock library:

(here's an example usage)

import contextlib
import collections
import mock
import sys

def fake_module(**args):
    return (collections.namedtuple('module', args.keys())(**args))

def get_patch_dict(dotted_module_path, module):
    patch_dict = {}
    module_splits = dotted_module_path.split('.')

    # Add our module to the patch dict
    patch_dict[dotted_module_path] = module

    # We add the rest of the fake modules in backwards
    while module_splits:
        # This adds the next level up into the patch dict which is a fake
        # module that points at the next level down
        patch_dict['.'.join(module_splits[:-1])] = fake_module(
            **{module_splits[-1]: patch_dict['.'.join(module_splits)]}
        )
        module_splits = module_splits[:-1]

    return patch_dict

with mock.patch.dict(
    sys.modules,
    get_patch_dict('herp.derp', fake_module(foo='bar'))
):
    import herp.derp
    # prints bar
    print herp.derp.foo

The reason this is so ridiculously complicated is when an import occurs python basically does this (take for example from herp.derp import foo)

  1. Does sys.modules['herp'] exist? Else import it. If still not ImportError
  2. Does sys.modules['herp.derp'] exist? Else import it. If still not ImportError
  3. Get attribute foo of sys.modules['herp.derp']. Else ImportError
  4. foo = sys.modules['herp.derp'].foo

There are some downsides to this hacked together solution: If something else relies on other stuff in the module path this kind of screws it over. Also this only works for stuff that is being imported inline such as

def foo():
    import herp.derp

or

def foo():
    __import__('herp.derp')
︶葆Ⅱㄣ 2024-12-30 00:05:49

我找到了在 Python 中模拟导入的好方法。 此处找到了 Eric 的 Zaadi 解决方案我只是在我的 Django 应用程序中使用。

我有类 SeatInterface ,它是 Seat 模型类的接口。
因此,在我的 seat_interface 模块中,我有这样的导入:

from ..models import Seat

class SeatInterface(object):
    (...)

我想为 SeatInterface 类创建隔离测试,并将模拟的 Seat 类作为 FakeSeat。问题是 - 如何在 Django 应用程序关闭的情况下离线运行测试。我有以下错误:

配置不正确:请求设置 BASE_DIR,但设置不正确
配置。您必须定义环境变量
DJANGO_SETTINGS_MODULE 或在访问之前调用 settings.configure()
设置。

在 0.078 秒内运行 1 次测试

失败(错误=1)

解决方案是:

import unittest
from mock import MagicMock, patch

class FakeSeat(object):
    pass

class TestSeatInterface(unittest.TestCase):

    def setUp(self):
        models_mock = MagicMock()
        models_mock.Seat.return_value = FakeSeat
        modules = {'app.app.models': models_mock}
        patch.dict('sys.modules', modules).start()

    def test1(self):
        from app.app.models_interface.seat_interface import SeatInterface

然后测试神奇地运行正常:)

.
在 0.002 秒内运行 1 次测试

确定

I found fine way to mock the imports in Python. It's Eric's Zaadi solution found here which I just use inside my Django application.

I've got class SeatInterface which is interface to Seat model class.
So inside my seat_interface module I have such an import:

from ..models import Seat

class SeatInterface(object):
    (...)

I wanted to create isolated tests for SeatInterface class with mocked Seat class as FakeSeat. The problem was - how tu run tests offline, where Django application is down. I had below error:

ImproperlyConfigured: Requested setting BASE_DIR, but settings are not
configured. You must either define the environment variable
DJANGO_SETTINGS_MODULE or call settings.configure() before accessing
settings.

Ran 1 test in 0.078s

FAILED (errors=1)

The solution was:

import unittest
from mock import MagicMock, patch

class FakeSeat(object):
    pass

class TestSeatInterface(unittest.TestCase):

    def setUp(self):
        models_mock = MagicMock()
        models_mock.Seat.return_value = FakeSeat
        modules = {'app.app.models': models_mock}
        patch.dict('sys.modules', modules).start()

    def test1(self):
        from app.app.models_interface.seat_interface import SeatInterface

And then test magically runs OK :)

.
Ran 1 test in 0.002s

OK

Oo萌小芽oO 2024-12-30 00:05:49

我知道这是一个相当老的问题,但我发现自己最近几次回到这个问题,并想分享一个简洁的解决方案。

import sys
from unittest import mock


def mock_module_import(module):
    """Source: https://stackoverflow.com/a/63584866/3972558"""
    def _outer_wrapper(func):
        def _inner_wrapper(*args, **kwargs):
            orig = sys.modules.get(module)  # get the original module, if present
            sys.modules[module] = mock.MagicMock()  # patch it
            try:
                return func(*args, **kwargs)
            finally:
                if orig is not None:  # if the module was installed, restore patch
                    sys.modules[module] = orig
                else:  # if the module never existed, remove the key
                    del sys.modules[module]
        return _inner_wrapper
    return _outer_wrapper

它的工作原理是临时修补 sys.modules 中模块的密钥,然后在调用修饰函数后恢复原始模块。这可以用于测试环境中可能未安装包的场景,或者更复杂的场景,其中修补的模块实际上可能执行一些其自己的内部猴子修补(这就是我面临的情况)。

这是一个使用示例:

@mock_module_import("some_module")
def test_foo():
    # use something that relies upon "some_module" here
    assert True

I know this is a fairly old question, but I have found myself returning to it a few times recently, and wanted to share a concise solution to this.

import sys
from unittest import mock


def mock_module_import(module):
    """Source: https://stackoverflow.com/a/63584866/3972558"""
    def _outer_wrapper(func):
        def _inner_wrapper(*args, **kwargs):
            orig = sys.modules.get(module)  # get the original module, if present
            sys.modules[module] = mock.MagicMock()  # patch it
            try:
                return func(*args, **kwargs)
            finally:
                if orig is not None:  # if the module was installed, restore patch
                    sys.modules[module] = orig
                else:  # if the module never existed, remove the key
                    del sys.modules[module]
        return _inner_wrapper
    return _outer_wrapper

It works by temporarily patching the key for the module in sys.modules, and then restoring the original module after the decorated function is called. This can be used in scenarios where a package may not be installed in the testing environment, or a more complex scenario where the patched module might actually perform some of its own internal monkey-patching (which was the case I was facing).

Here's an example of use:

@mock_module_import("some_module")
def test_foo():
    # use something that relies upon "some_module" here
    assert True
追星践月 2024-12-30 00:05:49

如果您执行import ModuleB,您实际上是在调用内置方法__import__

ModuleB = __import__('ModuleB', globals(), locals(), [], -1)

您可以通过导入__builtin__模块来覆盖此方法并创建一个__builtin__.__import__方法的包装器。或者您可以使用 imp 模块中的 NullImporter 挂钩。捕获异常并在 except 块中模拟您的模块/类。

指向相关文档的指针:

docs.python.org: __import__< /a>

使用 imp 模块访问导入内部

我希望这会有所帮助。 强烈建议您进入Python编程的更神秘的领域,a)充分理解您真正想要实现的目标,b)透彻理解其含义非常重要。

If you do an import ModuleB you are really calling the builtin method __import__ as:

ModuleB = __import__('ModuleB', globals(), locals(), [], -1)

You could overwrite this method by importing the __builtin__ module and make a wrapper around the __builtin__.__import__method. Or you could play with the NullImporter hook from the imp module. Catching the exception and Mock your module/class in the except-block.

Pointer to the relevant docs:

docs.python.org: __import__

Accessing Import internals with the imp Module

I hope this helps. Be HIGHLY adviced that you step into the more arcane perimeters of python programming and that a) solid understanding what you really want to achieve and b)thorough understanding of the implications is important.

ぃ弥猫深巷。 2024-12-30 00:05:49

我今天发现自己面临着类似的问题,并且我决定以不同的方式解决它。您无需在 Python 的导入机制之上进行黑客攻击,只需将模拟模块添加到 sys.path 中,并让 Python 优先选择它而不是原始模块。

  1. 在子目录中创建替换模块,例如:

    mkdir -p test/mocked-lib
    ${EDITOR} test/mocked-lib/B.py
    
  2. 在导入A之前,将此目录插入到sys.path。我正在使用 pytest,所以在我的 test/conftest.py 中,我简单地完成:

    导入os.path
    导入系统
    
    
    sys.path.insert(0, os.path.join(os.path.dirname(__file__), "mocked-lib"))
    

现在,当测试套件运行时,mocked-lib 子目录被添加到 sys.path 中,并且 import A 使用 B 来自模拟库

I found myself facing a similar problem today, and I've decided to solve it a bit differently. Rather than hacking on top of Python's import machinery, you can simply add the mocked module into sys.path, and have Python prefer it over the original module.

  1. Create the replacement module in a subdirectory, e.g.:

    mkdir -p test/mocked-lib
    ${EDITOR} test/mocked-lib/B.py
    
  2. Before A is imported, insert this directory to sys.path. I'm using pytest, so in my test/conftest.py, I've simply done:

    import os.path
    import sys
    
    
    sys.path.insert(0, os.path.join(os.path.dirname(__file__), "mocked-lib"))
    

Now, when the test suite is run, the mocked-lib subdirectory is prepended into sys.path and import A uses B from mocked-lib.

迷乱花海 2024-12-30 00:05:49

下面是使用 contextmanager 使测试看起来更清晰的一个:

正在测试的函数

def read_secret_from_databricks(scope: str, key: str) -> str:
    from pyspark.dbutils import DBUtils
    return DBUtils(spark).secrets.get(scope, key)

测试代码

from contextlib import contextmanager
from unittest import mock

# Usually in conftest.py
@contextmanager
def mocked_import(module_name, my_mock=None) -> mock.Mock:
    orig_import = __import__
    if not my_mock:
        my_mock = mock.MagicMock(name=f'mock_{module_name}')

    def import_mock(name, *args):
        return my_mock if name == module_name else orig_import(name, *args)

    with mock.patch('builtins.__import__', side_effect=import_mock):
        yield my_mock


# ---------------------------------------------------------------------
# some testcase.py

# fails with "ModuleNotFoundError: No module named 'dbutils'"
def test_read_secrets():
    read_secret_from_databricks('scope1', 'key1')


# Passes
def test_read_secrets_with_mock():
    with mocked_import('pyspark.dbutils') as m:
        read_secret_from_databricks('scope1', 'key1')
        assert mock.call.secrets.get('scope1', 'key1') in m.mock_calls

Here is one using contextmanager to make tests look cleaner:

Function being tested

def read_secret_from_databricks(scope: str, key: str) -> str:
    from pyspark.dbutils import DBUtils
    return DBUtils(spark).secrets.get(scope, key)

test code

from contextlib import contextmanager
from unittest import mock

# Usually in conftest.py
@contextmanager
def mocked_import(module_name, my_mock=None) -> mock.Mock:
    orig_import = __import__
    if not my_mock:
        my_mock = mock.MagicMock(name=f'mock_{module_name}')

    def import_mock(name, *args):
        return my_mock if name == module_name else orig_import(name, *args)

    with mock.patch('builtins.__import__', side_effect=import_mock):
        yield my_mock


# ---------------------------------------------------------------------
# some testcase.py

# fails with "ModuleNotFoundError: No module named 'dbutils'"
def test_read_secrets():
    read_secret_from_databricks('scope1', 'key1')


# Passes
def test_read_secrets_with_mock():
    with mocked_import('pyspark.dbutils') as m:
        read_secret_from_databricks('scope1', 'key1')
        assert mock.call.secrets.get('scope1', 'key1') in m.mock_calls
梦里南柯 2024-12-30 00:05:49

只是一点澄清和简化,我认为没有任何答案涵盖这一点。

假设我的应用程序类中有这些行:

try:
    import library_core.configure_module
    if not library_core.configure_module.configure_logging():
        print(f'WARN. Logger configuration failed', file=sys.stderr)
except BaseException as e:
    print(f'WARN. Logger configuration raised exception: {e}', file=sys.stderr)
    logging.exception('')

...在上面我们有 3 个通常涉及导入的组件:包 (library_core)、该包中的模块 (configure_module)并在该模块中运行(configure_logging)。

通常在测试中我们可能想要模拟包或模块导入失败,或者函数存在。我们可能还想模拟返回 False 的函数。

我们绝对不想做的另一件事是不安全地干扰 sys.modules,正如这里的许多答案所做的那样。 “手动”将其“恢复”到以前的状态也不够:因为测试可能会失败,因此在代码有机会执行此操作之前结束!这是基本的东西。相反,请使用上下文管理器:

以下是您如何使用 configure_logging 返回 TrueFalse 来测试行为:

@pytest.mark.parametrize('logger_config_success', [True, False])
def test_xxx...
    ...    
    mock_library_core_pkg = mock.Mock()
    with mock.patch.dict(sys.modules, {'library_core': mock_library_core_pkg}):
        mock_library_core_pkg.config_mod = mock.Mock()
        mock_library_core_pkg.config_mod.configure_logging = mock.Mock(return_value=logger_config_success)
        with mock.patch.dict(sys.modules, {'library_core.configure_module': mock_library_core_pkg.config_mod}):
            ... # here we do something which causes the app code to be run

...通常您可以使用capsys,在 False 返回时将显示消息“WARN。记录器配置失败”已打印到 stderr

我认为这种嵌套修补是模拟包然后模拟其中的模块(然后是函数......)的唯一(安全)方法。

Just a bit of clarification and simplification, and I don't think any answer covers this.

Say I have these lines in my app class:

try:
    import library_core.configure_module
    if not library_core.configure_module.configure_logging():
        print(f'WARN. Logger configuration failed', file=sys.stderr)
except BaseException as e:
    print(f'WARN. Logger configuration raised exception: {e}', file=sys.stderr)
    logging.exception('')

... in the above we have the 3 components typically involved in imports: package (library_core), module in that package (configure_module) and function in that module (configure_logging).

Typically in the tests we might want to simulate the failure of the import of the package or the module, or the existence of the function. We might also want to simulate the function returning False.

The other thing that we absolutely don't want to do is interfere unsafely with sys.modules, as so many answers here do. Nor is it sufficient to "restore" this to its former state "manually": because the test may fail and therefore end before the code gets a chance to do that! This is rudimentary stuff. Instead, use context managers:

Here's how you might test on the behaviour with configure_logging returning True or False:

@pytest.mark.parametrize('logger_config_success', [True, False])
def test_xxx...
    ...    
    mock_library_core_pkg = mock.Mock()
    with mock.patch.dict(sys.modules, {'library_core': mock_library_core_pkg}):
        mock_library_core_pkg.config_mod = mock.Mock()
        mock_library_core_pkg.config_mod.configure_logging = mock.Mock(return_value=logger_config_success)
        with mock.patch.dict(sys.modules, {'library_core.configure_module': mock_library_core_pkg.config_mod}):
            ... # here we do something which causes the app code to be run

... and typically you might use capsys, which on False return will show that the message "WARN. Logger configuration failed" was printed to stderr.

I think that this nested patching is the only (safe) way to mock a package and then mock a module within it (and then a function ...).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文