url = '<STR_LIT>'<EOL>payloads = {<EOL>'<STR_LIT>': <NUM_LIT:1>,<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': round(random.random(), <NUM_LIT:3>),<EOL>'<STR_LIT>': self.__token,<EOL>'<STR_LIT:t>': '<STR_LIT>',<EOL>'<STR_LIT>': fakeid,<EOL>}<EOL>headers = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>'.format(<EOL>token=self.__token,<EOL>),<EOL>'<STR_LIT>': self.__cookies,<EOL>}<EOL>r = requests.post(url, data=payloads, headers=headers)<EOL>try:<EOL><INDENT>message = json.dumps(json.loads(r.text)['<STR_LIT>'], ensure_ascii=False)<EOL><DEDENT>except (KeyError, ValueError):<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>return message<EOL>

获取指定用户的个人信息

返回JSON示例::

    {
        "province": "湖北",
        "city": "武汉",
        "gender": 1,
        "nick_name": "Doraemonext",
        "country": "中国",
        "remark_name": "",
        "fake_id": 844735403,
        "signature": "",
        "group_id": 0,
        "user_name": ""
    }

:param fakeid: 用户的 UID (即 fakeid)
:return: 返回的 JSON 数据
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


url = '<STR_LIT>'.format(<EOL>fakeid=fakeid,<EOL>token=self.__token,<EOL>)<EOL>headers = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>'.format(<EOL>token=self.__token,<EOL>),<EOL>'<STR_LIT>': self.__cookies,<EOL>}<EOL>r = requests.get(url, headers=headers, stream=True)<EOL>return r.raw.data<EOL>

获取用户头像信息
:param fakeid: 用户的 UID (即 fakeid)
:return: 二进制 JPG 数据字符串, 可直接作为 File Object 中 write 的参数
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


url = '<STR_LIT>'.format(<EOL>lastid=lastid,<EOL>token=self.__token,<EOL>)<EOL>payloads = {<EOL>'<STR_LIT>': <NUM_LIT:1>,<EOL>'<STR_LIT:f>': '<STR_LIT>',<EOL>'<STR_LIT>': random.random(),<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': self.__token,<EOL>}<EOL>headers = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>'.format(<EOL>token=self.__token,<EOL>),<EOL>'<STR_LIT>': self.__cookies,<EOL>}<EOL>r = requests.get(url, data=payloads, headers=headers)<EOL>try:<EOL><INDENT>return int(json.loads(r.text)['<STR_LIT>'])<EOL><DEDENT>except (KeyError, ValueError):<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>

获取新消息的数目
:param lastid: 最近获取的消息 ID, 为 0 时获取总消息数目
:return: 消息数目


return self.get_message_list(count=<NUM_LIT:1>)<EOL>

获取最新一条消息

返回JSON示例::

    {
        "msg_item": [
            {
                "id": 206448489,
                "type": 2,
                "fakeid": "844735403",
                "nick_name": "Doraemonext",
                "date_time": 1408696938,
                "source": "",
                "msg_status": 4,
                "has_reply": 0,
                "refuse_reason": "",
                "multi_item": [ ],
                "to_uin": 2391068708,
                "send_stat": {
                    "total": 0,
                    "succ": 0,
                    "fail": 0
                }
            }
        ]
    }

:return: 返回的 JSON 数据
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


def get_message_list(self, lastid=<NUM_LIT:0>, offset=<NUM_LIT:0>, count=<NUM_LIT:20>, day=<NUM_LIT:7>, star=False):

if star:<EOL><INDENT>star_param = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>star_param = '<STR_LIT>'<EOL><DEDENT>if lastid == <NUM_LIT:0>:<EOL><INDENT>lastid = '<STR_LIT>'<EOL><DEDENT>url = '<STR_LIT>'.format(<EOL>star=star_param,<EOL>count=count,<EOL>day=day,<EOL>lastid=lastid,<EOL>offset=offset,<EOL>token=self.__token,<EOL>)<EOL>headers = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>'.format(token=self.__token),<EOL>'<STR_LIT>': self.__cookies,<EOL>}<EOL>r = requests.get(url, headers=headers)<EOL>try:<EOL><INDENT>message = json.loads(r.text)['<STR_LIT>']<EOL><DEDENT>except (KeyError, ValueError):<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>return message<EOL>

获取消息列表

返回JSON示例::
    {
        "msg_item": [
            {
                "id": 206439583,
                "type": 1,
                "fakeid": "844735403",
                "nick_name": "Doraemonext",
                "date_time": 1408671892,
                "content": "测试消息",
                "source": "",
                "msg_status": 4,
                "has_reply": 0,
                "refuse_reason": "",
                "multi_item": [ ],
                "to_uin": 2391068708,
                "send_stat": {
                    "total": 0,
                    "succ": 0,
                    "fail": 0
                }
            },
            {
                "id": 206439579,
                "type": 1,
                "fakeid": "844735403",
                "nick_name": "Doraemonext",
                "date_time": 1408671889,
                "content": "wechat-python-sdk",
                "source": "",
                "msg_status": 4,
                "has_reply": 0,
                "refuse_reason": "",
                "multi_item": [ ],
                "to_uin": 2391068708,
                "send_stat": {
                    "total": 0,
                    "succ": 0,
                    "fail": 0
                }
            }
        ]
    }

:param lastid: 传入最后的消息 id 编号, 为 0 则从最新一条起倒序获取
:param offset: lastid 起算第一条的偏移量
:param count: 获取数目
:param day: 最近几天消息 (0: 今天, 1: 昨天, 2: 前天, 3: 更早, 7: 全部), 这里的全部仅有5天
:param star: 是否只获取星标消息
:return: 返回的 JSON 数据
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


def get_message_image(self, msgid, mode='<STR_LIT>'):

if mode != '<STR_LIT>' and mode != '<STR_LIT>':<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>url = '<STR_LIT>'.format(<EOL>msgid=msgid,<EOL>token=self.__token,<EOL>mode=mode,<EOL>)<EOL>headers = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>'.format(<EOL>token=self.__token,<EOL>),<EOL>'<STR_LIT>': self.__cookies,<EOL>}<EOL>r = requests.get(url, headers=headers, stream=True)<EOL>if r.headers.get('<STR_LIT>', None) == '<STR_LIT>':<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>if not r.raw.data:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>return r.raw.data<EOL>

根据消息 ID 获取图片消息内容
:param msgid: 消息 ID
:param mode: 图片尺寸 ('large'或'small')
:return: 二进制 JPG 图片字符串, 可直接作为 File Object 中 write 的参数
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
:raises ValueError: 参数出错, 错误原因直接打印异常即可, 错误内容: ``image message not exist``: msg参数无效, ``mode error``: mode参数无效


url = '<STR_LIT>'.format(<EOL>msgid=msgid,<EOL>token=self.__token,<EOL>)<EOL>headers = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>'.format(<EOL>token=self.__token,<EOL>),<EOL>'<STR_LIT>': self.__cookies,<EOL>}<EOL>r = requests.get(url, headers=headers, stream=True)<EOL>if r.headers.get('<STR_LIT>', None) == '<STR_LIT>':<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>if not r.raw.data:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>return r.raw.data<EOL>

根据消息 ID 获取语音消息内容
:param msgid: 消息 ID
:return: 二进制 MP3 音频字符串, 可直接作为 File Object 中 write 的参数
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
:raises ValueError: 参数出错, 错误原因直接打印异常即可, 错误内容: ``voice message not exist``: msg参数无效


根据消息 ID 获取视频消息内容
:param msgid: 消息 ID
:return: 二进制 MP4 视频字符串, 可直接作为 File Object 中 write 的参数
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
:raises ValueError: 参数出错, 错误原因直接打印异常即可, 错误内容: ``video message not exist``: msg参数无效


if not self.__fakeid:<EOL><INDENT>self._init_self_information()<EOL><DEDENT>

初始化公众号自身的 ``fakeid`` 值
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


if not self.__ticket:<EOL><INDENT>self._init_self_information()<EOL><DEDENT>

初始化公众号自身的 ``ticket`` 及 ``ticket_id`` 值
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


url = '<STR_LIT>'.format(token=self.__token)<EOL>headers = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': self.__cookies,<EOL>}<EOL>r = requests.get(url, headers=headers)<EOL>ticket_id = re.search(r'<STR_LIT>', r.text)<EOL>if not ticket_id:<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>self.__ticket_id = ticket_id.group(<NUM_LIT:1>)<EOL>ticket = re.search(r'<STR_LIT>', r.text)<EOL>if not ticket:<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>self.__ticket = ticket.group(<NUM_LIT:1>)<EOL>fakeid = re.search(r'<STR_LIT>', r.text)<EOL>if not fakeid:<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>self.__fakeid = fakeid.group(<NUM_LIT:1>)<EOL>

初始化公众号自身的属性值 (目前包括 ``Ticket`` 值 及 公众号自身的 ``fakeid`` 值)
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


if not self.__appid:<EOL><INDENT>self._init_plugin_token_appid()<EOL><DEDENT>

初始化公众号自身的 ``appid`` 值
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


if not self.__plugin_token:<EOL><INDENT>self._init_plugin_token_appid()<EOL><DEDENT>

初始化公众号自身的 ``PluginToken`` 值
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


if not self.__plugin_token or not self.__appid:<EOL><INDENT>url = '<STR_LIT>'.format(<EOL>token=self.__token,<EOL>)<EOL>headers = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>'.format(<EOL>token=self.__token,<EOL>),<EOL>'<STR_LIT>': self.__cookies,<EOL>}<EOL>r = requests.get(url, headers=headers)<EOL>plugin_token = re.search(r"<STR_LIT>", r.text)<EOL>if not plugin_token:<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>self.__plugin_token = plugin_token.group(<NUM_LIT:1>)<EOL>appid = re.search(r"<STR_LIT>", r.text)<EOL>if not appid:<EOL><INDENT>raise NeedLoginError(r.text)<EOL><DEDENT>self.__appid = appid.group(<NUM_LIT:1>)<EOL><DEDENT>

初始化公众号的 ``PluginToken`` 值及公众号自身的 ``appid`` 值
:raises NeedLoginError: 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据


if not data:<EOL><INDENT>return data<EOL><DEDENT>result = None<EOL>if isinstance(data, str) and hasattr(data, '<STR_LIT>'):<EOL><INDENT>result = data.decode('<STR_LIT:utf-8>')<EOL><DEDENT>else:<EOL><INDENT>result = data<EOL><DEDENT>return result<EOL>

编码转换
        :param data: 需要转换的数据
        :return: 转换好的数据


if not isinstance(data, list):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>result = []<EOL>for item in data:<EOL><INDENT>if isinstance(item, dict):<EOL><INDENT>result.append(cls._transcoding_dict(item))<EOL><DEDENT>elif isinstance(item, list):<EOL><INDENT>result.append(cls._transcoding_list(item))<EOL><DEDENT>else:<EOL><INDENT>result.append(item)<EOL><DEDENT><DEDENT>return result<EOL>

编码转换 for list
        :param data: 需要转换的 list 数据
        :return: 转换好的 list


if not isinstance(data, dict):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>result = {}<EOL>for k, v in data.items():<EOL><INDENT>k = cls._transcoding(k)<EOL>if isinstance(v, dict):<EOL><INDENT>v = cls._transcoding_dict(v)<EOL><DEDENT>elif isinstance(v, list):<EOL><INDENT>v = cls._transcoding_list(v)<EOL><DEDENT>else:<EOL><INDENT>v = cls._transcoding(v)<EOL><DEDENT>result.update({k: v})<EOL><DEDENT>return result<EOL>

编码转换 for dict
:param data: 需要转换的 dict 数据
:return: 转换好的 dict


self.__request = WechatRequest()<EOL>if kwargs.get('<STR_LIT>') is not True:<EOL><INDENT>disable_urllib3_warning()  <EOL><DEDENT>self.__token = kwargs.get('<STR_LIT>')<EOL>self.__appid = kwargs.get('<STR_LIT>')<EOL>self.__appsecret = kwargs.get('<STR_LIT>')<EOL>self.__encrypt_mode = kwargs.get('<STR_LIT>', '<STR_LIT>')<EOL>self.__encoding_aes_key = kwargs.get('<STR_LIT>')<EOL>self.__crypto = None<EOL>self._update_crypto()<EOL>self.__access_token_getfunc = kwargs.get('<STR_LIT>')<EOL>self.__access_token_setfunc = kwargs.get('<STR_LIT>')<EOL>self.__access_token_refreshfunc = kwargs.get('<STR_LIT>')<EOL>self.__access_token = kwargs.get('<STR_LIT>')<EOL>self.__access_token_expires_at = kwargs.get('<STR_LIT>')<EOL>self.__jsapi_ticket_getfunc = kwargs.get('<STR_LIT>')<EOL>self.__jsapi_ticket_setfunc = kwargs.get('<STR_LIT>')<EOL>self.__jsapi_ticket_refreshfunc = kwargs.get('<STR_LIT>')<EOL>self.__jsapi_ticket = kwargs.get('<STR_LIT>')<EOL>self.__jsapi_ticket_expires_at = kwargs.get('<STR_LIT>')<EOL>self.__partnerid = kwargs.get('<STR_LIT>')<EOL>self.__partnerkey = kwargs.get('<STR_LIT>')<EOL>self.__paysignkey = kwargs.get('<STR_LIT>')<EOL>

:param kwargs: 配置信息字典, 可用字典 key 值及对应解释如下:
               'token': 微信 Token

               'appid': App ID
               'appsecret': App Secret

               'encrypt_mode': 加解密模式 ('normal': 明文模式, 'compatible': 兼容模式, 'safe': 安全模式(默认))
               'encoding_aes_key': EncodingAESKey 值 (传入此值必须保证同时传入 token, appid, 否则抛出异常)

               'access_token_getfunc': access token 获取函数 (用于单机及分布式环境下, 具体格式参见文档)
               'access_token_setfunc': access token 写入函数 (用于单机及分布式环境下, 具体格式参见文档)
               'access_token_refreshfunc': access token 刷新函数 (用于单机及分布式环境下, 具体格式参见文档)
               'access_token': 直接导入的 access token 值, 该值需要在上一次该类实例化之后手动进行缓存并在此处传入, 如果不
                               传入, 将会在需要时自动重新获取 (传入 access_token_getfunc 和 access_token_setfunc 函数
                               后将会自动忽略此处的传入值)
               'access_token_expires_at': 直接导入的 access token 的过期日期, 该值需要在上一次该类实例化之后手动进行缓存
                                          并在此处传入, 如果不传入, 将会在需要时自动重新获取 (传入 access_token_getfunc
                                          和 access_token_setfunc 函数后将会自动忽略此处的传入值)

               'jsapi_ticket_getfunc': jsapi ticket 获取函数 (用于单机及分布式环境下, 具体格式参见文档)
               'jsapi_ticket_setfunc': jsapi ticket 写入函数 (用于单机及分布式环境下, 具体格式参见文档)
               'jsapi_ticket_refreshfunc': jsapi ticket 刷新函数 (用于单机及分布式环境下, 具体格式参见文档)
               'jsapi_ticket': 直接导入的 jsapi ticket 值, 该值需要在上一次该类实例化之后手动进行缓存并在此处传入, 如果不
                               传入, 将会在需要时自动重新获取 (传入 jsapi_ticket_getfunc 和 jsapi_ticket_setfunc 函数
                               后将会自动忽略此处的传入值)
               'jsapi_ticket_expires_at': 直接导入的 jsapi ticket 的过期日期, 该值需要在上一次该类实例化之后手动进行缓存
                                          并在此处传入, 如果不传入, 将会在需要时自动重新获取 (传入 jsapi_ticket_getfunc
                                          和 jsapi_ticket_setfunc 函数后将会自动忽略此处的传入值)

               'partnerid': 财付通商户身份标识, 支付权限专用
               'partnerkey': 财付通商户权限密钥 Key, 支付权限专用
               'paysignkey': 商户签名密钥 Key, 支付权限专用

               'checkssl': 是否检查 SSL, 默认不检查 (False), 可避免 urllib3 的 InsecurePlatformWarning 警告
