本文整理汇总了Python中utils.print_paragraph函数的典型用法代码示例。如果您正苦于以下问题:Python print_paragraph函数的具体用法?Python print_paragraph怎么用?Python print_paragraph使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了print_paragraph函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Python代码示例。
示例1: warn_if_hostname_conflict
def warn_if_hostname_conflict(ip):
"""
Prints a warning message if it seems like an existing host is already running
calico using this hostname.
:param ip: User-provided IP address to start this node with.
:return: Nothing
"""
# If there's already a calico-node container on this host, they're probably
# just re-running node to update one of the ip addresses, so skip..
try:
current_ipv4, _ = client.get_host_bgp_ips(hostname)
except KeyError:
# No other machine has registered configuration under this hostname.
# This must be a new host with a unique hostname, which is the
# expected behavior.
pass
else:
if current_ipv4 != "" and current_ipv4 != ip:
hostname_warning = "WARNING: Hostname '%s' is already in use " \
"with IP address %s. Calico requires each " \
"compute host to have a unique hostname. " \
"If this is your first time running " \
"'calicoctl node' on this host, ensure " \
"that another host is not already using the " \
"same hostname." % (hostname, ip)
try:
if not docker_client.containers(filters={'name': 'calico-node'}):
# Calico-node isn't running on this host.
# There may be another host using this hostname.
print_paragraph(hostname_warning)
except IOError:
# Couldn't connect to docker to confirm calico-node is running.
print_paragraph(hostname_warning)
开发者ID:ajaybhatnagar,项目名称:calico-docker,代码行数:34,代码来源:node.py
示例2: _translate_profile_for_datastore
def _translate_profile_for_datastore(self):
"""
Translate the profile for updating in the datastore. This also checks
the updated tags reference real Docker networks when the profile is
for a Docker network.
:return: The translated profile.
"""
# If this is not a Docker network profile then just return the profile
# unchanged.
if not self.is_docker_network_profile():
return self.profile
# This is a Docker network profile, so translate from names to IDs.
try:
profile = self._translate_profile(self.profile,
self._get_id_from_name)
except NoDockerNetwork as e:
# A tag in the profile does not reference a valid Docker network.
print_paragraph("You are referencing a Docker network (%s) that "
"does not exist. Create the network first and "
"then update this profile rule to reference "
"it." % e.name)
sys.exit(1)
else:
return profile
开发者ID:alexbrand,项目名称:calico-containers,代码行数:26,代码来源:profile.py
示例3: _assign_host_tunnel_addr
def _assign_host_tunnel_addr(ipip_pools):
"""
Claims an IPIP-enabled IP address from the first pool with some
space.
Stores the result in the host's config as its tunnel address.
Exits on failure.
:param ipip_pools: List of IPPools to search for an address.
"""
for ipip_pool in ipip_pools:
v4_addrs, _ = client.auto_assign_ips(
num_v4=1, num_v6=0,
handle_id=None,
attributes={},
pool=(ipip_pool, None),
host=hostname
)
if v4_addrs:
# Successfully allocated an address. Unpack the list.
[ip_addr] = v4_addrs
break
else:
# Failed to allocate an address, the pools must be full.
print_paragraph(
"Failed to allocate an IP address from an IPIP-enabled pool "
"for the host's IPIP tunnel device. Pools are likely "
"exhausted."
)
sys.exit(1)
# If we get here, we've allocated a new IPIP-enabled address,
# Store it in etcd so that Felix will pick it up.
client.set_per_host_config(hostname, "IpInIpTunnelAddr",
str(ip_addr))
开发者ID:Ma233,项目名称:calico-containers,代码行数:34,代码来源:node.py
示例4: warn_if_hostname_conflict
def warn_if_hostname_conflict(ip):
"""
Prints a warning message if it seems like an existing host is already running
calico using this hostname.
:param ip: User-provided IP address to start this node with.
:return: Nothing
"""
# If there's already a calico-node container on this host, they're probably
# just re-running node to update one of the ip addresses, so skip..
if len(docker_client.containers(filters={'name': 'calico-node'})) == 0:
# Otherwise, check if another host with the same hostname
# is already configured
try:
current_ipv4, _ = client.get_host_bgp_ips(hostname)
except KeyError:
# No other machine has registered configuration under this hostname.
# This must be a new host with a unique hostname, which is the
# expected behavior.
pass
else:
if current_ipv4 != "" and current_ipv4 != ip:
print_paragraph("WARNING: Hostname '%s' is already in use "
"with IP address %s. Calico requires each compute host to "
"have a unique hostname. If this is your first time "
"running 'calicoctl node' on this host, ensure that " \
"another host is not already using the " \
"same hostname." % (hostname, ip))
开发者ID:kriss9,项目名称:calico-docker,代码行数:28,代码来源:node.py
示例5: endpoint_profile_show
def endpoint_profile_show(hostname, orchestrator_id, workload_id, endpoint_id):
"""
List the profiles assigned to a particular endpoint.
:param hostname: The hostname.
:param orchestrator_id: The orchestrator ID.
:param workload_id: The workload ID.
:param endpoint_id: The endpoint ID.
:return: None
"""
try:
endpoint = client.get_endpoint(hostname=hostname,
orchestrator_id=orchestrator_id,
workload_id=workload_id,
endpoint_id=endpoint_id)
except MultipleEndpointsMatch:
print "Failed to list profiles in endpoint.\n"
print_paragraph("More than 1 endpoint matches the provided "
"criteria. Please provide additional parameters to "
"refine the search.")
sys.exit(1)
except KeyError:
print "Failed to list profiles in endpoint.\n"
print_paragraph("Endpoint %s is unknown to Calico.\n" % endpoint_id)
sys.exit(1)
if endpoint.profile_ids:
x = PrettyTable(["Name"], sortby="Name")
for name in endpoint.profile_ids:
x.add_row([name])
print str(x) + "\n"
else:
print "Endpoint has no profiles associated with it."
开发者ID:ninefive,项目名称:calico-docker,代码行数:34,代码来源:endpoint.py
示例6: get_ip_and_pool
def get_ip_and_pool(ip):
if ip.lower() in ("ipv4", "ipv6"):
if '4' in ip:
result = assign_any(1, 0)
ip = result[0][0]
else:
result = assign_any(0, 1)
ip = result[1][0]
pool = get_pool_or_exit(ip)
elif ip is not None and '/' in ip:
pool = IPPool(ip)
if IPNetwork(ip).version == 4:
result = assign_any(1, 0, pool=(pool, None))
ip = result[0][0]
else:
result = assign_any(0, 1, pool=(None, pool))
ip = result[1][0]
else:
# Check the IP is in the allocation pool. If it isn't, BIRD won't
# export it.
ip = IPAddress(ip)
pool = get_pool_or_exit(ip)
# Assign the IP
try:
client.assign_ip(ip, None, {})
except AlreadyAssignedError:
print_paragraph("IP address is already assigned in pool "
"%s." % pool)
sys.exit(1)
return (ip, pool)
开发者ID:xdongp,项目名称:calico-docker,代码行数:32,代码来源:container.py
示例7: validate_arguments
def validate_arguments(arguments):
"""
Validate argument values:
<PROFILES>
Arguments not validated:
<HOSTNAME>
<ORCHESTRATOR_ID>
<WORKLOAD_ID>
<ENDPOINT_ID>
:param arguments: Docopt processed arguments
"""
# Validate Profiles
profile_ok = True
profiles = arguments.get("<PROFILES>")
if profiles is not None:
for profile in profiles:
profile_ok = validate_characters(profile)
if not profile_ok:
print_paragraph("Profile names must be < 40 character long and can "
"only contain numbers, letters, dots, dashes and "
"underscores.")
sys.exit(1)
开发者ID:ninefive,项目名称:calico-docker,代码行数:25,代码来源:endpoint.py
示例8: print_container_not_in_calico_msg
def print_container_not_in_calico_msg(container_name):
"""
Display message indicating that the supplied container is not known to
Calico.
:param container_name: The container name.
:return: None.
"""
print_paragraph("Container %s is unknown to Calico." % container_name)
print_paragraph("Use `calicoctl container add` to add the container " "to the Calico network.")
开发者ID:webwurst,项目名称:calico-docker,代码行数:9,代码来源:container.py
示例9: upload_temp_diags
def upload_temp_diags(diags_path):
# TODO: Rewrite into httplib
print_paragraph("Uploading file. Available for 14 days from the URL "
"printed when the upload completes")
curl_cmd = ["curl", "--upload-file", diags_path,
os.path.join("https://transfer.sh",
os.path.basename(diags_path))]
curl_process = subprocess.Popen(curl_cmd)
curl_process.communicate()
curl_process.wait()
print("Done")
开发者ID:Zogg,项目名称:calico-docker,代码行数:11,代码来源:diags.py
示例10: get_ip_and_pool
def get_ip_and_pool(ip_or_pool):
"""
Return the IP address and associated pool to use when creating a container.
:param ip_or_pool: (string) The requested IP address, pool CIDR, or
special values "ipv4" and "ipv6". When an IP address is specified, that
IP address is used. When a pool CIDR is specified, an IP address is
allocated from that pool. IF either "ipv6" or "ipv6" are specified, then
an IP address is allocated from an arbitrary IPv4 or IPv6 pool
respectively.
:return: A tuple of (IPAddress, IPPool)
"""
if ip_or_pool.lower() in ("ipv4", "ipv6"):
# Requested to auto-assign an IP address
if ip_or_pool[-1] == '4':
result = assign_any(1, 0)
ip = result[0][0]
else:
result = assign_any(0, 1)
ip = result[1][0]
# We can't get the pool until we have the IP address. If we fail to
# get the pool (very small timing window if another client deletes the
# pool) we must release the IP.
try:
pool = get_pool_or_exit(ip)
except SystemExit:
client.release_ips({ip})
raise
elif ip_or_pool is not None and '/' in ip_or_pool:
# Requested to assign an IP address from a specified pool.
cidr = IPNetwork(ip_or_pool)
pool = get_pool_by_cidr_or_exit(cidr)
if cidr.version == 4:
result = assign_any(1, 0, pool=(pool, None))
ip = result[0][0]
else:
result = assign_any(0, 1, pool=(None, pool))
ip = result[1][0]
else:
# Requested a specific IP address to use.
ip = IPAddress(ip_or_pool)
pool = get_pool_or_exit(ip)
# Assign the IP
try:
client.assign_ip(ip, None, {})
except AlreadyAssignedError:
print_paragraph("IP address is already assigned in pool "
"%s." % pool)
sys.exit(1)
return (ip, pool)
开发者ID:MikeSpreitzer,项目名称:calico-containers,代码行数:53,代码来源:container.py
示例11: container
def container(arguments):
"""
Main dispatcher for container commands. Calls the corresponding helper
function.
:param arguments: A dictionary of arguments already processed through
this file's docstring with docopt
:return: None
"""
validate_arguments(arguments)
ip_version = get_container_ipv_from_arguments(arguments)
try:
if arguments.get("endpoint-id"):
container_endpoint_id_show(arguments.get("<CONTAINER>"))
elif arguments.get("ip"):
if arguments.get("add"):
container_ip_add(arguments.get("<CONTAINER>"),
arguments.get("<IP>"),
ip_version,
arguments.get("--interface"))
elif arguments.get("remove"):
container_ip_remove(arguments.get("<CONTAINER>"),
arguments.get("<IP>"),
ip_version,
arguments.get("--interface"))
else:
if arguments.get("add"):
container_add(arguments.get("<CONTAINER>"),
arguments.get("<IP>"),
arguments.get("--interface"))
if arguments.get("remove"):
container_remove(arguments.get("<CONTAINER>"))
else:
if arguments.get("add"):
container_add(arguments.get("<CONTAINER>"),
arguments.get("<IP>"),
arguments.get("--interface"))
if arguments.get("remove"):
container_remove(arguments.get("<CONTAINER>"))
except ConnectionError as e:
# We hit a "Permission denied error (13) if the docker daemon
# does not have sudo permissions
if permission_denied_error(e):
print_paragraph("Unable to run command. Re-run the "
"command as root, or configure the docker "
"group to run with sudo privileges (see docker "
"installation guide for details).")
else:
print_paragraph("Unable to run docker commands. Is the docker "
"daemon running?")
sys.exit(1)
开发者ID:kriss9,项目名称:calico-docker,代码行数:52,代码来源:container.py
示例12: endpoint_profile_append
def endpoint_profile_append(hostname, orchestrator_id, workload_id,
endpoint_id, profile_names):
"""
Append a list of profiles to the container endpoint profile list.
The hostname, orchestrator_id, workload_id, and endpoint_id are all
optional parameters used to determine which endpoint is being targeted.
The more parameters used, the faster the endpoint query will be. The
query must be specific enough to match a single endpoint or it will fail.
The profile list may not contain duplicate entries, invalid profile names,
or profiles that are already in the containers list.
If no profile is specified, nothing happens.
:param hostname: The host that the targeted endpoint resides on.
:param orchestrator_id: The orchestrator that created the targeted endpoint.
:param workload_id: The ID of workload which created the targeted endpoint.
:param endpoint_id: The endpoint ID of the targeted endpoint.
:param profile_names: The list of profile names to add to the targeted
endpoint.
:return: None
"""
# Validate the profile list.
validate_profile_list(profile_names)
if not profile_names:
print_paragraph("No profile specified.")
else:
try:
client.append_profiles_to_endpoint(profile_names,
hostname=hostname,
orchestrator_id=orchestrator_id,
workload_id=workload_id,
endpoint_id=endpoint_id)
print_paragraph("Profile(s) %s appended." %
(", ".join(profile_names)))
except KeyError:
print "Failed to append profiles to endpoint.\n"
print_paragraph("Endpoint %s is unknown to Calico.\n" % endpoint_id)
sys.exit(1)
except ProfileAlreadyInEndpoint, e:
print_paragraph("Profile %s is already in endpoint "
"profile list" % e.profile_name)
except MultipleEndpointsMatch:
print_paragraph("More than 1 endpoint matches the provided criteria. "
"Please provide additional parameters to refine the "
"search.")
sys.exit(1)
开发者ID:ninefive,项目名称:calico-docker,代码行数:49,代码来源:endpoint.py
示例13: parse_ports
def parse_ports(ports_str):
"""
Parse a string representing a port list into a list of ports and
port ranges.
Returns None if the input is None.
:param StringTypes|NoneType ports_str: string representing a port list.
Examples: "1" "1,2,3" "1:3" "1,2,3:4"
:return list[StringTypes|int]|NoneType: list of ports or None.
"""
if ports_str is None:
return None
# We allow ranges with : or - but convert to :, which is what the data
# model uses.
if not re.match(r'^(\d+([:-]\d+)?)(,\d+([:-]\d+)?)*$',
ports_str):
print_paragraph("Ports: %r are invalid; expecting a comma-separated "
"list of ports and port ranges." % ports_str)
sys.exit(1)
splits = ports_str.split(",")
parsed_ports = []
for split in splits:
m = re.match(r'^(\d+)[:-](\d+)$', split)
if m:
# Got a range, canonicalise it.
min = int(m.group(1))
max = int(m.group(2))
if min > max:
print "Port range minimum (%s) > maximum (%s)." % (min, max)
sys.exit(1)
if not (0 <= min <= 65535):
print "Port minimum (%s) out-of-range." % min
sys.exit(1)
if not (0 <= max <= 65535):
print "Port maximum (%s) out-of-range." % max
sys.exit(1)
parsed_ports.append("%s:%s" % (min, max))
else:
# Should be a lone port, convert to int.
port = int(split)
if not (0 <= port <= 65535):
print "Port (%s) out-of-range." % min
sys.exit(1)
parsed_ports.append(port)
return parsed_ports
开发者ID:xuzhaokui,项目名称:calico-docker,代码行数:46,代码来源:profile.py
示例14: error_if_bgp_ip_conflict
def error_if_bgp_ip_conflict(ip, ip6):
"""
Prints an error message and exits if either of the IPv4 or IPv6 addresses
is already in use by another calico BGP host.
:param ip: User-provided IPv4 address to start this node with.
:param ip6: User-provided IPv6 address to start this node with.
:return: Nothing
"""
ip_list = []
if ip:
ip_list.append(ip)
if ip6:
ip_list.append(ip6)
try:
# Get hostname of host that already uses the given IP, if it exists
ip_conflicts = client.get_hostnames_from_ips(ip_list)
except KeyError:
# No hosts have been configured in etcd, so there cannot be a conflict
return
if ip_conflicts.keys():
ip_error = (
"ERROR: IP address %s is already in use by host %s. "
"Calico requires each compute host to have a unique IP. "
"If this is your first time running 'calicoctl node' on "
"this host, ensure that another host is not already using "
"the same IP address."
)
try:
if ip_conflicts[ip] != hostname:
ip_error = ip_error % (ip, str(ip_conflicts[ip]))
print_paragraph(ip_error)
sys.exit(1)
except KeyError:
# IP address was not found in ip-host dictionary
pass
try:
if ip6 and ip_conflicts[ip6] != hostname:
ip_error = ip_error % (ip6, str(ip_conflicts[ip6]))
print_paragraph(ip_error)
sys.exit(1)
except KeyError:
# IP address was not found in ip-host dictionary
pass
开发者ID:bfosberry,项目名称:calico-containers,代码行数:45,代码来源:node.py
示例15: ip_pool_remove
def ip_pool_remove(cidrs, version):
"""
Remove the given CIDRs from the IP address allocation pool.
:param cidrs: The pools to remove in CIDR format, e.g. 192.168.0.0/16
:param version: 4 or 6
:return: None
"""
for cidr in cidrs:
# Get the existing IP Pool so that we can disable it,
try:
pool = client.get_ip_pool_config(version, IPNetwork(cidr))
except KeyError:
print "%s is not a configured pool." % cidr
sys.exit(1)
try:
# Disable the pool to prevent any further allocation blocks from
# being assigned from the pool. Existing allocation blocks will
# still exist and may be allocated from until affinity is removed
# from the blocks.
print "Disabling IP Pool"
pool.disabled = True
client.set_ip_pool_config(version, pool)
# Remove affinity from the allocation blocks for the pool. This
# will prevent these blocks from being used for auto-allocations.
# We pause before removing the affinities and the pool to allow
# any in-progress IP allocations to complete - there is a known
# timing window here, which can be closed but at the expense of
# additional etcd reads for each affine block allocation - since
# deletion of a pool is not common, it is simplest to pause in
# between disabling and deleting the pool.
print "Removing IPAM configuration for pool"
time.sleep(3)
client.release_pool_affinities(pool)
client.remove_ip_pool(version, pool.cidr)
print "Deleted IP Pool"
except (KeyError, HostAffinityClaimedError):
print_paragraph("Conflicting modifications have been made to the "
"IPAM configuration for this pool. Please retry "
"the command.")
sys.exit(1)
开发者ID:Virtustream-OSS,项目名称:calico-containers,代码行数:44,代码来源:pool.py
示例16: _find_or_pull_node_image
def _find_or_pull_node_image(image_name):
"""
Check if Docker has a cached copy of an image, and if not, attempt to pull
it.
:param image_name: The full name of the image.
:return: None.
"""
try:
_ = docker_client.inspect_image(image_name)
except docker.errors.APIError as err:
if err.response.status_code == 404:
# TODO: Display proper status bar
print_paragraph("Pulling Docker image %s" % image_name)
try:
# Pull the image and then verify that it was succesfully
# pulled (the pull doesn't raise an exception on failure).
docker_client.pull(image_name)
docker_client.inspect_image(image_name)
except docker.errors.APIError:
# Unable to download the Docker image.
print_paragraph("ERROR: Unable to download Docker image.")
print_paragraph("Please verify that you have network "
"connectivity to DockerHub and that, if you "
"explicitly specified which calico/node image "
"to use, the image name is correct.")
sys.exit(1)
开发者ID:ajaybhatnagar,项目名称:calico-docker,代码行数:28,代码来源:node.py
示例17: node_stop
def node_stop(force):
"""
Stop the Calico node. This stops the containers (calico/node and
calico/node-libnetwork) that are started by calicoctl node.
"""
endpoints = len(client.get_endpoints(hostname=hostname))
if endpoints:
if not force:
print_paragraph("Current host has active endpoints so can't be "
"stopped. Force with --force")
print_paragraph("Note that stopping the node while there are "
"active endpoints may make it difficult to clean "
"up the endpoints: for example, Docker containers "
"networked using libnetwork with Calico will not "
"invoke network cleanup during the normal "
"container lifecycle.")
sys.exit(1)
else:
print_paragraph("Stopping node while host has active endpoints. "
"If this in error, restart the node using the "
"'calicoctl node' command.")
try:
docker_client.stop("calico-node")
except docker.errors.APIError as err:
if err.response.status_code != 404:
raise
try:
docker_client.stop("calico-libnetwork")
except docker.errors.APIError as err:
if err.response.status_code != 404:
raise
print "Node stopped"
开发者ID:ajaybhatnagar,项目名称:calico-docker,代码行数:34,代码来源:node.py
示例18: node_remove
def node_remove(remove_endpoints):
"""
Remove a node from the Calico network.
:param remove_endpoints: Whether the endpoint data should be forcibly
removed.
"""
if _container_running("calico-node") or \
_container_running("calico-libnetwork"):
print_paragraph("The node cannot be removed while it is running. "
"Please run 'calicoctl node stop' to stop the node "
"before removing it.")
sys.exit(1)
endpoints = client.get_endpoints(hostname=hostname)
if endpoints and not remove_endpoints:
print_paragraph("The node has active Calico endpoints so can't be "
"deleted. Force with --remove-endpoints")
print_paragraph("Note that forcible removing the node may leave some "
"workloads in an indeterminate networked state. If "
"this is in error, you may restart the node using the "
"'calicoctl node' command and clean up the workloads "
"in the normal way.")
sys.exit(1)
for endpoint in endpoints:
remove_veth(endpoint.name)
client.remove_host(hostname)
print "Node configuration removed"
开发者ID:ajaybhatnagar,项目名称:calico-docker,代码行数:29,代码来源:node.py
示例19: endpoint_profile_set
def endpoint_profile_set(hostname, orchestrator_id, workload_id,
endpoint_id, profile_names):
"""
Set the complete list of profiles for the container endpoint profile list.
The hostname, orchestrator_id, workload_id, and endpoint_id are all optional
parameters used to determine which endpoint is being targeted.
The more parameters used, the faster the endpoint query will be. The
query must be specific enough to match a single endpoint or it will fail.
The profile list may not contain duplicate entries or invalid profile names.
:param hostname: The host that the targeted endpoint resides on.
:param orchestrator_id: The orchestrator that created the targeted endpoint.
:param workload_id: The ID of workload which created the targeted endpoint.
:param endpoint_id: The endpoint ID of the targeted endpoint.
:param profile_names: The list of profile names to set on the targeted
endpoint.
:return: None
"""
# Validate the profile list.
validate_profile_list(profile_names)
try:
client.set_profiles_on_endpoint(profile_names,
hostname=hostname,
orchestrator_id=orchestrator_id,
workload_id=workload_id,
endpoint_id=endpoint_id)
print_paragraph("Profiles %s set for %s." %
(", ".join(profile_names), endpoint_id))
except KeyError:
print "Failed to set profiles for endpoint.\n"
print_paragraph("Endpoint %s is unknown to Calico.\n" % endpoint_id)
sys.exit(1)
开发者ID:Zogg,项目名称:calico-docker,代码行数:36,代码来源:endpoint.py
示例20: validate_arguments
def validate_arguments(arguments):
"""
Validate argument values:
<IP>
Arguments not validated:
<CONTAINER>
<INTERFACE>
:param arguments: Docopt processed arguments
"""
# Validate IP
requested_ip = arguments.get("<IP>")
if not (requested_ip is None or
validate_ip(requested_ip, 4) or
validate_ip(requested_ip, 6) or
validate_cidr(requested_ip) or
requested_ip.lower() in ('ipv4', 'ipv6')):
print_paragraph("Invalid IP address specified. Argument must be a "
"valid IP or CIDR.")
sys.exit(1)
# Validate POOL
if requested_ip is not None and '/' in requested_ip:
requested_pool = IPNetwork(requested_ip)
try:
client.get_ip_pool_config(requested_pool.version, requested_pool)
except KeyError:
print_paragraph("Invalid CIDR specified for desired pool. "
"No pool found for {0}.".format(requested_pool))
sys.exit(1)
# Validate PROFILE
endpoint.validate_arguments(arguments)
开发者ID:xdongp,项目名称:calico-docker,代码行数:36,代码来源:container.py
注:本文中的utils.print_paragraph函数示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论