本文整理汇总了Python中itsdangerous.TimedSerializer.loads方法的典型用法代码示例。如果您正苦于以下问题:Python TimedSerializer.loads方法的具体用法?Python TimedSerializer.loads怎么用?Python TimedSerializer.loads使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类itsdangerous.TimedSerializer
的用法示例。
在下文中一共展示了TimedSerializer.loads方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: get_payouts
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def get_payouts():
""" Used by remote procedure call to retrieve a list of transactions to
be processed. Transaction information is signed for safety. """
s = TimedSerializer(current_app.config['rpc_signature'])
s.loads(request.data)
payouts = (Payout.query.filter_by(transaction_id=None).
join(Payout.block, aliased=True).filter_by(mature=True))
bonus_payouts = BonusPayout.query.filter_by(transaction_id=None)
pids = [(p.user, p.amount, p.id) for p in payouts]
bids = [(p.user, p.amount, p.id) for p in bonus_payouts]
return s.dumps([pids, bids])
示例2: reset_password
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def reset_password(data=None):
if data is not None and request.method == "GET":
return render_template('reset_password.html', mode='set')
if data is not None and request.method == "POST":
try:
s = TimedSerializer(app.config['SECRET_KEY'])
name = s.loads(urllib.unquote_plus(data.decode('base64')), max_age=1800)
except BadTimeSignature:
return render_template('reset_password.html', errors=['Your link has expired'])
except:
return render_template('reset_password.html', errors=['Your link appears broken, please try again.'])
team = Teams.query.filter_by(name=name).first_or_404()
team.password = bcrypt_sha256.encrypt(request.form['password'].strip())
db.session.commit()
db.session.close()
return redirect(url_for('auth.login'))
if request.method == 'POST':
email = request.form['email'].strip()
team = Teams.query.filter_by(email=email).first()
if not team:
return render_template('reset_password.html', errors=['If that account exists you will receive an email, please check your inbox'])
s = TimedSerializer(app.config['SECRET_KEY'])
token = s.dumps(team.name)
text = """
Did you initiate a password reset?
{0}/{1}
""".format(url_for('auth.reset_password', _external=True), urllib.quote_plus(token.encode('base64')))
utils.sendmail(email, text)
return render_template('reset_password.html', errors=['If that account exists you will receive an email, please check your inbox'])
return render_template('reset_password.html')
示例3: confirm_transactions
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def confirm_transactions():
""" Used as a response from an rpc payout system. This will either reset
the sent status of a list of transactions upon failure on the remote side,
or create a new CoinTransaction object and link it to the transactions to
signify that the transaction has been processed. Both request and response
are signed. """
s = TimedSerializer(current_app.config['rpc_signature'])
data = s.loads(request.data)
# basic checking of input
try:
assert len(data['coin_txid']) == 64
assert isinstance(data['pids'], list)
assert isinstance(data['bids'], list)
for id in data['pids']:
assert isinstance(id, int)
for id in data['bids']:
assert isinstance(id, int)
except AssertionError:
current_app.logger.warn("Invalid data passed to confirm", exc_info=True)
abort(400)
coin_trans = Transaction.create(data['coin_txid'])
db.session.flush()
Payout.query.filter(Payout.id.in_(data['pids'])).update(
{Payout.transaction_id: coin_trans.txid}, synchronize_session=False)
BonusPayout.query.filter(BonusPayout.id.in_(data['bids'])).update(
{BonusPayout.transaction_id: coin_trans.txid}, synchronize_session=False)
db.session.commit()
return s.dumps(True)
示例4: reset_password
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def reset_password(data=None):
if data is not None and request.method == "GET":
return render_template('reset_password.html', mode='set')
if data is not None and request.method == "POST":
try:
s = TimedSerializer(app.config['SECRET_KEY'])
name = s.loads(data.decode('base64'), max_age=1800)
except BadTimeSignature:
return render_template('reset_password.html', errors=['Your link has expired'])
team = Teams.query.filter_by(name=name).first()
team.password = bcrypt_sha256.encrypt(request.form['password'].strip())
db.session.commit()
db.session.close()
return redirect(url_for('auth.login'))
if request.method == 'POST':
email = request.form['email'].strip()
team = Teams.query.filter_by(email=email).first()
if not team:
return render_template('reset_password.html', errors=['Check your email'])
s = TimedSerializer(app.config['SECRET_KEY'])
token = s.dumps(team.name)
text = """
Did you initiate a password reset?
{0}/reset_password/{1}
""".format(app.config['HOST'], token.encode('base64'))
sendmail(email, text)
return render_template('reset_password.html', errors=['Check your email'])
return render_template('reset_password.html')
示例5: get_payouts
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def get_payouts():
""" Used by remote procedure call to retrieve a list of transactions to
be processed. Transaction information is signed for safety. """
s = TimedSerializer(current_app.config['rpc_signature'])
args = s.loads(request.data)
current_app.logger.info("get_payouts being called, args of {}!".format(args))
lock = False
merged = None
if isinstance(args, dict) and args['lock']:
lock = True
if isinstance(args, dict) and args['merged']:
merged = args['merged']
with Benchmark("Fetching payout information"):
pids = [(p.user, p.amount, p.id) for p in Payout.query.filter_by(transaction_id=None, locked=False, merged_type=merged).
join(Payout.block, aliased=True).filter_by(mature=True)]
bids = [(p.user, p.amount, p.id) for p in BonusPayout.query.filter_by(transaction_id=None, locked=False, merged_type=merged).
join(BonusPayout.block, aliased=True).filter_by(mature=True)]
if lock:
if bids:
current_app.logger.info("Locking {} bonus ids at retriever request."
.format(len(bids)))
(BonusPayout.query.filter(BonusPayout.id.in_(p[2] for p in bids))
.update({BonusPayout.locked: True}, synchronize_session=False))
if pids:
current_app.logger.info("Locking {} payout ids at retriever request."
.format(len(pids)))
(Payout.query.filter(Payout.id.in_(p[2] for p in pids))
.update({Payout.locked: True}, synchronize_session=False))
db.session.commit()
return s.dumps([pids, bids, lock])
示例6: get_payouts
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def get_payouts():
""" Used by remote procedure call to retrieve a list of transactions to
be processed. Transaction information is signed for safety. """
s = TimedSerializer(current_app.config['rpc_signature'])
args = s.loads(request.data)
current_app.logger.info("get_payouts being called, args of {}!".format(args))
lock = False
merged = None
if isinstance(args, dict) and args['lock']:
lock = True
if isinstance(args, dict) and args['merged']:
merged = args['merged']
payouts = (Payout.query.filter_by(transaction_id=None, locked=False, merged_type=merged).
join(Payout.block, aliased=True).filter_by(mature=True)).all()
bonus_payouts = (BonusPayout.query.filter_by(transaction_id=None, locked=False, merged_type=merged).
join(BonusPayout.block, aliased=True).filter_by(mature=True)).all()
pids = [(p.user, p.amount, p.id) for p in payouts]
bids = [(p.user, p.amount, p.id) for p in bonus_payouts]
if lock:
current_app.logger.info("Locking pids and bids at retriever request.")
for payout in payouts:
payout.locked = True
for payout in bonus_payouts:
payout.locked = True
db.session.commit()
return s.dumps([pids, bids, lock])
示例7: BaseConsumer
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
class BaseConsumer(object):
def __init__(self, base_url, public_key, private_key):
self.base_url = base_url
self.public_key = public_key
self.signer = TimedSerializer(private_key)
def consume(self, path, data, max_age=None):
if not path.startswith('/'):
raise ValueError("Paths must start with a slash")
signed_data = self.signer.dumps(data)
headers = {
PUBLIC_KEY_HEADER: self.public_key,
'Content-Type': 'application/json',
}
url = self.build_url(path)
body = self.send_request(url, data=signed_data, headers=headers)
return self.handle_response(body, max_age)
def handle_response(self, body, max_age):
return self.signer.loads(body, max_age=max_age)
def send_request(self, url, data, headers):
raise NotImplementedError("Implement send_request on BaseConsumer subclasses")
def raise_for_status(self, status_code, message):
if status_code == 400:
raise BadRequest(message)
elif status_code >= 300:
raise WebserviceError(message)
def build_url(self, path):
path = path.lstrip('/')
return urlparse.urljoin(self.base_url, path)
示例8: reset_password
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def reset_password(data=None):
if data is not None and request.method == "GET":
return render_template("reset_password.html", mode="set")
if data is not None and request.method == "POST":
try:
s = TimedSerializer(app.config["SECRET_KEY"])
name = s.loads(data.decode("base64"), max_age=1800)
except BadTimeSignature:
return render_template("reset_password.html", errors=["Your link has expired"])
team = Teams.query.filter_by(name=name).first()
team.password = bcrypt_sha256.encrypt(request.form["password"].strip())
db.session.commit()
db.session.close()
return redirect(url_for("auth.login"))
if request.method == "POST":
email = request.form["email"].strip()
team = Teams.query.filter_by(email=email).first()
if not team:
return render_template("reset_password.html", errors=["Check your email"])
s = TimedSerializer(app.config["SECRET_KEY"])
token = s.dumps(team.name)
text = """
Did you initiate a password reset?
{0}/reset_password/{1}
""".format(
url_for("auth.reset_password", _external=True), token.encode("base64")
)
sendmail(email, text)
return render_template("reset_password.html", errors=["Check your email"])
return render_template("reset_password.html")
示例9: verify_auth_token
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def verify_auth_token(token, max_age=3600):
s = TimedSerializer(secret_key)
try:
data = s.loads(token, max_age=max_age)
except SignatureExpired:
return None
except BadSignature:
return None
return data
示例10: confirm_transactions
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def confirm_transactions():
""" Used to confirm that a transaction is now complete on the network. """
s = TimedSerializer(current_app.config['rpc_signature'])
data = s.loads(request.data)
# basic checking of input
try:
assert isinstance(data['tids'], list)
except AssertionError:
current_app.logger.warn("Invalid data passed to confirm_transactions",
exc_info=True)
abort(400)
Transaction.query.filter(Transaction.txid.in_(data['tids'])).update(
{Transaction.confirmed: True}, synchronize_session=False)
db.session.commit()
return s.dumps(True)
示例11: get_response
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
def get_response(self, method, signed_data, get_header):
if method != 'POST':
return (405, ['POST'])
public_key = get_header(PUBLIC_KEY_HEADER, None)
if not public_key:
return (400, "No public key")
private_key = self.get_private_key(public_key)
if not private_key:
return (400, "Invalid public key")
signer = TimedSerializer(private_key)
try:
data = signer.loads(signed_data, max_age=self.max_age)
except SignatureExpired:
return (400, "Signature expired")
except BadSignature:
return (400, "Bad Signature")
try:
raw_response_data = self.provide(data)
except:
self.report_exception()
return (400, "Failed to process the request")
response_data = signer.dumps(raw_response_data)
return (200, response_data)
示例12: Auth_webSilvia
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
class Auth_webSilvia(Auth_Base):
def __init__(self, config):
self.signer = TimedSerializer(config['shared_secret'])
super(Auth_webSilvia, self).__init__(config)
# This functions returns which credentials we need to retrieve
# to get all of the requested_attributes
def get_credentials(self, requested_attributes):
credentials_to_request = self.config['always_retrieve']
if '/' in self.config['username_mapping']:
credential, _ = self.config['username_mapping'].split('/', 1)
credentials_to_request.append(credential)
for requested_attribute in requested_attributes:
if requested_attribute in self.config['attribute_mapping'].keys():
if '/' in self.config['attribute_mapping'][requested_attribute]:
credential, _ = self.config['attribute_mapping'][requested_attribute].split('/', 1)
credentials_to_request.append(credential)
credentials_request = {}
for credential_to_request in credentials_to_request:
if credential_to_request in self.config['known_credentials']:
credentials_request[credential_to_request] = self.config['known_credentials'][credential_to_request]
else:
# We do not know the paths for this credential...
logger.error('Credential was mapped to, but could not be found: %s', credential_to_request)
return credentials_request
# Do the actual authentication
# Whatever you do, make sure to pass request.transaction_id either in GET
# or POST in the field 'transaction'.
# The requested_attributes can be used in authentication modules that need
# to know up-front which attributes are going to be requested. Any
# attributes not requested here MAY raise a NotRequestedAttributeError on
# attempt to retrieval, but it's also perfectly valid for the auth module
# to just return the value if it can retrieve it.
# Return True when authentication was successful
# Return False when authentication was cancelled
# Anything else will be returned to Flask as view result
def authenticate(self, login_target, form_url, requested_attributes=[]):
if request.method == 'POST':
# We are returning from webSilvia!
result = request.form['result']
result = self.signer.loads(result)
user = {}
needed_credentials = self.config['required_credentials']
for credential in result['verified']:
if result['verified'][credential]['status'] == 'OK':
if result['verified'][credential]['expiry'] >= time.time():
if credential in needed_credentials:
needed_credentials.remove(credential)
user[credential] = result['verified'][credential]['attributes']
else:
# Attribute no longer valid
logger.info('Credential expired: %s', result['credentials'][credential])
else:
# Attribute status != OK
logger.info('Credential not status=OK: %s', result['credentials'][credential])
if len(needed_credentials) > 0:
return False
self.save_success(user)
return True
else:
# Build the request for webSilvia
websilvia_request = {'protocol': 'request-1',
'return_url': '%s?transaction=%s' % (form_url, request.transaction_id),
'token': request.transaction_id,
'nonce': time.time(),
'to_verify': self.get_credentials(requested_attributes),
'to_issue': {}}
websilvia_request = self.signer.dumps(websilvia_request)
return render_template('webSilvia.html',
request=websilvia_request,
requestor_id=self.config['requestor_id'],
websilvia_url=self.config['websilvia_url'])
def follow_mapping(self, mapping, user):
if '/' not in mapping:
return mapping
else:
credential, attribute = mapping.split('/', 1)
if credential in self._user.keys():
if attribute in self._user[credential]:
return self._user[credential][attribute]
else:
raise NotRequestedAttributeError()
else:
raise NotRequestedAttributeError()
def get_username(self):
if not self.logged_in():
raise UnauthorizedError
return self.follow_mapping(self.config['username_mapping'],
self._user)
#.........这里部分代码省略.........
示例13: SCRPCClient
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
#.........这里部分代码省略.........
self.logger.addHandler(handler)
# don't attach a file handler if path evals false
if self.config['log_path']:
handler = logging.FileHandler(self.config['log_path'])
handler.setFormatter(log_format)
handler.setLevel(getattr(logging, self.config['log_level']))
self.logger.addHandler(handler)
self.serializer = TimedSerializer(self.config['rpc_signature'])
########################################################################
# Helper URL methods
########################################################################
def post(self, url, *args, **kwargs):
if 'data' not in kwargs:
kwargs['data'] = ''
kwargs['data'] = self.serializer.dumps(kwargs['data'])
return self.remote('/rpc/' + url, 'post', *args, **kwargs)
def get(self, url, *args, **kwargs):
return self.remote(url, 'get', *args, **kwargs)
def remote(self, url, method, max_age=None, signed=True, **kwargs):
url = urljoin(self.config['rpc_url'], url)
self.logger.debug("Making request to {}".format(url))
ret = getattr(requests, method)(url, timeout=270, **kwargs)
if ret.status_code != 200:
raise SCRPCException("Non 200 from remote: {}".format(ret.text))
try:
self.logger.debug("Got {} from remote".format(ret.text.encode('utf8')))
if signed:
return self.serializer.loads(ret.text, max_age or self.config['max_age'])
else:
return ret.json()
except BadData:
self.logger.error("Invalid data returned from remote!", exc_info=True)
raise SCRPCException("Invalid signature")
########################################################################
# RPC Client methods
########################################################################
def pull_payouts(self, simulate=False):
""" Gets all the unpaid payouts from the server """
if simulate:
self.logger.info('#'*20 + ' Simulation mode ' + '#'*20)
try:
payouts = self.post(
'get_payouts',
data={'currency': self.config['currency_code']}
)['pids']
except ConnectionError:
self.logger.warn('Unable to connect to SC!', exc_info=True)
return
if not payouts:
self.logger.info("No {} payouts to process.."
.format(self.config['currency_code']))
return
repeat = 0
new = 0
invalid = 0
示例14: RPCClient
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
class RPCClient(object):
def __init__(self, config_path='/config.yml', root_suffix='/../',
max_age=5):
self.root = os.path.abspath(os.path.dirname(__file__) + root_suffix)
self.config = current_app.config
del current_app.logger.handlers[0]
current_app.logger.addHandler(ch)
self.serializer = TimedSerializer(self.config['rpc_signature'])
self.max_age = max_age
def post(self, url, *args, **kwargs):
if 'data' not in kwargs:
kwargs['data'] = ''
kwargs['data'] = self.serializer.dumps(kwargs['data'])
return self.remote(url, 'post', *args, **kwargs)
def get(self, url, *args, **kwargs):
return self.remote(url, 'get', *args, **kwargs)
def remote(self, url, method, max_age=None, **kwargs):
url = urljoin(self.config['rpc_url'], url)
ret = getattr(requests, method)(url, **kwargs)
if ret.status_code != 200:
raise RPCException("Non 200 from remote")
try:
return self.serializer.loads(ret.text, max_age or self.max_age)
except BadData:
raise RPCException("Invalid signature: {}".format(ret.text))
def poke_rpc(self):
try:
coinserv.getinfo()
except JSONRPCException:
raise RPCException("Coinserver not awake")
def proc_trans(self, simulate=False):
self.poke_rpc()
payouts, bonus_payouts = self.post('get_payouts')
pids = [t[2] for t in payouts]
bids = [t[2] for t in bonus_payouts]
logger.info("Recieved {} payouts and {} bonus payouts from the server"
.format(len(pids), len(bids)))
if not len(pids) and not len(bids):
logger.info("No payouts to process..")
return
# builds two dictionaries, one that tracks the total payouts to a user,
# and another that tracks all the payout ids (pids) giving that amount
# to the user
totals = {}
pids = {}
bids = {}
for user, amount, id in payouts:
if user.startswith('D'):
totals.setdefault(user, 0)
totals[user] += amount
pids.setdefault(user, [])
pids[user].append(id)
else:
logger.warn("User {} has been excluded due to invalid address"
.format(user))
for user, amount, id in bonus_payouts:
if user.startswith('D'):
totals.setdefault(user, 0)
totals[user] += amount
bids.setdefault(user, [])
bids[user].append(id)
else:
logger.warn("User {} has been excluded due to invalid address"
.format(user))
# identify the users who meet minimum payout and format for sending
# to rpc
users = {user: amount / float(100000000) for user, amount in totals.iteritems()
if amount > current_app.config['minimum_payout']}
logger.info("Trying to payout a total of {}".format(sum(users.values())))
if len(users) == 0:
logger.info("Nobody has a big enough balance to pay out...")
return
# now we have all the users who we're going to send money. build a list
# of the pids that will be being paid in this transaction
committed_pids = []
for user in users:
committed_pids.extend(pids.get(user, []))
committed_bids = []
for user in users:
committed_bids.extend(bids.get(user, []))
logger.info("Total user payouts")
logger.info(pprint.pformat(users))
logger.info("Total bonus IDs")
logger.info(pprint.pformat(bids))
logger.info("Total payout IDs")
logger.info(pprint.pformat(pids))
#.........这里部分代码省略.........
示例15: RPCClient
# 需要导入模块: from itsdangerous import TimedSerializer [as 别名]
# 或者: from itsdangerous.TimedSerializer import loads [as 别名]
class RPCClient(object):
def __init__(self, config_path='/config.yml', root_suffix='/../',
max_age=5):
self.root = os.path.abspath(os.path.dirname(__file__) + root_suffix)
self.config = current_app.config
del current_app.logger.handlers[0]
current_app.logger.addHandler(ch)
self.serializer = TimedSerializer(self.config['rpc_signature'])
self.max_age = max_age
def post(self, url, *args, **kwargs):
if 'data' not in kwargs:
kwargs['data'] = ''
kwargs['data'] = self.serializer.dumps(kwargs['data'])
return self.remote(url, 'post', *args, **kwargs)
def get(self, url, *args, **kwargs):
return self.remote(url, 'get', *args, **kwargs)
def remote(self, url, method, max_age=None, signed=True, **kwargs):
url = urljoin(self.config['rpc_url'], url)
ret = getattr(requests, method)(url, **kwargs)
if ret.status_code != 200:
raise RPCException("Non 200 from remote: {}".format(ret.text))
try:
logger.debug("Got {} from remote".format(ret.text))
if signed:
return self.serializer.loads(ret.text, max_age or self.max_age)
else:
return ret.json()
except BadData:
raise RPCException("Invalid signature: {}".format(ret.text))
def poke_rpc(self, conn):
try:
conn.getinfo()
except JSONRPCException:
raise RPCException("Coinserver not awake")
def confirm_trans(self, simulate=False):
proc_pids = []
res = self.get('api/transaction?__filter_by={"confirmed":false}', signed=False)
if not res['success']:
logger.error("Failure from remote: {}".format(res))
return
tids = []
for obj in res['objects']:
if obj['merged_type']:
conn = merge_coinserv[obj['merged_type']]
confirms = current_app.config['merged_cfg'][obj['merged_type']]['trans_confirmations']
else:
conn = coinserv
confirms = current_app.config['trans_confirmations']
logger.debug("Connecting to {} coinserv to lookup confirms for {}"
.format(obj['merged_type'] or 'main', obj['txid']))
res = conn.gettransaction(obj['txid'])
if res['confirmations'] > confirms:
tids.append(obj['txid'])
logger.info("Confirmed txid {} with {} confirms"
.format(obj['txid'], res['confirmations']))
data = {'tids': tids}
self.post('confirm_transactions', data=data)
def reset_trans(self, pids, bids, simulate=False):
proc_pids = []
if pids:
proc_pids = [int(i) for i in pids.split(',')]
proc_bids = []
if bids:
proc_bids = [int(i) for i in bids.split(',')]
data = {'pids': proc_pids, 'bids': proc_bids, 'reset': True}
logger.info("Resetting requested bids and pids")
self.post('update_payouts', data=data)
def validate_address(self, conn, address):
ret = conn.validateaddress(address)
return ret['isvalid']
def proc_trans(self, simulate=False, merged=None):
logger.info("Running payouts for merged = {}".format(merged))
if merged:
merged_cfg = current_app.config['merged_cfg'][merged]
conn = merge_coinserv[merged]
else:
conn = coinserv
self.poke_rpc(conn)
lock = True
if simulate:
lock = False
payouts, bonus_payouts, lock_res = self.post(
'get_payouts',
data={'lock': lock, 'merged': merged}
)
if lock:
#.........这里部分代码省略.........