:return:


self._check_token()<EOL>return self.__token<EOL>


self.__token = token<EOL>self._update_crypto()<EOL>


return self.__appid<EOL>


return self.__appsecret<EOL>


def set_appid_appsecret(self, appid, appsecret):

self.__appid = appid<EOL>self.__appsecret = appsecret<EOL>self._update_crypto()<EOL>


return self.__encoding_aes_key<EOL>


self.__encoding_aes_key = encoding_aes_key<EOL>self._update_crypto()<EOL>


self.__encrypt_mode = encrypt_mode<EOL>self._update_crypto()<EOL>


return self.__crypto<EOL>

获取当前 Crypto 实例


self._check_appid_appsecret()<EOL>if callable(self.__access_token_getfunc):<EOL><INDENT>self.__access_token, self.__access_token_expires_at = self.__access_token_getfunc()<EOL><DEDENT>if self.__access_token:<EOL><INDENT>now = time.time()<EOL>if self.__access_token_expires_at - now > <NUM_LIT>:<EOL><INDENT>return self.__access_token<EOL><DEDENT><DEDENT>self.grant_access_token()  <EOL>return self.__access_token<EOL>

获取当前 access token 值, 本方法会自行维护 access token 有效性


self._check_appid_appsecret()<EOL>if callable(self.__jsapi_ticket_getfunc):<EOL><INDENT>self.__jsapi_ticket, self.__jsapi_ticket_expires_at = self.__jsapi_ticket_getfunc()<EOL><DEDENT>if self.__jsapi_ticket:<EOL><INDENT>now = time.time()<EOL>if self.__jsapi_ticket_expires_at - now > <NUM_LIT>:<EOL><INDENT>return self.__jsapi_ticket<EOL><DEDENT><DEDENT>self.grant_jsapi_ticket()  <EOL>return self.__jsapi_ticket<EOL>

获取当前 jsapi ticket 值, 本方法会自行维护 jsapi ticket 有效性


return self.__partnerid<EOL>

获取当前财付通商户身份标识


return self.__partnerkey<EOL>

获取当前财付通商户权限密钥 Key


return self.__paysignkey<EOL>

获取商户签名密钥 Key


self._check_appid_appsecret()<EOL>if callable(self.__access_token_refreshfunc):<EOL><INDENT>self.__access_token, self.__access_token_expires_at = self.__access_token_refreshfunc()<EOL>return<EOL><DEDENT>response_json = self.__request.get(<EOL>url="<STR_LIT>",<EOL>params={<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.__appid,<EOL>"<STR_LIT>": self.__appsecret,<EOL>},<EOL>access_token=self.__access_token<EOL>)<EOL>self.__access_token = response_json['<STR_LIT>']<EOL>self.__access_token_expires_at = int(time.time()) + response_json['<STR_LIT>']<EOL>if callable(self.__access_token_setfunc):<EOL><INDENT>self.__access_token_setfunc(self.__access_token, self.__access_token_expires_at)<EOL><DEDENT>return response_json<EOL>

获取 access token 并更新当前配置
:return: 返回的 JSON 数据包 (传入 access_token_refreshfunc 参数后返回 None)


self._check_appid_appsecret()<EOL>if callable(self.__jsapi_ticket_refreshfunc):<EOL><INDENT>self.__jsapi_ticket, self.__jsapi_ticket_expires_at = self.__jsapi_ticket_refreshfunc()<EOL>return<EOL><DEDENT>response_json = self.__request.get(<EOL>url="<STR_LIT>",<EOL>params={<EOL>"<STR_LIT:type>": "<STR_LIT>",<EOL>},<EOL>access_token=self.access_token,<EOL>)<EOL>self.__jsapi_ticket = response_json['<STR_LIT>']<EOL>self.__jsapi_ticket_expires_at = int(time.time()) + response_json['<STR_LIT>']<EOL>if callable(self.__jsapi_ticket_setfunc):<EOL><INDENT>self.__jsapi_ticket_setfunc(self.__jsapi_ticket, self.__jsapi_ticket_expires_at)<EOL><DEDENT>return response_json<EOL>

获取 jsapi ticket 并更新当前配置
:return: 返回的 JSON 数据包 (传入 jsapi_ticket_refreshfunc 参数后返回 None)


self._check_appid_appsecret()<EOL>return {<EOL>'<STR_LIT>': self.access_token,<EOL>'<STR_LIT>': self.__access_token_expires_at,<EOL>}<EOL>

获取 Access Token 及 Access Token 过期日期, 仅供缓存使用, 如果希望得到原生的 Access Token 请求数据请使用 :func:`grant_token`
**仅为兼容 v0.6.0 以前版本使用, 自行维护 access_token 请使用 access_token_setfunc 和 access_token_getfunc 进行操作**
:return: dict 对象, key 包括 `access_token` 及 `access_token_expires_at`


self._check_appid_appsecret()<EOL>return {<EOL>'<STR_LIT>': self.jsapi_ticket,<EOL>'<STR_LIT>': self.__jsapi_ticket_expires_at,<EOL>}<EOL>

获取 Jsapi Ticket 及 Jsapi Ticket 过期日期, 仅供缓存使用, 如果希望得到原生的 Jsapi Ticket 请求数据请使用 :func:`grant_jsapi_ticket`
**仅为兼容 v0.6.0 以前版本使用, 自行维护 jsapi_ticket 请使用 jsapi_ticket_setfunc 和 jsapi_ticket_getfunc 进行操作**
:return: dict 对象, key 包括 `jsapi_ticket` 及 `jsapi_ticket_expires_at`


if not self.__token:<EOL><INDENT>raise NeedParamError('<STR_LIT>')<EOL><DEDENT>

检查 Token 是否存在
:raises NeedParamError: Token 参数没有在初始化的时候提供


if not self.__appid or not self.__appsecret:<EOL><INDENT>raise NeedParamError('<STR_LIT>')<EOL><DEDENT>

检查 AppID 和 AppSecret 是否存在
:raises NeedParamError: AppID 或 AppSecret 参数没有在初始化的时候完整提供


if self.__encrypt_mode in ['<STR_LIT>', '<STR_LIT>'] and self.__encoding_aes_key is not None:<EOL><INDENT>if self.__token is None or self.__appid is None:<EOL><INDENT>raise NeedParamError('<STR_LIT>')<EOL><DEDENT>self.__crypto = BasicCrypto(self.__token, self.__encoding_aes_key, self.__appid)<EOL><DEDENT>else:<EOL><INDENT>self.__crypto = None<EOL><DEDENT>

根据当前配置内容更新 Crypto 类


def __init__(self, token=None, appid=None, appsecret=None, partnerid=None,<EOL>partnerkey=None, paysignkey=None, access_token=None, access_token_expires_at=None,<EOL>jsapi_ticket=None, jsapi_ticket_expires_at=None, checkssl=False, conf=None):

if conf is not None:<EOL><INDENT>self.__conf = conf<EOL><DEDENT>elif isinstance(token, WechatConf):  <EOL><INDENT>self.__conf = token<EOL><DEDENT>else:  <EOL><INDENT>self.__conf = WechatConf(<EOL>token=token,<EOL>appid=appid,<EOL>appsecret=appsecret,<EOL>access_token=access_token,<EOL>access_token_expires_at=access_token_expires_at,<EOL>jsapi_ticket=jsapi_ticket,<EOL>jsapi_ticket_expires_at=jsapi_ticket_expires_at,<EOL>encrypt_mode='<STR_LIT>',<EOL>partnerid=partnerid,<EOL>partnerkey=partnerkey,<EOL>paysignkey=paysignkey,<EOL>checkssl=checkssl,<EOL>)<EOL><DEDENT>self.__request = WechatRequest(conf=self.__conf)<EOL>self.__is_parse = False<EOL>self.__message = None<EOL>

:param token: 微信 Token
:param appid: App ID
:param appsecret: App Secret
:param partnerid: 财付通商户身份标识, 支付权限专用
:param partnerkey: 财付通商户权限密钥 Key, 支付权限专用
:param paysignkey: 商户签名密钥 Key, 支付权限专用
:param access_token: 直接导入的 access_token 值, 该值需要在上一次该类实例化之后手动进行缓存并在此处传入, 如果不传入, 将会在需要时自动重新获取
:param access_token_expires_at: 直接导入的 access_token 的过期日期，该值需要在上一次该类实例化之后手动进行缓存并在此处传入, 如果不传入, 将会在需要时自动重新获取
:param jsapi_ticket: 直接导入的 jsapi_ticket 值, 该值需要在上一次该类实例化之后手动进行缓存并在此处传入, 如果不传入, 将会在需要时自动重新获取
:param jsapi_ticket_expires_at: 直接导入的 jsapi_ticket 的过期日期，该值需要在上一次该类实例化之后手动进行缓存并在此处传入, 如果不传入, 将会在需要时自动重新获取
:param checkssl: 是否检查 SSL, 默认为 False, 可避免 urllib3 的 InsecurePlatformWarning 警告
:param conf: WechatConf 配置类, 提供此参数将默认忽略其他所有参数, 所有数据均从此配置类中获取


return self.__conf<EOL>


self.__conf = conf<EOL>self.__request = WechatRequest(conf=self.__conf)<EOL>


return self.__request<EOL>


self.__request = request<EOL>


def check_signature(self, signature, timestamp, nonce):

if not signature or not timestamp or not nonce:<EOL><INDENT>return False<EOL><DEDENT>tmp_list = [self.conf.token, timestamp, nonce]<EOL>tmp_list.sort()<EOL>tmp_str = '<STR_LIT>'.join(tmp_list)<EOL>if signature != hashlib.sha1(tmp_str.encode('<STR_LIT:utf-8>')).hexdigest():<EOL><INDENT>return False<EOL><DEDENT>return True<EOL>

验证微信消息真实性
:param signature: 微信加密签名
:param timestamp: 时间戳
:param nonce: 随机数
:return: 通过验证返回 True, 未通过验证返回 False


def generate_jsapi_signature(self, timestamp, noncestr, url, jsapi_ticket=None):

if not jsapi_ticket:<EOL><INDENT>jsapi_ticket = self.conf.jsapi_ticket<EOL><DEDENT>data = {<EOL>'<STR_LIT>': jsapi_ticket,<EOL>'<STR_LIT>': noncestr,<EOL>'<STR_LIT>': timestamp,<EOL>'<STR_LIT:url>': url,<EOL>}<EOL>keys = list(data.keys())<EOL>keys.sort()<EOL>data_str = '<STR_LIT:&>'.join(['<STR_LIT>' % (key, data[key]) for key in keys])<EOL>signature = hashlib.sha1(data_str.encode('<STR_LIT:utf-8>')).hexdigest()<EOL>return signature<EOL>

使用 jsapi_ticket 对 url 进行签名
:param timestamp: 时间戳
:param noncestr: 随机数
:param url: 要签名的 url，不包含 # 及其后面部分
:param jsapi_ticket: (可选参数) jsapi_ticket 值 (如不提供将自动通过 appid 和 appsecret 获取)
:return: 返回sha1签名的hexdigest值


def parse_data(self, data, msg_signature=None, timestamp=None, nonce=None):

result = {}<EOL>if isinstance(data, six.text_type):  <EOL><INDENT>data = data.encode('<STR_LIT:utf-8>')<EOL><DEDENT>if self.conf.encrypt_mode == '<STR_LIT>':<EOL><INDENT>if not (msg_signature and timestamp and nonce):<EOL><INDENT>raise ParseError('<STR_LIT>')<EOL><DEDENT>data = self.conf.crypto.decrypt_message(<EOL>msg=data,<EOL>msg_signature=msg_signature,<EOL>timestamp=timestamp,<EOL>nonce=nonce,<EOL>)<EOL><DEDENT>try:<EOL><INDENT>xml = XMLStore(xmlstring=data)<EOL><DEDENT>except Exception:<EOL><INDENT>raise ParseError()<EOL><DEDENT>result = xml.xml2dict<EOL>result['<STR_LIT>'] = data<EOL>result['<STR_LIT:type>'] = result.pop('<STR_LIT>').lower()<EOL>message_type = MESSAGE_TYPES.get(result['<STR_LIT:type>'], UnknownMessage)<EOL>self.__message = message_type(result)<EOL>self.__is_parse = True<EOL>

解析微信服务器发送过来的数据并保存类中
:param data: HTTP Request 的 Body 数据
:param msg_signature: EncodingAESKey 的 msg_signature
:param timestamp: EncodingAESKey 用时间戳
:param nonce: EncodingAESKey 用随机数
:raises ParseError: 解析微信服务器数据错误, 数据不合法


self._check_parse()<EOL>return self.__message<EOL>

获取解析好的 WechatMessage 对象
:return: 解析好的 WechatMessage 对象


return self.conf.get_access_token()<EOL>


return self.conf.get_jsapi_ticket()<EOL>


self._check_parse()<EOL>return self._encrypt_response('<STR_LIT:success>')<EOL>

回复空消息
:return: 符合微信服务器要求的空消息


def response_text(self, content, escape=False):

self._check_parse()<EOL>content = self._transcoding(content)<EOL>if escape:<EOL><INDENT>if six.PY2:<EOL><INDENT>content = cgi.escape(content)<EOL><DEDENT>else:<EOL><INDENT>import html<EOL>content = html.escape(content)<EOL><DEDENT><DEDENT>response = TextReply(message=self.__message, content=content).render()<EOL>return self._encrypt_response(response)<EOL>

将文字信息 content 组装为符合微信服务器要求的响应数据
:param content: 回复文字
:param escape: 是否转义该文本内容 (默认不转义)
:return: 符合微信服务器要求的 XML 响应数据


self._check_parse()<EOL>response = ImageReply(message=self.__message, media_id=media_id).render()<EOL>return self._encrypt_response(response)<EOL>

将 media_id 所代表的图片组装为符合微信服务器要求的响应数据
:param media_id: 图片的 MediaID
:return: 符合微信服务器要求的 XML 响应数据


self._check_parse()<EOL>response = VoiceReply(message=self.__message, media_id=media_id).render()<EOL>return self._encrypt_response(response)<EOL>

将 media_id 所代表的语音组装为符合微信服务器要求的响应数据
:param media_id: 语音的 MediaID
:return: 符合微信服务器要求的 XML 响应数据


def response_video(self, media_id, title=None, description=None):

self._check_parse()<EOL>title = self._transcoding(title)<EOL>description = self._transcoding(description)<EOL>response = VideoReply(message=self.__message, media_id=media_id, title=title, description=description).render()<EOL>return self._encrypt_response(response)<EOL>

