本文整理汇总了Python中mock.patch.multiple函数的典型用法代码示例。如果您正苦于以下问题:Python multiple函数的具体用法?Python multiple怎么用?Python multiple使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了multiple函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Python代码示例。
示例1: test_add_existant_nin
def test_add_existant_nin(self):
from eduiddashboard.msgrelay import MsgRelay
self.set_logged(user='[email protected]')
response_form = self.testapp.get('/profile/nins/')
form = response_form.forms[self.formname]
nin = '200010100001'
# First we add a nin...
with patch.object(UserDB, 'exists_by_filter', clear=True):
with patch.multiple(MsgRelay, nin_validator=return_true,
nin_reachable=return_true):
UserDB.exists_by_filter.return_value = True
form['norEduPersonNIN'].value = nin
form.submit('add')
# ...and then we try to add it again.
with patch.object(UserDB, 'exists_by_filter', clear=True):
with patch.multiple(MsgRelay, nin_validator=return_true,
nin_reachable=return_true):
UserDB.exists_by_filter.return_value = True
form['norEduPersonNIN'].value = nin
response = form.submit('add')
self.assertEqual(response.status, '200 OK')
self.assertIn(nin, response.body)
self.assertIn('alert-danger', response.body)
self.assertIsNotNone(getattr(response, 'form', None))
开发者ID:enriquepablo,项目名称:eduid-dashboard,代码行数:25,代码来源:test_views_nins.py
示例2: test_Providers_from_config__files
def test_Providers_from_config__files(sysdir, userdir, dsdir):
"""Test configuration file precedence
Ensure that provider precedence works in the correct order:
datalad defaults < dataset defaults < system defaults < user defaults
"""
# Test the default, this is an arbitrary provider used from another
# test
providers = Providers.from_config_files(reload=True)
provider = providers.get_provider('https://crcns.org/data....')
assert_equal(provider.name, 'crcns')
# Test that the dataset provider overrides the datalad
# default
with chpwd(dsdir):
providers = Providers.from_config_files(reload=True)
provider = providers.get_provider('https://crcns.org/data....')
assert_equal(provider.name, 'dscrcns')
# Test that the system defaults take precedence over the dataset
# defaults (we're still within the dsdir)
with patch.multiple("appdirs.AppDirs", site_config_dir=sysdir, user_config_dir=None):
providers = Providers.from_config_files(reload=True)
provider = providers.get_provider('https://crcns.org/data....')
assert_equal(provider.name, 'syscrcns')
# Test that the user defaults take precedence over the system
# defaults
with patch.multiple("appdirs.AppDirs", site_config_dir=sysdir, user_config_dir=userdir):
providers = Providers.from_config_files(reload=True)
provider = providers.get_provider('https://crcns.org/data....')
assert_equal(provider.name, 'usercrcns')
开发者ID:datalad,项目名称:datalad,代码行数:34,代码来源:test_providers.py
示例3: setUp
def setUp(self):
super(RedisRestoreTests, self).setUp()
self.conf_man_patch = patch.object(
configuration.ConfigurationManager, 'parse_configuration',
mock.Mock(return_value={'dir': '/var/lib/redis',
'dbfilename': 'dump.rdb'}))
self.conf_man_patch.start()
self.addCleanup(self.conf_man_patch.stop)
self.os_patch = patch.multiple(operating_system,
chown=DEFAULT,
create_directory=DEFAULT)
self.os_patch.start()
self.addCleanup(self.os_patch.stop)
self.restore_runner = utils.import_class(
RESTORE_REDIS_CLS)('swift', location='http://some.where',
checksum='True_checksum',
restore_location='/var/lib/somewhere')
self.restore_runner_patch = patch.multiple(
self.restore_runner, _run_restore=DEFAULT,
pre_restore=DEFAULT, post_restore=DEFAULT)
self.restore_runner_mocks = self.restore_runner_patch.start()
self.expected_content_length = 123
self.restore_runner._run_restore = mock.Mock(
return_value=self.expected_content_length)
self.addCleanup(self.restore_runner_patch.stop)
开发者ID:Tesora-Release,项目名称:tesora-trove,代码行数:26,代码来源:test_backups.py
示例4: test_main
def test_main(self):
suite_name = 'SUITE'
throttle = '3'
machine_type = 'burnupi'
def prepare_and_schedule(obj):
assert obj.base_config.suite == suite_name
assert obj.args.throttle == throttle
def fake_str(*args, **kwargs):
return 'fake'
def fake_bool(*args, **kwargs):
return True
with patch.multiple(
'teuthology.suite.run.util',
fetch_repos=DEFAULT,
package_version_for_hash=fake_str,
git_branch_exists=fake_bool,
git_ls_remote=fake_str,
):
with patch.multiple(
'teuthology.suite.run.Run',
prepare_and_schedule=prepare_and_schedule,
):
main([
'--suite', suite_name,
'--throttle', throttle,
'--machine-type', machine_type,
])
开发者ID:BlaXpirit,项目名称:teuthology,代码行数:31,代码来源:test_init.py
示例5: test_reset_password_mina
def test_reset_password_mina(self):
response_form = self.testapp.get('/profile/reset-password/mina/')
form = response_form.forms['resetpasswordninview-form']
form['email_or_username'].value = '[email protected]'
response = form.submit('reset')
self.assertEqual(response.status, '302 Found')
self.db.reset_passwords.remove()
form['email_or_username'].value = '[email protected]'
from eduiddashboard.msgrelay import MsgRelay
with patch.multiple(MsgRelay, nin_validator=return_true, nin_reachable=return_true,
nin_reset_password=return_true):
response = form.submit('reset')
self.assertEqual(response.status, '302 Found')
self.db.reset_passwords.remove()
form['email_or_username'].value = '0701234567'
with patch.multiple(MsgRelay, nin_validator=return_true, nin_reachable=return_true,
nin_reset_password=return_true):
response = form.submit('reset')
self.assertEqual(response.status, '302 Found')
reset_passwords_after = list(self.db.reset_passwords.find())
self.assertEqual(len(reset_passwords_after), 1)
form['email_or_username'].value = '[email protected]'
response = form.submit('reset')
self.assertIn('Valid input formats are:', response.body)
开发者ID:enriquepablo,项目名称:eduid-dashboard,代码行数:29,代码来源:test_views_password.py
示例6: setUp
def setUp(self):
# Clear the queue
while True:
try:
self.queue.get(block=False)
except Empty:
break
self.server.data_version = 0
# Logger patching
self.tmp_dir = mkdtemp()
logger_patcher = patch.multiple('virtwho.log.Logger', _log_dir=self.tmp_dir,
_stream_handler=None, _queue_logger=None)
logger_patcher.start()
self.addCleanup(logger_patcher.stop)
self.addCleanup(rmtree, self.tmp_dir)
log_patcher = patch.multiple('virtwho.log', DEFAULT_LOG_DIR=self.tmp_dir)
log_patcher.start()
self.addCleanup(log_patcher.stop)
rhsm_log_patcher = patch('rhsm.connection.log')
rhsm_log_patcher.start()
self.addCleanup(rhsm_log_patcher.stop)
# Reduce minimum send interval to allow for faster test completion
minimum_patcher = patch('virtwho.config.MinimumSendInterval', 2)
minimum_patcher.start()
self.addCleanup(minimum_patcher.stop)
# Mock PIDFILE (so we can run tests as an unprivledged user)
pid_file_name = self.tmp_dir + 'virt-who.pid'
pid_file_patcher = patch('virtwho.main.PIDFILE', pid_file_name)
pid_file_patcher.start()
self.addCleanup(pid_file_patcher.stop)
开发者ID:candlepin,项目名称:virt-who,代码行数:35,代码来源:virtwhotest.py
示例7: test_get_glottolog_data_download
def test_get_glottolog_data_download(self):
data_dir = os.path.join(self.tmp.as_posix(), 'data')
class URLopener(object):
def retrieve(self, url, fname):
with io.open(fname, 'w', encoding='utf8') as fp:
fp.write('(B [abcd1234],C [abcd1234])A [abcd1234];')
class URLopenerError(object):
def retrieve(self, url, fname):
raise IOError()
with patch.multiple(
'beastling.configuration',
user_data_dir=Mock(return_value=data_dir),
URLopener=URLopenerError,
):
with self.assertRaises(ValueError):
get_glottolog_data('newick', '2.5')
with patch.multiple(
'beastling.configuration',
user_data_dir=Mock(return_value=data_dir),
URLopener=URLopener,
):
assert get_glottolog_data('newick', '2.5')
开发者ID:Anaphory,项目名称:BEASTling,代码行数:26,代码来源:configuration_tests.py
示例8: test_git_update
def test_git_update(rmtree_mock):
g = git.GitRepo('.', 'https://example.com')
with patch.multiple(g, clone=DEFAULT, path=DEFAULT,
diff=DEFAULT, pull=DEFAULT) as git_mock:
git_mock['path'].is_dir.return_value = False
g.update()
assert git_mock['clone'].called
git_mock['pull'].assert_not_called()
rmtree_mock.reset_mock()
with patch.multiple(g, clone=DEFAULT, path=DEFAULT,
diff=DEFAULT, pull=DEFAULT) as git_mock:
git_mock['path'].is_dir.return_value = True
git_mock['path'].joinpath().is_dir.return_value = False
g.update()
rmtree_mock.assert_called_with(g.path_str, ignore_errors=True)
assert git_mock['clone'].called
git_mock['pull'].assert_not_called()
rmtree_mock.reset_mock()
with patch.multiple(g, clone=DEFAULT, path=DEFAULT,
diff=DEFAULT, pull=DEFAULT) as git_mock:
git_mock['path'].is_dir.return_value = True
git_mock['path'].joinpath().is_dir.return_value = True
val = g.update()
rmtree_mock.assert_not_called()
git_mock['clone'].assert_not_called()
assert git_mock['pull'].called
assert val == git_mock['pull'].return_value
开发者ID:Porkepix,项目名称:bedrock,代码行数:29,代码来源:test_git.py
示例9: test_run_error
def test_run_error(self):
self.cls.reactor = Mock(spec_set=reactor)
with patch.multiple(
pbm,
logger=DEFAULT,
Site=DEFAULT,
LoopingCall=DEFAULT,
VaultRedirectorSite=DEFAULT
) as mod_mocks:
with patch.multiple(
pb,
get_active_node=DEFAULT,
run_reactor=DEFAULT,
listentcp=DEFAULT,
add_update_loop=DEFAULT
) as cls_mocks:
cls_mocks['get_active_node'].return_value = None
with pytest.raises(SystemExit) as excinfo:
self.cls.run()
assert excinfo.value.code == 3
assert mod_mocks['logger'].mock_calls == [
call.critical("ERROR: Could not get active vault node from "
"Consul. Exiting.")
]
assert mod_mocks['VaultRedirectorSite'].mock_calls == []
assert mod_mocks['Site'].mock_calls == []
assert self.cls.reactor.mock_calls == []
assert cls_mocks['run_reactor'].mock_calls == []
assert mod_mocks['LoopingCall'].mock_calls == []
开发者ID:jantman,项目名称:vault-redirector-twisted,代码行数:29,代码来源:test_redirector.py
示例10: test_patch_multiple
def test_patch_multiple(self):
original_foo = Foo
original_f = Foo.f
original_g = Foo.g
patcher1 = patch.multiple(foo_name, f=1, g=2)
patcher2 = patch.multiple(Foo, f=1, g=2)
for patcher in patcher1, patcher2:
patcher.start()
try:
self.assertIs(Foo, original_foo)
self.assertEqual(Foo.f, 1)
self.assertEqual(Foo.g, 2)
finally:
patcher.stop()
self.assertIs(Foo, original_foo)
self.assertEqual(Foo.f, original_f)
self.assertEqual(Foo.g, original_g)
@patch.multiple(foo_name, f=3, g=4)
def test():
self.assertIs(Foo, original_foo)
self.assertEqual(Foo.f, 3)
self.assertEqual(Foo.g, 4)
test()
开发者ID:calvinchengx,项目名称:python-mock,代码行数:29,代码来源:testpatch.py
示例11: test_flavor
def test_flavor(self):
def get_sorted_flavors(self, arch, select):
return [
{
'Name': 'too_small',
'RAM': 2048,
'Disk': 50,
'VCPUs': 1,
},
]
with patch.multiple(
OpenStack,
get_sorted_flavors=get_sorted_flavors,
):
with pytest.raises(NoFlavorException):
hint = { 'ram': 1000, 'disk': 40, 'cpus': 2 }
OpenStack().flavor(hint, 'arch', None)
flavor = 'good-flavor'
def get_sorted_flavors(self, arch, select):
return [
{
'Name': flavor,
'RAM': 2048,
'Disk': 50,
'VCPUs': 2,
},
]
with patch.multiple(
OpenStack,
get_sorted_flavors=get_sorted_flavors,
):
hint = { 'ram': 1000, 'disk': 40, 'cpus': 2 }
assert flavor == OpenStack().flavor(hint, 'arch', None)
开发者ID:ceph,项目名称:teuthology,代码行数:34,代码来源:test_openstack.py
示例12: test_remove_from_persistent
def test_remove_from_persistent(self):
from MMApp.entities.project import ProjectService
existingItem = {"qid" : 1, "pid": "52812ee5a6844e30fc4adcac" , "lid" : "52812fd8a6844e327e4adcac", "model_type": "Gradient Boosted Trees" }
newItem = {"qid" : 1, "pid": "52812ee5a6844e30fc4adcac" , "lid" : "new", "model_type": "Gradient Boosted Trees"}
update_vals = {'s': 0}
# test remove_from_persistent when lb 'lid' key is 'new'
with patch.multiple(ProjectService,
get_leaderboard_item = DEFAULT,
delete_leaderboard_item = DEFAULT,
save_leaderboard_item = DEFAULT ) as mock_new:
# make sure a lid of 'new' returns false
self.assertFalse( self.q.remove_from_persistent(newItem) )
# test remove_from_persistent when lb 's' key is 0
with patch.multiple(ProjectService,
get_leaderboard_item = DEFAULT,
delete_leaderboard_item = DEFAULT,
save_leaderboard_item = DEFAULT ) as mock_zero:
output = self.q.remove_from_persistent(existingItem)
mock_zero['delete_leaderboard_item'].assert_called_once_with(existingItem['lid'])
self.assertTrue(output)
# test remove_from_persistent when lb 's' key is 1
existingItem.update({'s':1})
with patch.multiple(ProjectService,
get_leaderboard_item = DEFAULT,
delete_leaderboard_item = DEFAULT,
save_leaderboard_item = DEFAULT ) as mock_one:
output = self.q.remove_from_persistent(existingItem)
mock_one['save_leaderboard_item'].assert_called_once_with(existingItem['lid'],update_vals)
self.assertTrue(output)
开发者ID:tkincaid,项目名称:tkincaid.github.com,代码行数:34,代码来源:test_jobqueue.py
示例13: test_list_multipath
def test_list_multipath(self):
#
# multipath data partition
#
if platform.system() == "FreeBSD":
return
partition_uuid = "56244cf5-83ef-4984-888a-2d8b8e0e04b2"
disk = "Xda"
partition = "Xda1"
def get_partition_type(dev):
return main.PTYPE['mpath']['osd']['ready']
with patch.multiple(
main,
list_all_partitions=lambda: {disk: [partition]},
get_partition_uuid=lambda dev: partition_uuid,
get_partition_type=get_partition_type,
is_partition=lambda dev: True,
):
expect = [{'path': '/dev/' + disk,
'partitions': [{
'dmcrypt': {},
'fs_type': None,
'is_partition': True,
'mount': None,
'multipath': True,
'path': '/dev/' + partition,
'ptype': main.PTYPE['mpath']['osd']['ready'],
'state': 'unprepared',
'type': 'data',
'uuid': partition_uuid,
}]}]
assert expect == main.list_devices()
#
# multipath journal partition
#
journal_partition_uuid = "2cc40457-259e-4542-b029-785c7cc37871"
def get_partition_type(dev):
return main.PTYPE['mpath']['journal']['ready']
with patch.multiple(
main,
list_all_partitions=lambda: {disk: [partition]},
get_partition_uuid=lambda dev: journal_partition_uuid,
get_partition_type=get_partition_type,
is_partition=lambda dev: True,
):
expect = [{'path': '/dev/' + disk,
'partitions': [{
'dmcrypt': {},
'is_partition': True,
'multipath': True,
'path': '/dev/' + partition,
'ptype': main.PTYPE['mpath']['journal']['ready'],
'type': 'journal',
'uuid': journal_partition_uuid,
}]}]
assert expect == main.list_devices()
开发者ID:tchaikov,项目名称:ceph,代码行数:59,代码来源:test_main.py
示例14: patch_requests
def patch_requests(mapping=None, allowed_domains=None, allowed_methods=None): # pylint: disable=too-complex
"""
mapping is a dict of str => data
so that "toto" => {"response" => {"success" : 1}, "json" => True/False} means that
any url called with *toto* will return {"success" : 1}
json part is optional
allowed_domains can be used in place of a mapping if you don't care about specifying specific return values
but is required so as to ensure that you are only patching the specific domains that your test expects to hit.
allowed_methods limits the methods that can be called on requests
"""
if mapping is None:
if allowed_domains is None:
raise ValueError('patch_requests(): you must specify a mapping or a list of allowed_domains')
mapping = {domain: {} for domain in allowed_domains}
def _request_response_from_query(_, url, **kwargs): # pylint: disable=C0111,W0613
return _response(url)
def _other_response_from_query(url, **kwargs): # pylint: disable=C0111,W0613
return _response(url)
def _response(url):
"""
If the requested URL is found in the mapping, returns the mocked response as configured
"""
logging.debug("mocking %s", url)
for (token, config) in mapping.iteritems():
if token in url:
resp = requests.Response()
resp.url = config.get('url', url)
resp.status_code = config.get('http_code', 200)
if config.get("json", True) and 'response' in config:
resp._content = json.dumps(config["response"]) # pylint: disable=W0212
elif config.get("stream", False):
resp.raw = MagicMock(
stream=MagicMock(return_value=config["response"])
)
else:
# str: Requests uses str as bytes internally, at least on Python 2
resp._content = str(config.get("response", '')) # pylint: disable=W0212
if config.get('headers'):
resp.headers = config.get('headers')
return resp
raise Exception("Requests mock called with unexpected URL, nothing in the mapping for %s" % url)
if allowed_methods is None:
allowed_methods = ['get', 'post', 'put', 'head', 'patch', 'options', 'delete']
methods_map = {method: MagicMock(side_effect=_other_response_from_query) for method in allowed_methods}
methods_map['request'] = MagicMock(side_effect=_request_response_from_query)
with patch.multiple('requests', **methods_map):
with patch.multiple('requests.Session', **methods_map):
yield {k: getattr(requests, k) for k in methods_map}
开发者ID:Work4Labs,项目名称:django-short-urls,代码行数:59,代码来源:mock_requests.py
示例15: testDownload2
def testDownload2(self):
from clld.web.adapters.download import CsvDump, N3Dump, RdfXmlDump
from clld.web.adapters.cldf import CldfDownload
tmp = mktemp()
class Path(MagicMock, UnicodeMixin):
@property
def stem(self):
return 'a'
@property
def parent(self):
return Mock(exists=Mock(return_value=False))
def open(self, mode):
return open(tmp, mode)
with patch.multiple(
'clld.web.adapters.cldf',
ZipFile=MagicMock(),
Path=MagicMock(return_value=Path()),
move=Mock(),
remove=Mock(),
):
with patch(
'clld.web.adapters.download.Path',
new=MagicMock(return_value=Path()),
):
dl = CldfDownload(Dataset, 'clld')
dl.create(self.env['request'], verbose=False)
with patch.multiple(
'clld.web.adapters.download',
ZipFile=MagicMock(),
Path=MagicMock(return_value=Path()),
move=Mock(),
remove=Mock(),
):
dl = CsvDump(Language, 'clld')
dl.create(self.env['request'], verbose=False)
dl.create(self.env['request'], filename='name.n3', verbose=False)
dl = N3Dump(Language, 'clld')
dl.create(self.env['request'], verbose=False)
if os.path.exists(tmp):
os.remove(tmp)
else: # pragma: no cover
raise ValueError
dl = RdfXmlDump(Language, 'clld')
dl.create(self.env['request'], verbose=False)
with closing(gzip.open(tmp, 'rb')) as fp:
assert et.fromstring(fp.read())
if os.path.exists(tmp):
os.remove(tmp)
else: # pragma: no cover
raise ValueError
开发者ID:cevmartinez,项目名称:clld,代码行数:58,代码来源:test_web_adapters_download.py
示例16: test_stale_openstack_volumes
def test_stale_openstack_volumes(self):
ctx = Mock()
ctx.teuthology_config = config
ctx.dry_run = False
now = datetime.datetime.strftime(datetime.datetime.now(),
"%Y-%m-%dT%H:%M:%S.000000")
id = '4bee3af9-febb-40c1-a17e-ff63edb415c5'
name = 'target1-0'
volume_list = json.loads(
'[{'
' "ID": "' + id + '"'
'}]'
)
#
# A volume created a second ago is left untouched
#
volume_show = (
'['
' {"Field": "id", "Value": "' + id + '"},'
' {"Field": "created_at", "Value": "' + now + '"},'
' {"Field": "display_name", "Value": "' + name + '"}'
']'
)
def sh(cmd):
if 'volume show' in cmd:
return volume_show
with patch.multiple(
nuke,
sh=sh,
openstack_delete_volume=DEFAULT,
) as m:
nuke.stale_openstack_volumes(ctx, volume_list)
m['openstack_delete_volume'].assert_not_called()
#
# A volume created long ago is destroyed
#
ancient = "2000-11-02T15:43:12.000000"
volume_show = (
'['
' {"Field": "id", "Value": "' + id + '"},'
' {"Field": "created_at", "Value": "' + ancient + '"},'
' {"Field": "display_name", "Value": "' + name + '"}'
']'
)
def sh(cmd):
if 'volume show' in cmd:
return volume_show
with patch.multiple(
nuke,
sh=sh,
openstack_delete_volume=DEFAULT,
) as m:
nuke.stale_openstack_volumes(ctx, volume_list)
m['openstack_delete_volume'].assert_called_with(id)
开发者ID:charpty,项目名称:teuthology,代码行数:57,代码来源:test_nuke.py
示例17: test_exists
def test_exists(self):
with patch.multiple(misc, sh=lambda cmd: self.teuthology_instance):
o = OpenStackInstance("NAME")
assert o.exists()
def sh_raises(cmd):
raise subprocess.CalledProcessError("FAIL", "BAD")
with patch.multiple(misc, sh=sh_raises):
o = OpenStackInstance("NAME")
assert not o.exists()
开发者ID:charpty,项目名称:teuthology,代码行数:11,代码来源:test_openstack.py
示例18: test_patch_multiple_create
def test_patch_multiple_create(self):
patcher = patch.multiple(Foo, blam='blam')
self.assertRaises(AttributeError, patcher.start)
patcher = patch.multiple(Foo, blam='blam', create=True)
patcher.start()
try:
self.assertEqual(Foo.blam, 'blam')
finally:
patcher.stop()
self.assertFalse(hasattr(Foo, 'blam'))
开发者ID:calvinchengx,项目名称:python-mock,代码行数:12,代码来源:testpatch.py
示例19: test_create_abstract_method_method
def test_create_abstract_method_method(self):
mocked_path = MagicMock()
mocked_git = MagicMock()
with patch.multiple('pyolite.managers.manager',
Path=MagicMock(return_value=mocked_path),
Git=MagicMock(return_value=mocked_git)):
with patch.multiple('pyolite.managers.manager.Manager',
__abstractmethods__=set()):
manager = Manager('/path/to/admin/repo')
manager.create('entity')
开发者ID:Codevolve,项目名称:pyolite,代码行数:12,代码来源:test_manager.py
示例20: test_if_admin_repository_is_not_dir_it_should_raise_ValueError
def test_if_admin_repository_is_not_dir_it_should_raise_ValueError():
mocked_path = MagicMock()
mocked_git = MagicMock()
mocked_path.isdir.return_value = False
with patch.multiple('pyolite.managers.manager',
Path=MagicMock(return_value=mocked_path),
Git=MagicMock(return_value=mocked_git)):
with patch.multiple('pyolite.managers.manager.Manager',
__abstractmethods__=set()):
with pytest.raises(ValueError):
Manager('/path/to/repo')
开发者ID:PressLabs,项目名称:pyolite,代码行数:13,代码来源:test_manager.py
注:本文中的mock.patch.multiple函数示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论