将 media_id 所代表的视频组装为符合微信服务器要求的响应数据
:param media_id: 视频的 MediaID
:param title: 视频消息的标题
:param description: 视频消息的描述
:return: 符合微信服务器要求的 XML 响应数据


def response_music(self, music_url, title=None, description=None, hq_music_url=None, thumb_media_id=None):

self._check_parse()<EOL>music_url = self._transcoding(music_url)<EOL>title = self._transcoding(title)<EOL>description = self._transcoding(description)<EOL>hq_music_url = self._transcoding(hq_music_url)<EOL>response = MusicReply(message=self.__message, title=title, description=description, music_url=music_url,<EOL>hq_music_url=hq_music_url, thumb_media_id=thumb_media_id).render()<EOL>return self._encrypt_response(response)<EOL>

将音乐信息组装为符合微信服务器要求的响应数据
:param music_url: 音乐链接
:param title: 音乐标题
:param description: 音乐描述
:param hq_music_url: 高质量音乐链接, WIFI环境优先使用该链接播放音乐
:param thumb_media_id: 缩略图的 MediaID
:return: 符合微信服务器要求的 XML 响应数据


self._check_parse()<EOL>for article in articles:<EOL><INDENT>if article.get('<STR_LIT:title>'):<EOL><INDENT>article['<STR_LIT:title>'] = self._transcoding(article['<STR_LIT:title>'])<EOL><DEDENT>if article.get('<STR_LIT:description>'):<EOL><INDENT>article['<STR_LIT:description>'] = self._transcoding(article['<STR_LIT:description>'])<EOL><DEDENT>if article.get('<STR_LIT>'):<EOL><INDENT>article['<STR_LIT>'] = self._transcoding(article['<STR_LIT>'])<EOL><DEDENT>if article.get('<STR_LIT:url>'):<EOL><INDENT>article['<STR_LIT:url>'] = self._transcoding(article['<STR_LIT:url>'])<EOL><DEDENT><DEDENT>news = ArticleReply(message=self.__message)<EOL>for article in articles:<EOL><INDENT>article = Article(**article)<EOL>news.add_article(article)<EOL><DEDENT>response = news.render()<EOL>return self._encrypt_response(response)<EOL>

将新闻信息组装为符合微信服务器要求的响应数据
:param articles: list 对象, 每个元素为一个 dict 对象, key 包含 `title`, `description`, `picurl`, `url`
:return: 符合微信服务器要求的 XML 响应数据


self._check_parse()<EOL>response = GroupTransferReply(message=self.__message).render()<EOL>return self._encrypt_response(response)<EOL>

将 message 群发到多客服系统
:return: 符合微信服务器要求的 XML 响应数据


return self.conf.grant_access_token()<EOL>

获取 Access Token
详情请参考 http://mp.weixin.qq.com/wiki/11/0e4b294685f817b95cbed85ba5e82b8f.html
:return: 返回的 JSON 数据包


return self.conf.grant_jsapi_ticket()<EOL>

获取 Jsapi Ticket
详情请参考 http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95
:return: 返回的 JSON 数据包


menu_data = self._transcoding_dict(menu_data)<EOL>return self.request.post(<EOL>url='<STR_LIT>',<EOL>data=menu_data<EOL>)<EOL>

创建自定义菜单 ::

    # -*- coding: utf-8 -*-
    wechat = WechatBasic(appid='appid', appsecret='appsecret')
    wechat.create_menu({
        'button':[
            {
                'type': 'click',
                'name': '今日歌曲',
                'key': 'V1001_TODAY_MUSIC'
            },
            {
                'type': 'click',
                'name': '歌手简介',
                'key': 'V1001_TODAY_SINGER'
            },
            {
                'name': '菜单',
                'sub_button': [
                    {
                        'type': 'view',
                        'name': '搜索',
                        'url': 'http://www.soso.com/'
                    },
                    {
                        'type': 'view',
                        'name': '视频',
                        'url': 'http://v.qq.com/'
                    },
                    {
                        'type': 'click',
                        'name': '赞一下我们',
                        'key': 'V1001_GOOD'
                    }
                ]
            }
        ]})

详情请参考 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html
:param menu_data: Python 字典
:return: 返回的 JSON 数据包


return self.request.get('<STR_LIT>')<EOL>

查询自定义菜单
详情请参考 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html
:return: 返回的 JSON 数据包


删除自定义菜单
详情请参考 http://mp.weixin.qq.com/wiki/16/8ed41ba931e4845844ad6d1eeb8060c8.html
:return: 返回的 JSON 数据包


def upload_media(self, media_type, media_file, extension='<STR_LIT>'):

if six.PY2:<EOL><INDENT>return self._upload_media_py2(media_type, media_file, extension)<EOL><DEDENT>else:<EOL><INDENT>return self._upload_media_py3(media_type, media_file, extension)<EOL><DEDENT>

上传多媒体文件
详情请参考 http://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html
:param media_type: 媒体文件类型，分别有图片（image）、语音（voice）、视频（video）和缩略图（thumb）
:param media_file: 要上传的文件，一个 File object 或 StringIO object
:param extension: 如果 media_file 传入的为 StringIO object，那么必须传入 extension 显示指明该媒体文件扩展名，如 ``mp3``, ``amr``；如果 media_file 传入的为 File object，那么该参数请留空
:return: 返回的 JSON 数据包


return self.request.get(<EOL>'<STR_LIT>',<EOL>params={<EOL>'<STR_LIT>': media_id,<EOL>},<EOL>stream=True,<EOL>)<EOL>

下载多媒体文件
详情请参考 http://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html
:param media_id: 媒体文件 ID
:return: requests 的 Response 实例


return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': {<EOL>'<STR_LIT:name>': name,<EOL>},<EOL>}<EOL>)<EOL>

创建分组
详情请参考 http://mp.weixin.qq.com/wiki/13/be5272dc4930300ba561d927aead2569.html
:param name: 分组名字（30个字符以内）
:return: 返回的 JSON 数据包
:raise HTTPError: 微信api http 请求失败


查询所有分组
详情请参考 http://mp.weixin.qq.com/wiki/13/be5272dc4930300ba561d927aead2569.html
:return: 返回的 JSON 数据包


return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': openid,<EOL>}<EOL>)<EOL>

查询用户所在分组
详情请参考 http://mp.weixin.qq.com/wiki/13/be5272dc4930300ba561d927aead2569.html
:param openid: 用户的OpenID
:return: 返回的 JSON 数据包


return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': {<EOL>'<STR_LIT:id>': int(group_id),<EOL>'<STR_LIT:name>': name,<EOL>}<EOL>}<EOL>)<EOL>

修改分组名
详情请参考 http://mp.weixin.qq.com/wiki/13/be5272dc4930300ba561d927aead2569.html
:param group_id: 分组id，由微信分配
:param name: 分组名字（30个字符以内）
:return: 返回的 JSON 数据包


return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': group_id,<EOL>}<EOL>)<EOL>

移动用户分组
详情请参考 http://mp.weixin.qq.com/wiki/13/be5272dc4930300ba561d927aead2569.html
:param user_id: 用户 ID 。 就是你收到的 WechatMessage 的 source
:param group_id: 分组 ID
:return: 返回的 JSON 数据包


def get_user_info(self, user_id, lang='<STR_LIT>'):

return self.request.get(<EOL>url='<STR_LIT>',<EOL>params={<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': lang,<EOL>}<EOL>)<EOL>

获取用户基本信息
详情请参考 http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html
:param user_id: 用户 ID, 就是你收到的 WechatMessage 的 source
:param lang: 返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语
:return: 返回的 JSON 数据包


params = dict()<EOL>if first_user_id:<EOL><INDENT>params['<STR_LIT>'] = first_user_id<EOL><DEDENT>return self.request.get('<STR_LIT>', params=params)<EOL>

获取关注者列表
详情请参考 http://mp.weixin.qq.com/wiki/3/17e6919a39c1c53555185907acf70093.html
:param first_user_id: 可选。第一个拉取的OPENID，不填默认从头开始拉取
:return: 返回的 JSON 数据包


def send_text_message(self, user_id, content):

return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': '<STR_LIT:text>',<EOL>'<STR_LIT:text>': {<EOL>'<STR_LIT:content>': content,<EOL>},<EOL>}<EOL>)<EOL>

发送文本消息
详情请参考 http://mp.weixin.qq.com/wiki/7/12a5a320ae96fecdf0e15cb06123de9f.html
:param user_id: 用户 ID, 就是你收到的 WechatMessage 的 source
:param content: 消息正文
:return: 返回的 JSON 数据包


def send_image_message(self, user_id, media_id):

return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': '<STR_LIT:image>',<EOL>'<STR_LIT:image>': {<EOL>'<STR_LIT>': media_id,<EOL>},<EOL>}<EOL>)<EOL>

发送图片消息
详情请参考 http://mp.weixin.qq.com/wiki/7/12a5a320ae96fecdf0e15cb06123de9f.html
:param user_id: 用户 ID, 就是你收到的 WechatMessage 的 source
:param media_id: 图片的媒体ID。 可以通过 :func:`upload_media` 上传。
:return: 返回的 JSON 数据包


def send_voice_message(self, user_id, media_id):

return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': media_id,<EOL>},<EOL>}<EOL>)<EOL>

发送语音消息
详情请参考 http://mp.weixin.qq.com/wiki/7/12a5a320ae96fecdf0e15cb06123de9f.html
:param user_id: 用户 ID, 就是你收到的 WechatMessage 的 source
:param media_id: 发送的语音的媒体ID。 可以通过 :func:`upload_media` 上传。
:return: 返回的 JSON 数据包


def send_video_message(self, user_id, media_id, title=None, description=None):

video_data = {<EOL>'<STR_LIT>': media_id,<EOL>}<EOL>if title:<EOL><INDENT>video_data['<STR_LIT:title>'] = title<EOL><DEDENT>if description:<EOL><INDENT>video_data['<STR_LIT:description>'] = description<EOL><DEDENT>return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': video_data,<EOL>}<EOL>)<EOL>

发送视频消息
详情请参考 http://mp.weixin.qq.com/wiki/7/12a5a320ae96fecdf0e15cb06123de9f.html
:param user_id: 用户 ID, 就是你收到的 WechatMessage 的 source
:param media_id: 发送的视频的媒体ID。 可以通过 :func:`upload_media` 上传。
:param title: 视频消息的标题
:param description: 视频消息的描述
:return: 返回的 JSON 数据包


def send_music_message(self, user_id, url, hq_url, thumb_media_id, title=None, description=None):

music_data = {<EOL>'<STR_LIT>': url,<EOL>'<STR_LIT>': hq_url,<EOL>'<STR_LIT>': thumb_media_id,<EOL>}<EOL>if title:<EOL><INDENT>music_data['<STR_LIT:title>'] = title<EOL><DEDENT>if description:<EOL><INDENT>music_data['<STR_LIT:description>'] = description<EOL><DEDENT>return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': music_data,<EOL>}<EOL>)<EOL>

发送音乐消息
详情请参考 http://mp.weixin.qq.com/wiki/7/12a5a320ae96fecdf0e15cb06123de9f.html
:param user_id: 用户 ID, 就是你收到的 WechatMessage 的 source
:param url: 音乐链接
:param hq_url: 高品质音乐链接，wifi环境优先使用该链接播放音乐
:param thumb_media_id: 缩略图的媒体ID。 可以通过 :func:`upload_media` 上传。
:param title: 音乐标题
:param description: 音乐描述
:return: 返回的 JSON 数据包


def send_article_message(self, user_id, articles=None, media_id=None):

<EOL>if articles is None and media_id is None:<EOL><INDENT>raise TypeError('<STR_LIT>')<EOL><DEDENT>if articles:<EOL><INDENT>articles_data = []<EOL>for article in articles:<EOL><INDENT>article = Article(**article)<EOL>articles_data.append({<EOL>'<STR_LIT:title>': article.title,<EOL>'<STR_LIT:description>': article.description,<EOL>'<STR_LIT:url>': article.url,<EOL>'<STR_LIT>': article.picurl,<EOL>})<EOL><DEDENT>return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': articles_data,<EOL>},<EOL>}<EOL>)<EOL><DEDENT>return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': media_id,<EOL>},<EOL>}<EOL>)<EOL>

发送图文消息
详情请参考 http://mp.weixin.qq.com/wiki/7/12a5a320ae96fecdf0e15cb06123de9f.html
:param user_id: 用户 ID, 就是你收到的 WechatMessage 的 source
:param articles: list 对象, 每个元素为一个 dict 对象, key 包含 `title`, `description`, `picurl`, `url`
:param media_id: 待发送的图文 Media ID
:return: 返回的 JSON 数据包


data = self._transcoding_dict(data)<EOL>return self.request.post(<EOL>url='<STR_LIT>',<EOL>data=data<EOL>)<EOL>

创建二维码
详情请参考 http://mp.weixin.qq.com/wiki/18/28fc21e7ed87bec960651f0ce873ef8a.html
:param data: 你要发送的参数 dict
:return: 返回的 JSON 数据包


return requests.get(<EOL>url='<STR_LIT>',<EOL>params={<EOL>'<STR_LIT>': ticket<EOL>}<EOL>)<EOL>

通过ticket换取二维码
详情请参考 http://mp.weixin.qq.com/wiki/18/28fc21e7ed87bec960651f0ce873ef8a.html
:param ticket: 二维码 ticket 。可以通过 :func:`create_qrcode` 获取到
:return: 返回的 Request 对象


def set_template_industry(self, industry_id1, industry_id2):

return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': str(industry_id1),<EOL>'<STR_LIT>': str(industry_id2),<EOL>}<EOL>)<EOL>

设置所属行业
详情请参考 http://mp.weixin.qq.com/wiki/17/304c1885ea66dbedf7dc170d84999a9d.html
:param industry_id1: 主营行业代码
:param industry_id2: 副营行业代码
:return: 返回的 JSON 数据包


return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': str(template_id_short),<EOL>}<EOL>)<EOL>

获得模板ID
详情请参考 http://mp.weixin.qq.com/wiki/17/304c1885ea66dbedf7dc170d84999a9d.html
:param template_id_short: 模板库中模板的编号，有“TM**”和“OPENTMTM**”等形式
:return: 返回的 JSON 数据包


def send_template_message(self, user_id, template_id, data, url='<STR_LIT>', topcolor='<STR_LIT>'):

unicode_data = {}<EOL>if data:<EOL><INDENT>unicode_data = self._transcoding_dict(data)<EOL><DEDENT>return self.request.post(<EOL>url='<STR_LIT>',<EOL>data={<EOL>'<STR_LIT>': user_id,<EOL>"<STR_LIT>": template_id,<EOL>"<STR_LIT:url>": url,<EOL>"<STR_LIT>": topcolor,<EOL>"<STR_LIT:data>": unicode_data<EOL>}<EOL>)<EOL>

发送模版消息
详情请参考 http://mp.weixin.qq.com/wiki/17/304c1885ea66dbedf7dc170d84999a9d.html
:param user_id: 用户 ID, 就是你收到的 WechatMessage 的 source (OpenID)
:param template_id: 模板ID
:param data: 模板消息数据 (dict形式)，示例如下：
{
    "first": {
       "value": "恭喜你购买成功！",
       "color": "#173177"
    },
    "keynote1":{
       "value": "巧克力",
       "color": "#173177"
    },
    "keynote2": {
       "value": "39.8元",
       "color": "#173177"
    },
    "keynote3": {
       "value": "2014年9月16日",
       "color": "#173177"
    },
    "remark":{
       "value": "欢迎再次购买！",
       "color": "#173177"
    }
}
:param url: 跳转地址 (默认为空)
:param topcolor: 顶部颜色RGB值 (默认 '#FF0000' )
:return: 返回的 JSON 数据包


if not self.__is_parse:<EOL><INDENT>raise NeedParseError()<EOL><DEDENT>

检查是否成功解析微信服务器传来的数据
:raises NeedParseError: 需要解析微信服务器传来的数据


if "<STR_LIT>" in json_data and json_data["<STR_LIT>"] != <NUM_LIT:0>:<EOL><INDENT>raise OfficialAPIError(errcode=json_data.get('<STR_LIT>'), errmsg=json_data.get('<STR_LIT>', '<STR_LIT>'))<EOL><DEDENT>

检测微信公众平台返回值中是否包含错误的返回码
:raises OfficialAPIError: 如果返回码提示有错误，抛出异常；否则返回 True


self._remove_whitespace_nodes(self._doc.childNodes[<NUM_LIT:0>])<EOL>return self._element2dict(self._doc.childNodes[<NUM_LIT:0>])<EOL>


d = {}<EOL>for node in parent.childNodes:<EOL><INDENT>if not isinstance(node, minidom.Element):<EOL><INDENT>continue<EOL><DEDENT>if not node.hasChildNodes():<EOL><INDENT>continue<EOL><DEDENT>if node.childNodes[<NUM_LIT:0>].nodeType == minidom.Node.ELEMENT_NODE:<EOL><INDENT>try:<EOL><INDENT>d[node.tagName]<EOL><DEDENT>except KeyError:<EOL><INDENT>d[node.tagName] = []<EOL><DEDENT>d[node.tagName].append(self._element2dict(node))<EOL><DEDENT>elif len(node.childNodes) == <NUM_LIT:1> and node.childNodes[<NUM_LIT:0>].nodeType in [minidom.Node.CDATA_SECTION_NODE, minidom.Node.TEXT_NODE]:<EOL><INDENT>d[node.tagName] = node.childNodes[<NUM_LIT:0>].data<EOL><DEDENT><DEDENT>return d<EOL>

将单个节点转换为 dict


def _remove_whitespace_nodes(self, node, unlink=True):

remove_list = []<EOL>for child in node.childNodes:<EOL><INDENT>if child.nodeType == Node.TEXT_NODE and not child.data.strip():<EOL><INDENT>remove_list.append(child)<EOL><DEDENT>elif child.hasChildNodes():<EOL><INDENT>self._remove_whitespace_nodes(child, unlink)<EOL><DEDENT><DEDENT>for node in remove_list:<EOL><INDENT>node.parentNode.removeChild(node)<EOL>if unlink:<EOL><INDENT>node.unlink()<EOL><DEDENT><DEDENT>


self.__conf = conf<EOL>


def request(self, method, url, access_token=None, **kwargs):

access_token = self.__conf.access_token if self.__conf is not None else access_token<EOL>if "<STR_LIT>" not in kwargs:<EOL><INDENT>kwargs["<STR_LIT>"] = {<EOL>"<STR_LIT>": access_token<EOL>}<EOL><DEDENT>else:<EOL><INDENT>kwargs["<STR_LIT>"]["<STR_LIT>"] = access_token<EOL><DEDENT>if isinstance(kwargs.get("<STR_LIT:data>", "<STR_LIT>"), dict):<EOL><INDENT>body = json.dumps(kwargs["<STR_LIT:data>"], ensure_ascii=False)<EOL>if isinstance(body, six.text_type):<EOL><INDENT>body = body.encode('<STR_LIT:utf8>')<EOL><DEDENT>kwargs["<STR_LIT:data>"] = body<EOL><DEDENT>r = requests.request(<EOL>method=method,<EOL>url=url,<EOL>**kwargs<EOL>)<EOL>r.raise_for_status()<EOL>try:<EOL><INDENT>response_json = r.json()<EOL><DEDENT>except ValueError:  <EOL><INDENT>return r<EOL><DEDENT>headimgurl = response_json.get('<STR_LIT>')<EOL>if headimgurl:<EOL><INDENT>response_json['<STR_LIT>'] = headimgurl.replace('<STR_LIT:\\>', '<STR_LIT>')<EOL><DEDENT>self._check_official_error(response_json)<EOL>return response_json<EOL>

向微信服务器发送请求
:param method: 请求方法
:param url: 请求地址
:param access_token: access token 值, 如果初始化时传入 conf 会自动获取, 如果没有传入则请提供此值
:param kwargs: 附加数据
:return: 微信服务器响应的 JSON 数据


def get(self, url, access_token=None, **kwargs):

return self.request(<EOL>method="<STR_LIT>",<EOL>url=url,<EOL>access_token=access_token,<EOL>**kwargs<EOL>)<EOL>

使用 GET 方法向微信服务器发出请求
:param url: 请求地址
:param access_token: access token 值, 如果初始化时传入 conf 会自动获取, 如果没有传入则请提供此值
:param kwargs: 附加数据
:return: 微信服务器响应的 JSON 数据


def post(self, url, access_token=None, **kwargs):

使用 POST 方法向微信服务器发出请求
:param url: 请求地址
:param access_token: access token 值, 如果初始化时传入 conf 会自动获取, 如果没有传入则请提供此值
:param kwargs: 附加数据
:return: 微信服务器响应的 JSON 数据


if '<STR_LIT>' in json_data and json_data['<STR_LIT>'] != <NUM_LIT:0>:<EOL><INDENT>raise OfficialAPIError(errcode=json_data.get('<STR_LIT>'), errmsg=json_data.get('<STR_LIT>', '<STR_LIT>'))<EOL><DEDENT>


def __init__(self, token, encoding_aes_key, _id):

self.__key = base64.b64decode(to_binary(encoding_aes_key) + to_binary('<STR_LIT:=>'))<EOL>if len(self.__key) != <NUM_LIT:32>:<EOL><INDENT>raise ValidateAESKeyError(encoding_aes_key)<EOL><DEDENT>self.__token = to_binary(token)<EOL>self.__id = to_binary(_id)<EOL>self.__pc = BaseCrypto(self.__key)<EOL>

构造函数

        :param token: 公众平台上，开发者设置的Token
        :param encoding_aes_key: 公众平台上，开发者设置的EncodingAESKey
        :param _id: 公众号的 appid 或企业号的 corpid


def _check_signature(self, msg_signature, timestamp, nonce, echostr):

signature = get_sha1_signature(self.__token, timestamp, nonce, echostr)<EOL>if not signature == msg_signature:<EOL><INDENT>raise ValidateSignatureError()<EOL><DEDENT>try:<EOL><INDENT>return self.__pc.decrypt(echostr, self.__id)<EOL><DEDENT>except DecryptAESError as e:<EOL><INDENT>raise ValidateSignatureError(e)<EOL><DEDENT>

验证签名有效性

        :param msg_signature: 签名串，对应URL参数的msg_signature
        :param timestamp: 时间戳，对应URL参数的timestamp
        :param nonce: 随机串，对应URL参数的nonce
        :param echostr: 随机串，对应URL参数的echostr
        :return: 解密之后的echostr
        :raise ValidateSignatureError: 签名无效异常


def _encrypt_message(self, msg, nonce, timestamp=None):

xml =

将公众号回复用户的消息加密打包

        :param msg: 待回复用户的消息，xml格式的字符串
        :param nonce: 随机串，可以自己生成，也可以用URL参数的nonce
        :param timestamp: 时间戳，可以自己生成，也可以用URL参数的timestamp,如为None则自动用当前时间
        :return: 加密后的可以直接回复用户的密文，包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串


def _decrypt_message(self, msg, msg_signature, timestamp, nonce):

timestamp = to_binary(timestamp)<EOL>nonce = to_binary(nonce)<EOL>if isinstance(msg, six.string_types):<EOL><INDENT>try:<EOL><INDENT>msg = xmltodict.parse(to_text(msg))['<STR_LIT>']<EOL><DEDENT>except Exception as e:<EOL><INDENT>raise ParseError(e)<EOL><DEDENT><DEDENT>encrypt = msg['<STR_LIT>']<EOL>signature = get_sha1_signature(self.__token, timestamp, nonce, encrypt)<EOL>if signature != msg_signature:<EOL><INDENT>raise ValidateSignatureError()<EOL><DEDENT>return self.__pc.decrypt(encrypt, self.__id)<EOL>

检验消息的真实性，并且获取解密后的明文

        :param msg: 密文，对应POST请求的数据
        :param msg_signature: 签名串，对应URL参数的msg_signature
        :param timestamp: 时间戳，对应URL参数的timestamp
        :param nonce: 随机串，对应URL参数的nonce
        :return: 解密后的原文


<EOL>text = self.get_random_str() + struct.pack("<STR_LIT:I>", socket.htonl(len(text))) + to_binary(text) + appid<EOL>pkcs7 = PKCS7Encoder()<EOL>text = pkcs7.encode(text)<EOL>cryptor = AES.new(self.key, self.mode, self.key[:<NUM_LIT:16>])<EOL>try:<EOL><INDENT>ciphertext = cryptor.encrypt(text)<EOL>return base64.b64encode(ciphertext)<EOL><DEDENT>except Exception as e:<EOL><INDENT>raise EncryptAESError(e)<EOL><DEDENT>

对明文进行加密

        @param text: 需要加密的明文
        @return: 加密得到的字符串


try:<EOL><INDENT>cryptor = AES.new(self.key, self.mode, self.key[:<NUM_LIT:16>])<EOL>plain_text = cryptor.decrypt(base64.b64decode(text))<EOL><DEDENT>except Exception as e:<EOL><INDENT>raise DecryptAESError(e)<EOL><DEDENT>try:<EOL><INDENT>if six.PY2:<EOL><INDENT>pad = ord(plain_text[-<NUM_LIT:1>])<EOL><DEDENT>else:<EOL><INDENT>pad = plain_text[-<NUM_LIT:1>]<EOL><DEDENT>content = plain_text[<NUM_LIT:16>:-pad]<EOL>xml_len = socket.ntohl(struct.unpack("<STR_LIT:I>", content[: <NUM_LIT:4>])[<NUM_LIT:0>])<EOL>xml_content = content[<NUM_LIT:4>: xml_len + <NUM_LIT:4>]<EOL>from_appid = content[xml_len + <NUM_LIT:4>:]<EOL><DEDENT>except Exception as e:<EOL><INDENT>raise IllegalBuffer(e)<EOL><DEDENT>if from_appid != appid:<EOL><INDENT>raise ValidateAppIDError()<EOL><DEDENT>return xml_content<EOL>

对解密后的明文进行补位删除

        @param text: 密文
        @return: 删除填充补位后的明文


rule = string.ascii_letters + string.digits<EOL>return "<STR_LIT>".join(random.sample(rule, <NUM_LIT:16>))<EOL>

随机生成16位字符串

        @return: 16位字符串


text_length = len(text)<EOL>amount_to_pad = cls.block_size - (text_length % cls.block_size)<EOL>if amount_to_pad == <NUM_LIT:0>:<EOL><INDENT>amount_to_pad = cls.block_size<EOL><DEDENT>pad = to_binary(chr(amount_to_pad))<EOL>return text + pad * amount_to_pad<EOL>

对需要加密的明文进行填充补位
@param text: 需要进行填充补位操作的明文
@return: 补齐明文字符串


pad = ord(decrypted[-<NUM_LIT:1>])<EOL>if pad < <NUM_LIT:1> or pad > <NUM_LIT:32>:<EOL><INDENT>pad = <NUM_LIT:0><EOL><DEDENT>return decrypted[:-pad]<EOL>

删除解密后明文的补位字符
@param decrypted: 解密后的明文
@return: 删除补位字符后的明文


def get_sha1_signature(token, timestamp, nonce, encrypt):

try:<EOL><INDENT>sortlist = [token, timestamp, nonce, to_binary(encrypt)]<EOL>sortlist.sort()<EOL>sha = hashlib.sha1()<EOL>sha.update(to_binary("<STR_LIT>").join(sortlist))<EOL>return sha.hexdigest()<EOL><DEDENT>except Exception as e:<EOL><INDENT>raise CryptoComputeSignatureError(e)<EOL><DEDENT>

用 SHA1 算法生成安全签名
@param token: 票据
@param timestamp: 时间戳
@param encrypt: 密文
@param nonce: 随机字符串
@return: 安全签名


super(TextReply, self).__init__(message=message, content=content)<EOL>

:param message: WechatMessage 对象
:param content: 文字回复内容


super(ImageReply, self).__init__(message=message, media_id=media_id)<EOL>

:param message: WechatMessage 对象
:param media_id: 图片的 MediaID


super(VoiceReply, self).__init__(message=message, media_id=media_id)<EOL>

:param message: WechatMessage 对象
:param media_id: 语音的 MediaID


def __init__(self, message, media_id, title=None, description=None):

title = title or '<STR_LIT>'<EOL>description = description or '<STR_LIT>'<EOL>super(VideoReply, self).__init__(message=message, media_id=media_id, title=title, description=description)<EOL>

:param message: WechatMessage对象
:param media_id: 视频的 MediaID
:param title: 视频消息的标题
:param description: 视频消息的描述


super(GroupTransferReply, self).__init__(message=message)<EOL>


if not value:<EOL><INDENT>return '<STR_LIT>'<EOL><DEDENT>if isinstance(value, six.text_type):<EOL><INDENT>return value<EOL><DEDENT>if isinstance(value, six.binary_type):<EOL><INDENT>return value.decode(encoding)<EOL><DEDENT>return six.text_type(value)<EOL>

将 value 转为 unicode，默认编码 utf-8

    :param value: 待转换的值
    :param encoding: 编码


if not value:<EOL><INDENT>return b'<STR_LIT>'<EOL><DEDENT>if isinstance(value, six.binary_type):<EOL><INDENT>return value<EOL><DEDENT>if isinstance(value, six.text_type):<EOL><INDENT>return value.encode(encoding)<EOL><DEDENT>if six.PY3:<EOL><INDENT>return six.binary_type(str(value), encoding)  <EOL><DEDENT>return six.binary_type(value)<EOL>

将 values 转为 bytes，默认编码 utf-8

    :param value: 待转换的值
    :param encoding: 编码


try:<EOL><INDENT>import requests.packages.urllib3<EOL>requests.packages.urllib3.disable_warnings()<EOL><DEDENT>except Exception:<EOL><INDENT>pass<EOL><DEDENT>


return int(time.time())<EOL>

生成 timestamp
    :return: timestamp string


return random.randrange(<NUM_LIT>, <NUM_LIT>)<EOL>


table = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>}<EOL>if extension in table:<EOL><INDENT>return table[extension]<EOL><DEDENT>raise ValueError("<STR_LIT>")<EOL>

将扩展名转换为 MIME 格式
    :return: mime string


table = ('<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>')<EOL>if extension in table:<EOL><INDENT>return True<EOL><DEDENT>return False<EOL>

检查扩展名是否是可以上传到服务器
    :return: True if ok


raise NotImplementedError('<STR_LIT>')<EOL>


根据 openid 新建一个上下文对话存储


self.errcode = errcode<EOL>self.errmsg = errmsg<EOL>

:param errcode: 错误代码
:param errmsg: 错误信息


self.message = message<EOL>


self._source = source<EOL>self._load_source(source)<EOL>if pause:<EOL><INDENT>time.sleep(<NUM_LIT:0.5>)  <EOL>self.pause()<EOL><DEDENT>

Loads a new source (as a file) from ``source`` (a file path or URL)
by killing the current ``omxplayer`` process and forking a new one.

Args:
    source (string): Path to the file to play or URL


return self._root_interface_property('<STR_LIT>')<EOL>

Returns:
    bool: whether the player can quit or not


Returns:
    bool: whether the player is fullscreen or not


Returns:
    bool: whether the player can go fullscreen


Returns:
    bool: whether the player can raise the display window atop of all other windows


Returns:
    bool: whether the player has a track list or not


Returns:
    str: Returns `omxplayer`, the name of the player


Returns:
    str: list of supported URI schemes
Examples:
    >>> player.supported_uri_schemes()
    ["file", "http", "rtsp", "rtmp"]


return self._player_interface_property('<STR_LIT>')<EOL>

Returns:
    bool: whether the player can move to the next item in the playlist


Returns:
    bool: whether the player can move to the previous item in the
          playlist


Returns:
    bool: whether the player can seek


Returns:
    bool: whether the player can be controlled


Returns:
    bool: whether the player can play


Returns:
    bool: whether the player can pause


Returns:
    str: one of ("Playing" | "Paused" | "Stopped")


if self._is_muted:<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>return self._player_interface_property('<STR_LIT>')<EOL>

Returns:
    float: current player volume


<EOL>if volume == <NUM_LIT:0>:<EOL><INDENT>volume = <NUM_LIT><EOL><DEDENT>return self._player_interface_property('<STR_LIT>', dbus.Double(volume))<EOL>

Args:
    float: volume in the interval [0, 10]


Returns:
    int: position in microseconds


return self._position_us() / (<NUM_LIT> * <NUM_LIT>)<EOL>


Returns:
    float: minimum playback rate (as proportion of normal rate)


Returns:
    float: maximum playback rate (as proportion of normal rate)


return self._rate<EOL>

Returns:
    float: playback rate, 1 is the normal rate, 2 would be double speed.


self._rate = self._player_interface_property('<STR_LIT>', dbus.Double(rate))<EOL>return self._rate<EOL>

Set the playback rate of the video as a multiple of the default playback speed

Examples:
    >>> player.set_rate(2)
    # Will play twice as fast as normal speed
    >>> player.set_rate(0.5)
    # Will play half speed


Returns:
    dict: containing track information ('URI', 'length')
Examples:
    >>> player.metadata()
    {
        'mpris:length': 19691000,
        'xesam:url': 'file:///home/name/path/to/media/file.mp4'
    }


Returns:
    int: number of video streams


Returns:
    int: total length in microseconds


return self._duration_us() / (<NUM_LIT> * <NUM_LIT>)<EOL>


self._player_interface.Pause()<EOL>self._is_playing = False<EOL>self.pauseEvent(self)<EOL>


self._player_interface.PlayPause()<EOL>self._is_playing = not self._is_playing<EOL>if self._is_playing:<EOL><INDENT>self.playEvent(self)<EOL><DEDENT>else:<EOL><INDENT>self.pauseEvent(self)<EOL><DEDENT>

Pause playback if currently playing, otherwise start playing if currently paused.


self._player_interface.Stop()<EOL>self.stopEvent(self)<EOL>


self._player_interface.Seek(Int64(<NUM_LIT> * <NUM_LIT:1000> * relative_position))<EOL>self.seekEvent(self, relative_position)<EOL>

Seek the video by `relative_position` seconds

Args:
    relative_position (float): The position in seconds to seek to.


self._player_interface.SetPosition(ObjectPath("<STR_LIT>"), Int64(position * <NUM_LIT> * <NUM_LIT:1000>))<EOL>self.positionEvent(self, position)<EOL>

Set the video to playback position to `position` seconds from the start of the video

Args:
    position (float): The position in seconds.


self._player_interface.SetAlpha(ObjectPath('<STR_LIT>'), Int64(alpha))<EOL>

Set the transparency of the video overlay

Args:
    alpha (float): The transparency (0..255)


self._is_muted = True<EOL>self._player_interface.Mute()<EOL>

Mute audio. If already muted, then this does not do anything


self._is_muted = False<EOL>self._player_interface.Unmute()<EOL>

Unmutes the video. If already unmuted, then this does not do anything


self._player_interface.SetAspectMode(ObjectPath('<STR_LIT>'), String(mode))<EOL>

Set the aspect mode of the video

Args:
    mode (str): One of ("letterbox" | "fill" | "stretch")


@_check_player_is_active<EOL><INDENT>@_from_dbus_type<EOL>def set_video_pos(self, x1, y1, x2, y2):<DEDENT>

position = "<STR_LIT>" % (str(x1),str(y1),str(x2),str(y2))<EOL>self._player_interface.VideoPos(ObjectPath('<STR_LIT>'), String(position))<EOL>

Set the video position on the screen

Args:
    x1 (int): Top left x coordinate (px)
    y1 (int): Top left y coordinate (px)
    x2 (int): Bottom right x coordinate (px)
    y2 (int): Bottom right y coordinate (px)


position_string = self._player_interface.VideoPos(ObjectPath('<STR_LIT>'))<EOL>return list(map(int, position_string.split("<STR_LIT:U+0020>")))<EOL>

Returns:
    (int, int, int, int): Video spatial position (x1, y1, x2, y2) where (x1, y1) is top left,
                          and (x2, y2) is bottom right. All values in px.


@_check_player_is_active<EOL><INDENT>@_from_dbus_type<EOL>def set_video_crop(self, x1, y1, x2, y2):<DEDENT>

crop = "<STR_LIT>" % (str(x1),str(y1),str(x2),str(y2))<EOL>self._player_interface.SetVideoCropPos(ObjectPath('<STR_LIT>'), String(crop))<EOL>

Args:
    x1 (int): Top left x coordinate (px)
    y1 (int): Top left y coordinate (px)
    x2 (int): Bottom right x coordinate (px)
    y2 (int): Bottom right y coordinate (px)


self._player_interface.UnHideVideo()<EOL>

Shows the video (to undo a `hide_video`)


return self._player_interface.ListAudio()<EOL>

Returns:
    [str]: A list of all known audio streams, each item is in the
           format: ``<index>:<language>:<name>:<codec>:<active>``


return self._player_interface.ListVideo()<EOL>

Returns:
    [str]: A list of all known video streams, each item is in the
           format: ``<index>:<language>:<name>:<codec>:<active>``


return self._player_interface.ListSubtitles()<EOL>

Returns:
    [str]: A list of all known subtitles, each item is in the
           format: ``<index>:<language>:<name>:<codec>:<active>``


return self._player_interface.SelectSubtitle(dbus.Int32(index))<EOL>

Enable a subtitle specified by the index it is listed in :class:`list_subtitles`

Args:
    index (int): index of subtitle listing returned by :class:`list_subtitles`


return self._player_interface.SelectAudio(dbus.Int32(index))<EOL>

Select audio stream specified by the index of the stream in :class:`list_audio`

Args:
    index (int): index of audio stream returned by :class:`list_audio`


return self._player_interface.ShowSubtitles()<EOL>

Shows subtitles after :class:`hide_subtitles`


return self._player_interface.HideSubtitles()<EOL>


self._player_interface.Action(code)<EOL>

Executes a keyboard command via a code

Args:
    code (int): The key code you wish to emulate
                refer to ``keys.py`` for the possible keys


self._is_playing = (self.playback_status() == "<STR_LIT>")<EOL>logger.info("<STR_LIT>" % self._is_playing)<EOL>return self._is_playing<EOL>

Returns:
    bool: Whether the player is playing


Play the video and block whilst the video is playing


if not self.is_playing():<EOL><INDENT>self.play_pause()<EOL>self._is_playing = True<EOL>self.playEvent(self)<EOL><DEDENT>

Play the video asynchronously returning control immediately to the calling code


return self._player_interface.Next()<EOL>

Skip to the next chapter

Returns:
    bool: Whether the player skipped to the next chapter


return self._player_interface.Previous()<EOL>

Skip to the previous chapter

Returns:
    bool: Whether the player skipped to the previous chapter


if self._process is None:<EOL><INDENT>logger.debug('<STR_LIT>')<EOL>return<EOL><DEDENT>try:<EOL><INDENT>logger.debug('<STR_LIT>')<EOL>process_group_id = os.getpgid(self._process.pid)<EOL>os.killpg(process_group_id, signal.SIGTERM)<EOL>logger.debug('<STR_LIT>' % process_group_id)<EOL>self._process_monitor.join()<EOL><DEDENT>except OSError:<EOL><INDENT>logger.error('<STR_LIT>')<EOL><DEDENT>self._process = None<EOL>

Quit the player, blocking until the process has died


return self._source<EOL>

Get the source URI of the currently playing media

Returns:
    str: source currently playing


return self.get_source()<EOL>

Returns:
    str: source currently playing

.. deprecated:: 0.2.0
   Use: :func:`get_source` instead.


possible_address_files = []<EOL>while not possible_address_files:<EOL><INDENT>isnt_pid_file = lambda path: not path.endswith('<STR_LIT>')<EOL>possible_address_files = list(filter(isnt_pid_file,<EOL>glob('<STR_LIT>')))<EOL>possible_address_files.sort(key=lambda path: os.path.getmtime(path))<EOL>time.sleep(<NUM_LIT>)<EOL><DEDENT>self.path = possible_address_files[-<NUM_LIT:1>]<EOL>

Finds the OMXPlayer DBus connection
Assumes there is an alive OMXPlayer process.
:return:


@wraps(f)<EOL>def wrapper(*args, **kwargs):<EOL><INDENT>raise_exception = kwargs.pop('<STR_LIT>', False)<EOL>try:<EOL><INDENT>return f(*args, **kwargs)<EOL><DEDENT>except KeyboardInterrupt:<EOL><INDENT>if not raise_exception:<EOL><INDENT>sys.exit()<EOL><DEDENT>raise KeyboardInterrupt<EOL><DEDENT><DEDENT>return wrapper<EOL>

Decorator that allows user to exit script by sending a keyboard interrupt
    (ctrl + c) without raising an exception.


if op in self.OPERATORS:<EOL><INDENT>return self.OPERATORS.get(op)<EOL><DEDENT>try:<EOL><INDENT>n_args = len(inspect.getargspec(op)[<NUM_LIT:0>])<EOL>if n_args != <NUM_LIT:2>:<EOL><INDENT>raise TypeError<EOL><DEDENT><DEDENT>except:<EOL><INDENT>eprint('<STR_LIT>')<EOL>raise<EOL><DEDENT>else:<EOL><INDENT>return op<EOL><DEDENT>

Assigns function to the operators property of the instance.


if is_string(prompter):<EOL><INDENT>if prompter not in prompters:<EOL><INDENT>eprint("<STR_LIT>".format(prompter))<EOL>sys.exit()<EOL><DEDENT>self.prompter = prompters[prompter]<EOL><DEDENT>else:<EOL><INDENT>self.prompter = prompter<EOL><DEDENT>

If you want to change the core prompters registry, you can
        override this method in a Question subclass.


if '<STR_LIT>' in kwargs and isinstance(kwargs['<STR_LIT>'], Question):<EOL><INDENT>question = kwargs['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>question = Question(*args, **kwargs)<EOL><DEDENT>self.questions.setdefault(question.key, []).append(question)<EOL>return question<EOL>

Add a Question instance to the questions dict. Each key points
        to a list of Question instances with that key. Use the `question`
        kwarg to pass a Question instance if you want, or pass in the same
        args you would pass to instantiate a question.


return self.questions.pop(key)<EOL>

Remove all questions associated with `key`. Raises exception if `key`
        doesn't exist.


while not self.done:<EOL><INDENT>self.ask()<EOL><DEDENT>return self.answers<EOL>

Asks all remaining questions in the questionnaire, returns the answers.


q = self.next_question<EOL>if q is None:<EOL><INDENT>return<EOL><DEDENT>try:<EOL><INDENT>answer = q.prompter(self.get_prompt(q, error), *q.prompter_args, **q.prompter_kwargs)<EOL><DEDENT>except QuestionnaireGoBack as e:<EOL><INDENT>steps = e.args[<NUM_LIT:0>] if e.args else <NUM_LIT:1><EOL>if steps == <NUM_LIT:0>:<EOL><INDENT>self.ask()  <EOL>return<EOL><DEDENT>self.go_back(steps)<EOL><DEDENT>else:<EOL><INDENT>if q._validate:<EOL><INDENT>error = q._validate(answer)<EOL>if error:<EOL><INDENT>self.ask(error)<EOL>return<EOL><DEDENT><DEDENT>if q._transform:<EOL><INDENT>answer = q._transform(answer)<EOL><DEDENT>self.answers[q.key] = answer<EOL>return answer<EOL><DEDENT>

Asks the next question in the questionnaire and returns the answer,
        unless user goes back.


for key, questions in self.questions.items():<EOL><INDENT>if key in self.answers:<EOL><INDENT>continue<EOL><DEDENT>for question in questions:<EOL><INDENT>if self.check_condition(question._condition):<EOL><INDENT>return question<EOL><DEDENT><DEDENT><DEDENT>return None<EOL>

Returns the next `Question` in the questionnaire, or `None` if there
        are no questions left. Returns first question for whose key there is no
        answer and for which condition is satisfied, or for which there is no
        condition.


if not condition:<EOL><INDENT>return True<EOL><DEDENT>for c in condition.conditions:<EOL><INDENT>key, value, operator = c<EOL>if not operator(self.answers[key], value):<EOL><INDENT>return False<EOL><DEDENT><DEDENT>return True<EOL>

Helper that returns True if condition is satisfied/doesn't exist.


if not self.can_go_back:<EOL><INDENT>return<EOL><DEDENT>N = max(len(self.answers)-abs(n), <NUM_LIT:0>)<EOL>self.answers = OrderedDict(islice(self.answers.items(), N))<EOL>

Move `n` questions back in the questionnaire by removing the last `n`
        answers.


fmts = ('<STR_LIT>', '<STR_LIT>', '<STR_LIT>')<EOL>if fmt not in fmts:<EOL><INDENT>eprint("<STR_LIT>".format(fmt, fmts))<EOL>return<EOL><DEDENT>def stringify(val):<EOL><INDENT>if type(val) in (list, tuple):<EOL><INDENT>return '<STR_LIT:U+002CU+0020>'.join(str(e) for e in val)<EOL><DEDENT>return val<EOL><DEDENT>if fmt == '<STR_LIT>':<EOL><INDENT>return json.dumps(self.answers)<EOL><DEDENT>elif fmt == '<STR_LIT>':<EOL><INDENT>answers = [[k, v] for k, v in self.answers.items()]<EOL>return json.dumps(answers)<EOL><DEDENT>elif fmt == '<STR_LIT>':<EOL><INDENT>answers = '<STR_LIT:\n>'.join('<STR_LIT>'.format(k, stringify(v)) for k, v in self.answers.items())<EOL>return answers<EOL><DEDENT>


padding = len(max(self.questions.keys(), key=len)) + <NUM_LIT:5><EOL>for key in list(self.answers.keys()):<EOL><INDENT>s += '<STR_LIT>'.format(key, padding, self.answers[key])<EOL><DEDENT>return s<EOL>

Helper method for displaying the answers so far.


def decorate(func):<EOL><INDENT>prompters[key] = func<EOL>return func<EOL><DEDENT>return decorate<EOL>

Add decorated functions to prompters dict.


@register(key='<STR_LIT>')<EOL>def one(prompt, *args, **kwargs):

indicator = '<STR_LIT>'<EOL>if sys.version_info < (<NUM_LIT:3>, <NUM_LIT:0>):<EOL><INDENT>indicator = '<STR_LIT:>>'<EOL><DEDENT>def go_back(picker):<EOL><INDENT>return None, -<NUM_LIT:1><EOL><DEDENT>options, verbose_options = prepare_options(args)<EOL>idx = kwargs.get('<STR_LIT>', <NUM_LIT:0>)<EOL>picker = Picker(verbose_options, title=prompt, indicator=indicator, default_index=idx)<EOL>picker.register_custom_handler(ord('<STR_LIT:h>'), go_back)<EOL>picker.register_custom_handler(curses.KEY_LEFT, go_back)<EOL>with stdout_redirected(sys.stderr):<EOL><INDENT>option, index = picker.start()<EOL>if index == -<NUM_LIT:1>:<EOL><INDENT>raise QuestionnaireGoBack<EOL><DEDENT>if kwargs.get('<STR_LIT>', False):<EOL><INDENT>return index<EOL><DEDENT>return options[index]<EOL><DEDENT>

Instantiates a picker, registers custom handlers for going back,
    and starts the picker.


@register(key='<STR_LIT>')<EOL>def many(prompt, *args, **kwargs):

def get_options(options, chosen):<EOL><INDENT>return [options[i] for i, c in enumerate(chosen) if c]<EOL><DEDENT>def get_verbose_options(verbose_options, chosen):<EOL><INDENT>no, yes = '<STR_LIT:U+0020>', '<STR_LIT>'<EOL>if sys.version_info < (<NUM_LIT:3>, <NUM_LIT:3>):<EOL><INDENT>no, yes = '<STR_LIT:U+0020>', '<STR_LIT:@>'<EOL><DEDENT>opts = ['<STR_LIT>'.format(yes if c else no, verbose_options[i]) for i, c in enumerate(chosen)]<EOL>return opts + ['<STR_LIT>'.format('<STR_LIT:U+0020>', kwargs.get('<STR_LIT>', '<STR_LIT>'))]<EOL><DEDENT>options, verbose_options = prepare_options(args)<EOL>chosen = [False] * len(options)<EOL>index = kwargs.get('<STR_LIT>', <NUM_LIT:0>)<EOL>default = kwargs.get('<STR_LIT:default>', None)<EOL>if isinstance(default, list):<EOL><INDENT>for idx in default:<EOL><INDENT>chosen[idx] = True<EOL><DEDENT><DEDENT>if isinstance(default, int):<EOL><INDENT>chosen[default] = True<EOL><DEDENT>while True:<EOL><INDENT>try:<EOL><INDENT>index = one(prompt, *get_verbose_options(verbose_options, chosen), return_index=True, idx=index)<EOL><DEDENT>except QuestionnaireGoBack:<EOL><INDENT>if any(chosen):<EOL><INDENT>raise QuestionnaireGoBack(<NUM_LIT:0>)<EOL><DEDENT>else:<EOL><INDENT>raise QuestionnaireGoBack<EOL><DEDENT><DEDENT>if index == len(options):<EOL><INDENT>return get_options(options, chosen)<EOL><DEDENT>chosen[index] = not chosen[index]<EOL><DEDENT>

Calls `pick` in a while loop to allow user to pick many
    options. Returns a list of chosen options.


options_, verbose_options = [], []<EOL>for option in options:<EOL><INDENT>if is_string(option):<EOL><INDENT>options_.append(option)<EOL>verbose_options.append(option)<EOL><DEDENT>else:<EOL><INDENT>options_.append(option[<NUM_LIT:0>])<EOL>verbose_options.append(option[<NUM_LIT:1>])<EOL><DEDENT><DEDENT>return options_, verbose_options<EOL>

Create options and verbose options from strings and non-string iterables in
    `options` array.


@register(key='<STR_LIT>')<EOL>def raw(prompt, *args, **kwargs):

go_back = kwargs.get('<STR_LIT>', '<STR_LIT:<>')<EOL>type_ = kwargs.get('<STR_LIT:type>', str)<EOL>default = kwargs.get('<STR_LIT:default>', '<STR_LIT>')<EOL>with stdout_redirected(sys.stderr):<EOL><INDENT>while True:<EOL><INDENT>try:<EOL><INDENT>if kwargs.get('<STR_LIT>', False):<EOL><INDENT>answer = getpass.getpass(prompt)<EOL><DEDENT>elif sys.version_info < (<NUM_LIT:3>, <NUM_LIT:0>):<EOL><INDENT>answer = raw_input(prompt)<EOL><DEDENT>else:<EOL><INDENT>answer = input(prompt)<EOL><DEDENT>if not answer:<EOL><INDENT>answer = default<EOL><DEDENT>if answer == go_back:<EOL><INDENT>raise QuestionnaireGoBack<EOL><DEDENT>return type_(answer)<EOL><DEDENT>except ValueError:<EOL><INDENT>eprint('<STR_LIT>'.format(answer, type_))<EOL><DEDENT><DEDENT><DEDENT>

Calls input to allow user to input an arbitrary string. User can go
    back by entering the `go_back` string. Works in both Python 2 and 3.


stdout = sys.stdout<EOL>stdout_fd = fileno(stdout)<EOL>with os.fdopen(os.dup(stdout_fd), '<STR_LIT:wb>') as copied:<EOL><INDENT>stdout.flush()  <EOL>try:<EOL><INDENT>os.dup2(fileno(to), stdout_fd)  <EOL><DEDENT>except ValueError:  <EOL><INDENT>with open(to, '<STR_LIT:wb>') as to_file:<EOL><INDENT>os.dup2(to_file.fileno(), stdout_fd)  <EOL><DEDENT><DEDENT>try:<EOL><INDENT>yield stdout  <EOL><DEDENT>finally:<EOL><INDENT>stdout.flush()<EOL>os.dup2(copied.fileno(), stdout_fd)<EOL><DEDENT><DEDENT>

Lifted from: https://stackoverflow.com/questions/4675728/redirect-stdout-to-a-file-in-python

    This is the only way I've found to redirect stdout with curses. This way the
    output from questionnaire can be piped to another program, without piping
    what's written to the terminal by the prompters.


def decorator(func):<EOL><INDENT>@functools.wraps(func)<EOL>def wrapper(*args, **kwds):<EOL><INDENT>try:<EOL><INDENT>oldcwd = os.getcwd()<EOL>repo_root = os.path.dirname(test_dir)<EOL>os.chdir(os.path.join(repo_root, path))<EOL>return func(*args, **kwds)<EOL><DEDENT>finally:<EOL><INDENT>os.chdir(oldcwd)<EOL><DEDENT><DEDENT>return wrapper<EOL><DEDENT>return decorator<EOL>

Decorator to run function at `path`.

:type path: str
:arg path: relative path from repository root (e.g., 'pyqode' or 'test').


def decorator(func):<EOL><INDENT>@functools.wraps(func)<EOL>def wrapper(*args, **kwds):<EOL><INDENT>try:<EOL><INDENT>return func(*args, **kwds)<EOL><DEDENT>finally:<EOL><INDENT>try:<EOL><INDENT>os.remove(path)<EOL><DEDENT>except (IOError, OSError):<EOL><INDENT>pass<EOL><DEDENT><DEDENT><DEDENT>return wrapper<EOL><DEDENT>return decorator<EOL>


pass<EOL>


self.recent_files_manager = widgets.RecentFilesManager(<EOL>'<STR_LIT>', '<STR_LIT>')<EOL>self.menu_recents = widgets.MenuRecentFiles(<EOL>self.menuFile, title='<STR_LIT>',<EOL>recent_files_manager=self.recent_files_manager)<EOL>self.menu_recents.open_requested.connect(self.open_file)<EOL>self.menuFile.insertMenu(self.actionSave, self.menu_recents)<EOL>self.menuFile.insertSeparator(self.actionSave)<EOL>


self.tabWidget.closeEvent(QCloseEvent)<EOL>

Delegates the close event to the tabWidget to be sure we do not quit
the application while there are some still some unsaved tabs.


Setup the python editor, run the server and connect a few signals.

:param editor: editor to setup.


editor = None<EOL>if path:<EOL><INDENT>interpreter, pyserver, args = self._get_backend_parameters()<EOL>editor = self.tabWidget.open_document(<EOL>path, None, interpreter=interpreter, server_script=pyserver,<EOL>args=args)<EOL>if editor:<EOL><INDENT>self.setup_editor(editor)<EOL><DEDENT>self.recent_files_manager.open_file(path)<EOL>self.menu_recents.update_actions()<EOL><DEDENT>if line is not None:<EOL><INDENT>TextHelper(self.tabWidget.current_widget()).goto_line(line)<EOL><DEDENT>return editor<EOL>

Creates a new GenericCodeEdit, opens the requested file and adds it
to the tab widget.

:param path: Path of the file to open

:return The opened editor if open succeeded.


frozen = hasattr(sys, '<STR_LIT>')<EOL>interpreter = Settings().interpreter<EOL>if frozen:<EOL><INDENT>interpreter = None<EOL><DEDENT>pyserver = server.__file__ if interpreter is not None else '<STR_LIT>'<EOL>args = []<EOL>return interpreter, pyserver, args<EOL>

Gets the pyqode backend parameters (interpreter and script).


interpreter, pyserver, args = self._get_backend_parameters()<EOL>self.setup_editor(self.tabWidget.create_new_document(<EOL>extension='<STR_LIT>', interpreter=interpreter, server_script=pyserver,<EOL>args=args))<EOL>self.actionRun.setDisabled(True)<EOL>self.actionConfigure_run.setDisabled(True)<EOL>

Add a new empty code editor to the tab widget


filename, filter = QtWidgets.QFileDialog.getOpenFileName(self, '<STR_LIT>')<EOL>if filename:<EOL><INDENT>self.open_file(filename)<EOL><DEDENT>self.actionRun.setEnabled(True)<EOL>self.actionConfigure_run.setEnabled(True)<EOL>

Shows an open file dialog and open the file if the dialog was
accepted.


path = self.tabWidget.current_widget().file.path<EOL>path = os.path.dirname(path) if path else '<STR_LIT>'<EOL>filename, filter = QtWidgets.QFileDialog.getSaveFileName(<EOL>self, '<STR_LIT>', path)<EOL>if filename:<EOL><INDENT>self.tabWidget.save_current(filename)<EOL>self.recent_files_manager.open_file(filename)<EOL>self.menu_recents.update_actions()<EOL>self.actionRun.setEnabled(True)<EOL>self.actionConfigure_run.setEnabled(True)<EOL>self._update_status_bar(self.tabWidget.current_widget())<EOL><DEDENT>


self.menuEdit.addActions(editor.actions())<EOL>self.menuEdit.addSeparator()<EOL>self.setup_mnu_style(editor)<EOL>

Setup the edit menu for the current editor. We show the current editor
context menu and a menu to change the python interpreter.

:param editor: new editor


menu = QtWidgets.QMenu('<STR_LIT>', self.menuEdit)<EOL>group = QtWidgets.QActionGroup(self)<EOL>self.styles_group = group<EOL>current_style = editor.syntax_highlighter.color_scheme.name<EOL>group.triggered.connect(self.on_style_changed)<EOL>for s in sorted(PYGMENTS_STYLES):<EOL><INDENT>a = QtWidgets.QAction(menu)<EOL>a.setText(s)<EOL>a.setCheckable(True)<EOL>if s == current_style:<EOL><INDENT>a.setChecked(True)<EOL><DEDENT>group.addAction(a)<EOL>menu.addAction(a)<EOL><DEDENT>self.menuEdit.addMenu(menu)<EOL>


for panel in editor.panels:<EOL><INDENT>if panel.dynamic:<EOL><INDENT>continue<EOL><DEDENT>a = QtWidgets.QAction(self.menuModes)<EOL>a.setText(panel.name)<EOL>a.setCheckable(True)<EOL>a.setChecked(panel.enabled)<EOL>a.changed.connect(self.on_panel_state_changed)<EOL>a.panel = weakref.proxy(panel)<EOL>self.menuPanels.addAction(a)<EOL><DEDENT>

Setup the panels menu for the current editor.
:param editor:


self.menuEdit.clear()<EOL>self.menuModes.clear()<EOL>self.menuPanels.clear()<EOL>editor = self.tabWidget.current_widget()<EOL>self.menuEdit.setEnabled(editor is not None)<EOL>self.menuModes.setEnabled(editor is not None)<EOL>self.menuPanels.setEnabled(editor is not None)<EOL>self.actionSave.setEnabled(editor is not None)<EOL>self.actionSave_as.setEnabled(editor is not None)<EOL>self.actionConfigure_run.setEnabled(editor is not None)<EOL>self.actionRun.setEnabled(editor is not None)<EOL>if editor is not None:<EOL><INDENT>self.setup_mnu_edit(editor)<EOL>self.setup_mnu_modes(editor)<EOL>self.setup_mnu_panels(editor)<EOL><DEDENT>self.widgetOutline.set_editor(editor)<EOL>self._update_status_bar(editor)<EOL>

Update action states when the current tab changed.


action = self.sender()<EOL>action.panel.enabled = action.isChecked()<EOL>action.panel.setVisible(action.isChecked())<EOL>


action = self.sender()<EOL>action.mode.enabled = action.isChecked()<EOL>


QtWidgets.QMessageBox.about(<EOL>self, '<STR_LIT>',<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')<EOL>


filename = self.tabWidget.current_widget().file.path<EOL>wd = os.path.dirname(filename)<EOL>args = Settings().get_run_config_for_file(filename)<EOL>self.interactiveConsole.start_process(<EOL>Settings().interpreter, args=[filename] + args, cwd=wd)<EOL>self.dockWidget.show()<EOL>self.actionRun.setEnabled(False)<EOL>self.actionConfigure_run.setEnabled(False)<EOL>


editor = self.open_file(assignment.module_path)<EOL>if editor:<EOL><INDENT>TextHelper(editor).goto_line(assignment.line, assignment.column)<EOL><DEDENT>

Open the a new tab when goto goes out of the current document.

:param assignment: Destination


string = self.settings.value('<STR_LIT>', '<STR_LIT:{}>')<EOL>return json.loads(string)<EOL>

Returns the dictionary of run configurations. A run configuration is
just a list of arguments to append to the run command.

This is internally stored as a json object


with open("<STR_LIT>") as f:<EOL><INDENT>lines = f.read().splitlines()<EOL>for l in lines:<EOL><INDENT>if "<STR_LIT>" in l:<EOL><INDENT>return l.split("<STR_LIT:=>")[<NUM_LIT:1>].strip().replace('<STR_LIT:">', "<STR_LIT>")<EOL><DEDENT><DEDENT><DEDENT>

Reads the version without self importing


def detect_fold_level(self, prev_block, block):

<EOL>lvl = super(PythonFoldDetector, self).detect_fold_level(<EOL>prev_block, block)<EOL>prev_lvl = TextBlockHelper.get_fold_lvl(prev_block)<EOL>if prev_block and lvl > prev_lvl and not (<EOL>self._strip_comments(prev_block).endswith('<STR_LIT::>')):<EOL><INDENT>lvl = prev_lvl<EOL><DEDENT>lvl = self._handle_docstrings(block, lvl, prev_block)<EOL>lvl = self._handle_imports(block, lvl, prev_block)<EOL>return lvl<EOL>

Perfoms fold level detection for current block (take previous block
into account).

:param prev_block: previous block, None if `block` is the first block.
:param block: block to analyse.
:return: block fold level


return "<STR_LIT>" % name + "<STR_LIT:|>".join(alternates) + "<STR_LIT:)>"<EOL>

Return a named group pattern matching list of alternates.


kw = r"<STR_LIT>" + any("<STR_LIT>", kwlist + additional_keywords) + r"<STR_LIT>"<EOL>kw_namespace = r"<STR_LIT>" + any("<STR_LIT>", kw_namespace_list) + r"<STR_LIT>"<EOL>word_operators = r"<STR_LIT>" + any("<STR_LIT>", wordop_list) + r"<STR_LIT>"<EOL>builtinlist = [str(name) for name in dir(builtins)<EOL>if not name.startswith('<STR_LIT:_>')] + additional_builtins<EOL>for v in ['<STR_LIT:None>', '<STR_LIT:True>', '<STR_LIT:False>']:<EOL><INDENT>builtinlist.remove(v)<EOL><DEDENT>builtin = r"<STR_LIT>" + any("<STR_LIT>", builtinlist) + r"<STR_LIT>"<EOL>builtin_fct = any("<STR_LIT>", [r'<STR_LIT>'])<EOL>comment = any("<STR_LIT>", [r"<STR_LIT>"])<EOL>instance = any("<STR_LIT>", [r"<STR_LIT>", r"<STR_LIT>"])<EOL>decorator = any('<STR_LIT>', [r'<STR_LIT>', r'<STR_LIT>'])<EOL>number = any("<STR_LIT>",<EOL>[r"<STR_LIT>",<EOL>r"<STR_LIT>",<EOL>r"<STR_LIT>",<EOL>r"<STR_LIT>",<EOL>r"<STR_LIT>"])<EOL>sqstring = r"<STR_LIT>"<EOL>dqstring = r'<STR_LIT>'<EOL>uf_sqstring = r"<STR_LIT>"<EOL>uf_dqstring = r'<STR_LIT>'<EOL>sq3string = r"<STR_LIT>"<EOL>dq3string = r'<STR_LIT>'<EOL>uf_sq3string = r"<STR_LIT>"<EOL>uf_dq3string = r'<STR_LIT>'<EOL>string = any("<STR_LIT:string>", [sq3string, dq3string, sqstring, dqstring])<EOL>ufstring1 = any("<STR_LIT>", [uf_sqstring])<EOL>ufstring2 = any("<STR_LIT>", [uf_dqstring])<EOL>ufstring3 = any("<STR_LIT>", [uf_sq3string])<EOL>ufstring4 = any("<STR_LIT>", [uf_dq3string])<EOL>return "<STR_LIT:|>".join([instance, decorator, kw, kw_namespace, builtin,<EOL>word_operators, builtin_fct, comment,<EOL>ufstring1, ufstring2, ufstring3, ufstring4, string,<EOL>number, any("<STR_LIT>", [r"<STR_LIT:\n>"])])<EOL>

Strongly inspired from idlelib.ColorDelegator.make_pat


def _handle_indent_between_paren(self, column, line, parent_impl, tc):

pre, post = parent_impl<EOL>next_char = self._get_next_char(tc)<EOL>prev_char = self._get_prev_char(tc)<EOL>prev_open = prev_char in ['<STR_LIT:[>', '<STR_LIT:(>', '<STR_LIT:{>']<EOL>next_close = next_char in ['<STR_LIT:]>', '<STR_LIT:)>', '<STR_LIT:}>']<EOL>(open_line, open_symbol_col), (close_line, close_col) =self._get_paren_pos(tc, column)<EOL>open_line_txt = self._helper.line_text(open_line)<EOL>open_line_indent = len(open_line_txt) - len(open_line_txt.lstrip())<EOL>if prev_open:<EOL><INDENT>post = (open_line_indent + self.editor.tab_length) * '<STR_LIT:U+0020>'<EOL><DEDENT>elif next_close and prev_char != '<STR_LIT:U+002C>':<EOL><INDENT>post = open_line_indent * '<STR_LIT:U+0020>'<EOL><DEDENT>elif tc.block().blockNumber() == open_line:<EOL><INDENT>post = open_symbol_col * '<STR_LIT:U+0020>'<EOL><DEDENT>if close_line and close_col:<EOL><INDENT>txt = self._helper.line_text(close_line)<EOL>bn = tc.block().blockNumber()<EOL>flg = bn == close_line<EOL>next_indent = self._helper.line_indent(bn + <NUM_LIT:1>) * '<STR_LIT:U+0020>'<EOL>if flg and txt.strip().endswith('<STR_LIT::>') and next_indent == post:<EOL><INDENT>post += self.editor.tab_length * '<STR_LIT:U+0020>'<EOL><DEDENT><DEDENT>if next_char in ['<STR_LIT:">', "<STR_LIT:'>"]:<EOL><INDENT>tc.movePosition(tc.Left)<EOL><DEDENT>is_string = self._helper.is_comment_or_string(tc, formats=['<STR_LIT:string>'])<EOL>if next_char in ['<STR_LIT:">', "<STR_LIT:'>"]:<EOL><INDENT>tc.movePosition(tc.Right)<EOL><DEDENT>if is_string:<EOL><INDENT>trav = QTextCursor(tc)<EOL>while self._helper.is_comment_or_string(<EOL>trav, formats=['<STR_LIT:string>']):<EOL><INDENT>trav.movePosition(trav.Left)<EOL><DEDENT>trav.movePosition(trav.Right)<EOL>symbol = '<STR_LIT:%s>' % self._get_next_char(trav)<EOL>pre += symbol<EOL>post += symbol<EOL><DEDENT>return pre, post<EOL>

Handle indent between symbols such as parenthesis, braces,...


if tc.atBlockStart():<EOL><INDENT>return True<EOL><DEDENT>column = tc.columnNumber()<EOL>indentation = len(line) - len(line.lstrip())<EOL>return column <= indentation<EOL>

Improve QTextCursor.atBlockStart to ignore spaces


return self._tab_always_indent<EOL>

When this flag is set to True, any call to indent will indent the whole
line instead of inserting a tab at the cursor position.


if not self.tab_always_indent:<EOL><INDENT>super(PyIndenterMode, self).indent()<EOL><DEDENT>else:<EOL><INDENT>cursor = self.editor.textCursor()<EOL>assert isinstance(cursor, QtGui.QTextCursor)<EOL>if cursor.hasSelection():<EOL><INDENT>self.indent_selection(cursor)<EOL><DEDENT>else:<EOL><INDENT>tab_len = self.editor.tab_length<EOL>cursor.beginEditBlock()<EOL>if self.editor.use_spaces_instead_of_tabs:<EOL><INDENT>cursor.insertText(tab_len * "<STR_LIT:U+0020>")<EOL><DEDENT>else:<EOL><INDENT>cursor.insertText('<STR_LIT:\t>')<EOL><DEDENT>cursor.endEditBlock()<EOL>self.editor.setTextCursor(cursor)<EOL><DEDENT><DEDENT>


if self.tab_always_indent:<EOL><INDENT>cursor = self.editor.textCursor()<EOL>if not cursor.hasSelection():<EOL><INDENT>cursor.select(cursor.LineUnderCursor)<EOL><DEDENT>self.unindent_selection(cursor)<EOL><DEDENT>else:<EOL><INDENT>super(PyIndenterMode, self).unindent()<EOL><DEDENT>


Called when the mode is activated/deactivated


cursor = self.editor.textCursor()<EOL>indent, comment, nb_lines = self.get_operation()<EOL>has_selection = cursor.hasSelection()<EOL>if nb_lines > <NUM_LIT:1>:<EOL><INDENT>self._move_cursor_to_selection_start(cursor)<EOL>cursor.beginEditBlock()<EOL>for i in range(nb_lines):<EOL><INDENT>self.comment_line(indent, cursor, comment)<EOL>cursor.movePosition(cursor.NextBlock)<EOL><DEDENT>cursor.endEditBlock()<EOL><DEDENT>else:<EOL><INDENT>cursor.beginEditBlock()<EOL>self.comment_line(indent, cursor, comment)<EOL>if not has_selection:<EOL><INDENT>cursor.movePosition(cursor.NextBlock)<EOL>text = cursor.block().text()<EOL>indent = len(text) - len(text.lstrip())<EOL>cursor.movePosition(cursor.Right, cursor.MoveAnchor, indent)<EOL>cursor.endEditBlock()<EOL>self.editor.setTextCursor(cursor)<EOL><DEDENT>else:<EOL><INDENT>cursor.endEditBlock()<EOL><DEDENT><DEDENT>

Comments/Uncomments the selected lines or the current lines if there
is no selection.


self._goto_requested = True<EOL>self._check_word_cursor()<EOL>

Request a goto action for the word under the text cursor.


if not tc:<EOL><INDENT>tc = TextHelper(self.editor).word_under_cursor()<EOL><DEDENT>request_data = {<EOL>'<STR_LIT:code>': self.editor.toPlainText(),<EOL>'<STR_LIT>': tc.blockNumber(),<EOL>'<STR_LIT>': tc.columnNumber(),<EOL>'<STR_LIT:path>': self.editor.file.path,<EOL>'<STR_LIT>': self.editor.file.encoding<EOL>}<EOL>try:<EOL><INDENT>self.editor.backend.send_request(<EOL>workers.goto_assignments, request_data,<EOL>on_receive=self._on_results_available)<EOL><DEDENT>except NotRunning:<EOL><INDENT>pass<EOL><DEDENT>

Request a go to assignment.

:param tc: Text cursor which contains the text that we must look for
           its assignment. Can be None to go to the text that is under
           the text cursor.
:type tc: QtGui.QTextCursor


<EOL>checked = []<EOL>for e in seq:<EOL><INDENT>present = False<EOL>for c in checked:<EOL><INDENT>if str(c) == str(e):<EOL><INDENT>present = True<EOL>break<EOL><DEDENT><DEDENT>if not present:<EOL><INDENT>checked.append(e)<EOL><DEDENT><DEDENT>return checked<EOL>


with open(path, '<STR_LIT:rb>') as file:<EOL><INDENT>source = file.read()<EOL>source = source.replace(b'<STR_LIT:\r>', b'<STR_LIT>')<EOL>source_str = str(source).replace('<STR_LIT>', '<STR_LIT:\n>')<EOL><DEDENT>byte_mark = ast.literal_eval(r"<STR_LIT>")<EOL>if source.startswith(byte_mark):<EOL><INDENT>return '<STR_LIT:utf-8>'<EOL><DEDENT>first_two_lines = re.match(r'<STR_LIT>', source_str).group(<NUM_LIT:0>)<EOL>possible_encoding = re.search(r"<STR_LIT>",<EOL>first_two_lines)<EOL>if possible_encoding:<EOL><INDENT>return possible_encoding.group(<NUM_LIT:1>)<EOL><DEDENT>return '<STR_LIT>'<EOL>

For the implementation of encoding definitions in Python, look at:
- http://www.python.org/dev/peps/pep-0263/

.. note:: code taken and adapted from
    ```jedi.common.source_to_unicode.detect_encoding```


Update terminal color scheme based on the pygments color scheme colors


super(PyInteractiveConsole, self).mouseMoveEvent(e)<EOL>cursor = self.cursorForPosition(e.pos())<EOL>assert isinstance(cursor, QtGui.QTextCursor)<EOL>p = cursor.positionInBlock()<EOL>usd = cursor.block().userData()<EOL>if usd and usd.start_pos_in_block <= p <= usd.end_pos_in_block:<EOL><INDENT>if QtWidgets.QApplication.overrideCursor() is None:<EOL><INDENT>QtWidgets.QApplication.setOverrideCursor(<EOL>QtGui.QCursor(QtCore.Qt.PointingHandCursor))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if QtWidgets.QApplication.overrideCursor() is not None:<EOL><INDENT>QtWidgets.QApplication.restoreOverrideCursor()<EOL><DEDENT><DEDENT>

Extends mouseMoveEvent to display a pointing hand cursor when the
mouse cursor is over a file location


super(PyInteractiveConsole, self).mousePressEvent(e)<EOL>cursor = self.cursorForPosition(e.pos())<EOL>p = cursor.positionInBlock()<EOL>usd = cursor.block().userData()<EOL>if usd and usd.start_pos_in_block <= p <= usd.end_pos_in_block:<EOL><INDENT>if e.button() == QtCore.Qt.LeftButton:<EOL><INDENT>self.open_file_requested.emit(usd.filename, usd.line)<EOL><DEDENT><DEDENT>

Emits open_file_requested if the press event occured  over
a file location string.


def setPlainText(self, txt, mimetype='<STR_LIT>', encoding='<STR_LIT:utf-8>'):

try:<EOL><INDENT>self.syntax_highlighter.docstrings[:] = []<EOL>self.syntax_highlighter.import_statements[:] = []<EOL><DEDENT>except AttributeError:<EOL><INDENT>pass<EOL><DEDENT>super(PyCodeEditBase, self).setPlainText(txt, mimetype, encoding)<EOL>

Extends QCodeEdit.setPlainText to allow user to setPlainText without
mimetype (since the python syntax highlighter does not use it).


return logging.getLogger(__name__)<EOL>


code = request_data['<STR_LIT:code>']<EOL>line = request_data['<STR_LIT>'] + <NUM_LIT:1><EOL>column = request_data['<STR_LIT>']<EOL>path = request_data['<STR_LIT:path>']<EOL>encoding = '<STR_LIT:utf-8>'<EOL>script = jedi.Script(code, line, column, path, encoding)<EOL>signatures = script.call_signatures()<EOL>for sig in signatures:<EOL><INDENT>results = (str(sig.module_name), str(sig.name),<EOL>[p.description for p in sig.params], sig.index,<EOL>sig.bracket_start, column)<EOL>return results<EOL><DEDENT>return []<EOL>

Worker that returns a list of calltips.

A calltips is a tuple made of the following parts:
  - module_name: name of the module of the function invoked
  - call_name: name of the function that is being called
  - params: the list of parameter names.
  - index: index of the current parameter
  - bracket_start

:returns tuple(module_name, call_name, params)


code = request_data['<STR_LIT:code>']<EOL>line = request_data['<STR_LIT>'] + <NUM_LIT:1><EOL>column = request_data['<STR_LIT>']<EOL>path = request_data['<STR_LIT:path>']<EOL>encoding = '<STR_LIT:utf-8>'<EOL>script = jedi.Script(code, line, column, path, encoding)<EOL>try:<EOL><INDENT>definitions = script.goto_assignments()<EOL><DEDENT>except jedi.NotFoundError:<EOL><INDENT>pass<EOL><DEDENT>else:<EOL><INDENT>ret_val = [(d.module_path, d.line - <NUM_LIT:1> if d.line else None,<EOL>d.column, d.full_name)<EOL>for d in definitions]<EOL>return ret_val<EOL><DEDENT>


global _old_definitions<EOL>ret_val = []<EOL>path = request_data['<STR_LIT:path>']<EOL>toplvl_definitions = jedi.names(<EOL>request_data['<STR_LIT:code>'], path, '<STR_LIT:utf-8>')<EOL>for d in toplvl_definitions:<EOL><INDENT>definition = _extract_def(d, path)<EOL>if d.type != '<STR_LIT>':<EOL><INDENT>ret_val.append(definition)<EOL><DEDENT><DEDENT>ret_val = [d.to_dict() for d in ret_val]<EOL>return ret_val<EOL>

Returns the list of defined names for the document.


code = request_data['<STR_LIT:code>']<EOL>line = request_data['<STR_LIT>'] + <NUM_LIT:1><EOL>column = request_data['<STR_LIT>']<EOL>path = request_data['<STR_LIT:path>']<EOL>encoding = '<STR_LIT:utf-8>'<EOL>script = jedi.Script(code, line, column, path, encoding)<EOL>try:<EOL><INDENT>definitions = script.goto_definitions()<EOL><DEDENT>except jedi.NotFoundError:<EOL><INDENT>return []<EOL><DEDENT>else:<EOL><INDENT>ret_val = [d.docstring() for d in definitions]<EOL>return ret_val<EOL><DEDENT>

Worker that returns the documentation of the symbol under cursor.


import pycodestyle<EOL>from pyqode.python.backend.pep8utils import CustomChecker<EOL>WARNING = <NUM_LIT:1><EOL>code = request_data['<STR_LIT:code>']<EOL>path = request_data['<STR_LIT:path>']<EOL>max_line_length = request_data['<STR_LIT>']<EOL>ignore_rules = request_data['<STR_LIT>']<EOL>ignore_rules += ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>']<EOL>pycodestyle.MAX_LINE_LENGTH = max_line_length<EOL>pep8style = pycodestyle.StyleGuide(parse_argv=False, config_file='<STR_LIT>',<EOL>checker_class=CustomChecker)<EOL>try:<EOL><INDENT>results = pep8style.input_file(path, lines=code.splitlines(True))<EOL><DEDENT>except Exception:<EOL><INDENT>_logger().exception('<STR_LIT>'<EOL>% request_data)<EOL>return []<EOL><DEDENT>else:<EOL><INDENT>messages = []<EOL>for line_number, offset, code, text, doc in results:<EOL><INDENT>if code in ignore_rules:<EOL><INDENT>continue<EOL><DEDENT>messages.append(('<STR_LIT>' % (code, text), WARNING,<EOL>line_number - <NUM_LIT:1>))<EOL><DEDENT>return messages<EOL><DEDENT>

Worker that run the pep8 tool on the current editor text.

:returns a list of tuples (msg, msg_type, line_number)


global prev_results<EOL>from pyflakes import checker<EOL>import _ast<EOL>WARNING = <NUM_LIT:1><EOL>ERROR = <NUM_LIT:2><EOL>ret_val = []<EOL>code = request_data['<STR_LIT:code>']<EOL>path = request_data['<STR_LIT:path>']<EOL>encoding = request_data['<STR_LIT>']<EOL>if not encoding:<EOL><INDENT>encoding = '<STR_LIT:utf-8>'<EOL><DEDENT>if not path:<EOL><INDENT>path = os.path.join(tempfile.gettempdir(), '<STR_LIT>')<EOL><DEDENT>if not code:<EOL><INDENT>return []<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>tree = compile(code.encode(encoding), path, "<STR_LIT>",<EOL>_ast.PyCF_ONLY_AST)<EOL><DEDENT>except SyntaxError as value:<EOL><INDENT>msg = '<STR_LIT>' % value.args[<NUM_LIT:0>]<EOL>(lineno, offset, text) = value.lineno - <NUM_LIT:1>, value.offset, value.text<EOL>if text is None:<EOL><INDENT>_logger().warning("<STR_LIT>",<EOL>path)<EOL><DEDENT>else:<EOL><INDENT>ret_val.append((msg, ERROR, lineno))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>w = checker.Checker(tree, os.path.split(path)[<NUM_LIT:1>])<EOL>w.messages.sort(key=lambda m: m.lineno)<EOL>for message in w.messages:<EOL><INDENT>msg = "<STR_LIT>" % str(message).split('<STR_LIT::>')[-<NUM_LIT:1>].strip()<EOL>line = message.lineno - <NUM_LIT:1><EOL>status = WARNINGif message.__class__ not in PYFLAKES_ERROR_MESSAGESelse ERROR<EOL>ret_val.append((msg, status, line))<EOL><DEDENT><DEDENT><DEDENT>prev_results = ret_val<EOL>return ret_val<EOL>

Worker that run a frosted (the fork of pyflakes) code analysis on the
current editor text.


ICONS = {<EOL>'<STR_LIT>': ICON_CLASS,<EOL>'<STR_LIT>': ICON_NAMESPACE,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_NAMESPACE,<EOL>'<STR_LIT>': ICON_KEYWORD,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_VAR,<EOL>'<STR_LIT>': ICON_FUNC,<EOL>'<STR_LIT>': ICON_FUNC,<EOL>'<STR_LIT>': ICON_FUNC_PRIVATE,<EOL>'<STR_LIT>': ICON_FUNC_PROTECTED<EOL>}<EOL>ret_val = None<EOL>icon_type = icon_type.upper()<EOL>if hasattr(name, "<STR_LIT:string>"):<EOL><INDENT>name = name.string<EOL><DEDENT>if icon_type == "<STR_LIT>" or icon_type == "<STR_LIT>":<EOL><INDENT>icon_type = "<STR_LIT>"<EOL><DEDENT>if icon_type == "<STR_LIT>" or icon_type == "<STR_LIT>":<EOL><INDENT>if name.startswith("<STR_LIT>"):<EOL><INDENT>icon_type += "<STR_LIT>"<EOL><DEDENT>elif name.startswith("<STR_LIT:_>"):<EOL><INDENT>icon_type += "<STR_LIT>"<EOL><DEDENT><DEDENT>if icon_type in ICONS:<EOL><INDENT>ret_val = ICONS[icon_type]<EOL><DEDENT>elif icon_type:<EOL><INDENT>_logger().warning("<STR_LIT>", icon_type)<EOL><DEDENT>return ret_val<EOL>

Returns the icon resource filename that corresponds to the given typename.

:param name: name of the completion. Use to make the distinction between
    public and private completions (using the count of starting '_')
:pram typename: the typename reported by jedi

:returns: The associate icon resource filename or None.


@staticmethod<EOL><INDENT>def complete(code, line, column, path, encoding, prefix):<DEDENT>

ret_val = []<EOL>try:<EOL><INDENT>script = jedi.Script(code, line + <NUM_LIT:1>, column, path, encoding)<EOL>completions = script.completions()<EOL>print('<STR_LIT>' % completions)<EOL><DEDENT>except jedi.NotFoundError:<EOL><INDENT>completions = []<EOL><DEDENT>for completion in completions:<EOL><INDENT>ret_val.append({<EOL>'<STR_LIT:name>': completion.name,<EOL>'<STR_LIT>': icon_from_typename(<EOL>completion.name, completion.type),<EOL>'<STR_LIT>': completion.description})<EOL><DEDENT>return ret_val<EOL>

Completes python code using `jedi`_.

:returns: a list of completion.


self._pidfile = pidfile<EOL>self.pidfile = None<EOL>


try:<EOL><INDENT>pidfile = open(self._pidfile, "<STR_LIT:a>")<EOL><DEDENT>except IOError as err:<EOL><INDENT>raise SystemExit(err)<EOL><DEDENT>try:<EOL><INDENT>fcntl.flock(pidfile.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)<EOL><DEDENT>except IOError:<EOL><INDENT>raise SystemExit('<STR_LIT>' + self._pidfile)<EOL><DEDENT>pidfile.seek(<NUM_LIT:0>)<EOL>pidfile.truncate()<EOL>pidfile.write(str(os.getpid()) + '<STR_LIT:\n>')<EOL>pidfile.flush()<EOL>self.pidfile = pidfile<EOL>atexit.register(self.release)<EOL>

Acquire the pidfile.

        Create the pidfile, lock it, write the pid into it
        and register the release with atexit.

        :return: None
        :raise: SystemExit


try:<EOL><INDENT>self.pidfile.close()<EOL>os.remove(self._pidfile)<EOL><DEDENT>except OSError as err:<EOL><INDENT>if err.errno != <NUM_LIT:2>:<EOL><INDENT>raise<EOL><DEDENT><DEDENT>

Release the pidfile.

        Close and delete the Pidfile.

        :return: None


maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[<NUM_LIT:1>]<EOL>if maxfd == resource.RLIM_INFINITY:<EOL><INDENT>maxfd = <NUM_LIT><EOL><DEDENT>for fileno in range(maxfd):<EOL><INDENT>if fileno not in preserve:<EOL><INDENT>try:<EOL><INDENT>os.close(fileno)<EOL><DEDENT>except OSError as err:<EOL><INDENT>if not err.errno == errno.EBADF:<EOL><INDENT>raise DaemonError(<EOL>'<STR_LIT>'<EOL>.format(fileno, err))<EOL><DEDENT><DEDENT><DEDENT><DEDENT>

Close unprotected file descriptors

    Close all open file descriptors that are not in preserve.

    If ulimit -nofile is "unlimited", all is defined filenos <= 4096,
    else all is <= the output of resource.getrlimit().

    :param preserve: set with protected files
    :type preserve: set

    :return: None


name_map = {<EOL>'<STR_LIT>': None,<EOL>'<STR_LIT>': None,<EOL>'<STR_LIT>': None,<EOL>'<STR_LIT>': '<STR_LIT>'}<EOL>signal_map = {}<EOL>for name, target in name_map.items():<EOL><INDENT>if hasattr(signal, name):<EOL><INDENT>signal_map[getattr(signal, name)] = target<EOL><DEDENT><DEDENT>return signal_map<EOL>

Create the default signal map for this system.

    :return: dict


if os.getppid() == <NUM_LIT:1>:<EOL><INDENT>return True<EOL><DEDENT>return False<EOL>

Check if parent is Init

    Check if the parent process is init, or something else that
    owns PID 1.

    :return: bool


result = False<EOL>sock = socket.fromfd(<EOL>sys.__stdin__.fileno(),<EOL>socket.AF_INET,<EOL>socket.SOCK_RAW)<EOL>try:<EOL><INDENT>sock.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)<EOL>result = True<EOL><DEDENT>except (OSError, socket.error) as err:<EOL><INDENT>if not err.args[<NUM_LIT:0>] == errno.ENOTSOCK:<EOL><INDENT>result = True<EOL><DEDENT><DEDENT>return result<EOL>

Check if parent is inet

    Check if our parent seems ot be a superserver, aka inetd/xinetd.

    This is done by checking if sys.__stdin__ is a network socket.

    :return: bool


if parent_is_inet() or parent_is_init():<EOL><INDENT>return False<EOL><DEDENT>return True<EOL>

Check if detaching is required

    This is done by collecting the results of parent_is_inet and
    parent_is_init. If one of them is True, detaching, aka the daemoninzing,
    aka the double fork magic, is not required, and can be skipped.

    :return: bool


if target is None:<EOL><INDENT>target_fd = os.open(os.devnull, os.O_RDWR)<EOL><DEDENT>else:<EOL><INDENT>target_fd = target.fileno()<EOL><DEDENT>try:<EOL><INDENT>os.dup2(target_fd, system.fileno())<EOL><DEDENT>except OSError as err:<EOL><INDENT>raise DaemonError('<STR_LIT>'<EOL>.format(system, target, err))<EOL><DEDENT>

Redirect Unix streams

    If None, redirect Stream to /dev/null, else redirect to target.

    :param system: ether sys.stdin, sys.stdout, or sys.stderr
    :type system: file object

    :param target: File like object, or None
    :type target: None, File Object

    :return: None
    :raise: DaemonError


def __init__(<EOL>self, chroot_directory=None, working_directory='<STR_LIT:/>',<EOL>umask=<NUM_LIT:0>, uid=None, gid=None, prevent_core=True,<EOL>detach_process=None, files_preserve=None, pidfile=None,<EOL>stdin=None, stdout=None, stderr=None, signal_map=None):

self._is_open = False<EOL>self._working_directory = None<EOL>self.chroot_directory = chroot_directory<EOL>self.umask = umask<EOL>self.uid = uid if uid else os.getuid()<EOL>self.gid = gid if gid else os.getgid()<EOL>if detach_process is None:<EOL><INDENT>self.detach_process = detach_required()<EOL><DEDENT>else:<EOL><INDENT>self.detach_process = detach_process<EOL><DEDENT>self.signal_map = signal_map if signal_map else default_signal_map()<EOL>self.files_preserve = files_preserve<EOL>self.pidfile = pidfile<EOL>self.prevent_core = prevent_core<EOL>self.stdin = stdin<EOL>self.stdout = stdout<EOL>self.stderr = stderr<EOL>self.working_directory = working_directory<EOL>


self.open()<EOL>return self<EOL>

Context Handler, wrapping self.open()

        :return: self


def __exit__(self, exc_type, exc_val, exc_tb):

self.close()<EOL>

Context Handler, wrapping self.close()

        :return: None


if not handler:<EOL><INDENT>result = signal.SIG_IGN<EOL><DEDENT>elif isinstance(handler, string_types):<EOL><INDENT>result = getattr(self, handler)<EOL><DEDENT>else:<EOL><INDENT>result = handler<EOL><DEDENT>return result<EOL>

get the callback function for handler

        If the handler is None, returns signal.SIG_IGN.
        If the handler is a string, return the matching attribute of this
        instance if possible.
        Else return the handler itself.

        :param handler:
        :type handler: str, None, function
        :return: function


result = set()<EOL>files = [] if not self.files_preserve else self.files_preserve<EOL>files.extend([self.stdin, self.stdout, self.stderr])<EOL>for item in files:<EOL><INDENT>if hasattr(item, '<STR_LIT>'):<EOL><INDENT>result.add(item.fileno())<EOL><DEDENT>if isinstance(item, int):<EOL><INDENT>result.add(item)<EOL><DEDENT><DEDENT>return result<EOL>

create a set of protected files

        create a set of files, based on self.files_preserve and
        self.stdin, self,stdout and self.stderr, that should not get
        closed while daemonizing.

        :return: set


result = {}<EOL>for signum, handler in self.signal_map.items():<EOL><INDENT>result[signum] = self._get_signal_handler(handler)<EOL><DEDENT>return result<EOL>

Create the signal handler map

        create a dictionary with signal:handler mapping based on
        self.signal_map

        :return: dict


if self.chroot_directory and notself._working_directory.startswith(self.chroot_directory):<EOL><INDENT>return self.chroot_directory + self._working_directory<EOL><DEDENT>else:<EOL><INDENT>return self._working_directory<EOL><DEDENT>

The working_directory property

        :return: str


self._working_directory = value<EOL>

Set working directory

        New value is ignored if already daemonized.

        :param value: str
        :return:


return self._is_open<EOL>

True when this instances open method was called

        :return: bool


pass<EOL>