精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Python靜態類型解析工具簡介和實踐

開發 開發工具 后端
Python是一門強類型的動態類型語言,開發者可以給對象動態指定類型(動態),但類型不匹配的操作是不被允許的(強類型,如str和int兩個變量無法相加)。

 [[412368]]

一、背景

Python是一門強類型的動態類型語言,開發者可以給對象動態指定類型(動態),但類型不匹配的操作是不被允許的(強類型,如str和int兩個變量無法相加)。

動態類型幫助開發者寫代碼輕松愉快,然而,俗話說:動態一時爽,重構火葬場。動態類型也帶來了許多麻煩,如果動態語言能加入靜態類型標記的話,主要有以下幾點好處:

  • 編寫更便捷。配合各種IDE工具,可以實現定義跳轉,類型提示等。

  • 編碼更可靠。既然有了類型定義的加持,許多工具能夠在靜態編碼階段就能提前發現語義錯誤。

  • 重構更放心。明確了接口的出入參,使代碼重構更明確更穩定。

目前主流語言大多數是支持靜態類型的,如Java,Go,Rust。而動態語言(Python,JS)也在擁抱靜態類型,如TypeScript。

本文主要介紹一下Python對靜態類型的支持、社區發展的現狀、類型檢查工具介紹與對比,以及類型解析的實戰。

二、Python的靜態類型支持

早在06年的Python3.0就引入了類型annotation的語法,并列出了許多改進項。

  1. # 加類型前 
  2. def add(a, b): 
  3.     return a + b 
  4.      
  5. # 加類型后 
  6. def add(a:int, b:int) -> int
  7.     return a + b 

隨著持續的演進,到Python3.5,能夠做到Type Hints,配合類型標注,IDE可以做Type Checking。

進而到Python3.7,靜態類型支持基本完善。

下面我來具體介紹下類型檢查工具和一些基礎概念。

三、類型檢查工具簡介

Python作者和主流大廠都陸續推出了Python類型檢查工具:

這些類型解析工具的功能大同小異,下面簡單介紹下:

1.mypy

最早的官方推出的mypy是由Python之父Guido van Rossum親自開發,被各種主流編輯器所集成(如PyCharm, Emacs, Sublime Text, VS Code等),用戶基礎和文檔經驗都很豐富。

2.pytype

谷歌的pytype可以做類型檢查,并且提供了一些實用小工具,下文會簡單介紹下其應用:

  • annotate-ast,過程中的AST樹標記工具。

  • merge-pyi,把生成的 pyi 文件合并回原文件中,甚至還能做到隱藏類型,在類型檢查時再加載。

  • pytd-tool,解析 pyi 文件的工具,解析成pytype自定義的PYTD文件。

  • pytype-single,再給定所有依賴的 pyi 文件的前提下,可以解析單個Python文件。

  • pyxref,交叉引用的生成器。

3.pyre

臉書的pyre-check有兩個特別的功能:

  • Watchman功能, 可以監聽代碼文件,追蹤改動。

  • Query功能,可以對源碼做局部區域性的檢查,例如查詢某行中一個表達式的類型、查詢一個類的全部方法并返回成列表等,避免了全局檢查。

4.pyright

微軟的pyright是最晚開源推出的,宣稱有以下優點:

  • 速度快。相較于 mypy 及其它用 Python 寫的檢查工具,它的速度是 5 倍甚至更多。

  • 不依賴 Python 環境。它用 TypeScript 寫成,運行于 node 上,不依賴 Python 環境或第三方包。

  • 可配置性強。支持自由地配置,支持指定不同的運行環境(PYTHONPATH 設置、Python 版本、平臺目標)。

  • 檢查項齊全。支持類型檢查及其它語法項的檢查(如 PEP-484、PEP-526、PEP-544),以及函數返回值、類變量、全局變量的檢查,甚至可以檢查條件循環語句。

  • 命令行工具。它包含兩個 VS Code 插件:一個命令行工具和一個語言服務器協議(Language Server Protocol)。

  • 內置 Stubs 。使用的是 Typeshed 的副本(注:使用靜態的 pyi 文件,檢查內置模塊、標準庫和三方件 ) 。

  • 語言服務特性。懸停提示信息、符號定義的跳轉、實時的編輯反饋。

四、Pytype使用介紹

接下來重點介紹一下pytype。為什么選取pytype呢,首先mypy比較古老,很多功能沒有新出的工具新穎和實用。計劃使用Python LSP來處理Python文件提供一些語法服務的功能,pyre-check用的是Ocamel,所以我們就拿Python語言的pytype來實現想要的功能,而且pytype提供了一些實用工具,比如解析一個pyi文件,基于Python文件生成pyi文件等。

1.基本概念

pyi 文件

pyi 的“ i ”指的是interfiace,將 Python 文件的類型定義用接口的形式存儲到pyi文件里,來輔助類型檢查。

大家常用的Pycharm,可以關注下項目空間的External Libraries > Python 3.6 > Typeshed Stubs里面就有許多內置的 pyi 文件,來輔助編碼過程的類型提示和定位。

Typeshed Stubs

上面提到了typeshed stubs,這相當于是提前集成的pyi集合,pycharm似乎自己維護了一份數據。 許多比較大的開源項目也在陸續提供stubs, 比如pyTorch。 Tensorflow也正在考慮。

很多Python大庫去制作pyi工程量比較大,而且還有很多C的API調用,大家還需要耐心等待。

2.實戰

我翻閱了pytype的源碼,把比較實用的代碼和需求做了結合,下面介紹幾個示例:

總體效果

  1. import logging 
  2. import sys 
  3. import os 
  4. import importlab.environment 
  5. import importlab.fs 
  6. import importlab.graph 
  7. import importlab.output 
  8. from importlab import parsepy 
  9.  
  10.  
  11. from sempy import util 
  12. from sempy import environment_util 
  13.  
  14.  
  15. from pytype.pyi import parser 

示例Demo,通過Importlab工具,解析項目空間的依賴關系,以及對應的pyi文件:

  1. def main(): 
  2.     # 指定要解析的目錄 
  3.     ROOT = '/path/to/demo_project' 
  4.     # 指定TYPESHED目錄,可以從這里下載:https://github.com/python/typeshed 
  5.     TYPESHED_HOME = '/path/to/typeshed_home' 
  6.     util.setup_logging() 
  7.     # 載入typeshed,如果TYPESHED_HOME配置的不對,會返回None 
  8.     typeshed = environment_util.initialize_typeshed_or_return_none(TYPESHED_HOME) 
  9.     # 載入目標目錄有效文件 
  10.     inputs = util.load_all_py_files(ROOT) 
  11.     # 生成用于生成import_graph的環境 
  12.     env = environment_util.create_importlab_environment(inputs, typeshed) 
  13.     # 基于pyi和工程文件生成import graph 
  14.     import_graph = importlab.graph.ImportGraph.create(env, inputs, trim=True) 
  15.     # 打印整個依賴樹 
  16.     logging.info('Source tree:\n%s', importlab.output.formatted_deps_list(import_graph)) 
  17.     # import模塊的別名 e.g. import numpy as np -> {'np''numpy'
  18.     alias_map = {} 
  19.     # 引入模塊的名稱和具體pyi文件的映射 e.g. import os -> {'os''/path/to/os/__init__.pyi'
  20.     import_path_map = {} 
  21.     # alias_map的value,可以和import_path_map的key對應,通過alias_map的key這個變量名去找真正的實現文件 
  22.     for file_name in inputs: 
  23.         # 如果有pyi文件匹配,則會放入resolved 
  24.         # 如果依賴了Build_in依賴,會被跳過,不返回 
  25.         # 如果依賴了自定義依賴,會放入unresolved,需要自己進一步解析,定位到項目工程文件 
  26.         (resolved, unresolved) = import_graph.get_file_deps(file_name) 
  27.         for item in resolved: 
  28.             item_name = item.replace('.pyi''') \ 
  29.                 .replace('.py''') \ 
  30.                 .replace('/__init__''').split('/')[-1
  31.             import_path_map[item_name] = item 
  32.         for item in unresolved: 
  33.             file_path = os.path.join(ROOT, item.new_name + '.py'
  34.             import_path_map[item.name] = file_path 
  35.         import_stmts = parsepy.get_imports(file_name, env.python_version) 
  36.         for import_stmt in import_stmts: 
  37.             alias_map[import_stmt.new_name] = import_stmt.name 
  38.     print('以下為通過importlab解析方式獲取的import關系\n\n'
  39.  
  40.  
  41.     # 對于代碼搜索場景,只需要alias_map,既可以通過正在使用的對象關聯到引入的模塊 
  42.     print('\n\n#################################\n\n'
  43.     print('對于代碼搜索場景,只需要alias_map,既可以通過正在使用的對象關聯到引入的模塊'
  44.     print('alias_map: ', alias_map) 
  45.  
  46.  
  47.     # 對于代碼補全場景,需要進一步解析當前文件以及引用的pyi文件,如果當前文件是__init__文件,則要進一步去該目錄下的所有文件方法中全局搜索 
  48.     print('\n\n#################################\n\n'
  49.     print('對于代碼補全場景,需要進一步解析當前文件以及引用的pyi文件,如果當前文件是__init__文件,則要進一步去該目錄下的所有文件方法中全局搜索'
  50.     print('import_path_map: ', import_path_map) 
  51.  
  52.  
  53.     print('\n\n\n以下為通過pytype工具,解析pyi文件AST來分析三方依賴返回類型,從而解析出當前變量的類型\n\n'
  54.     # 通過pytype的解析,去解析依賴的pyi文件,獲得調用方法的返回值 
  55.     fname = '/path/to/parsed_file' 
  56.     with open(fname, 'r') as reader: 
  57.         lines = reader.readlines() 
  58.     sourcecode = '\n'.join(lines) 
  59.     ret = parser.parse_string(sourcecode, filename=fname, python_version=3
  60.  
  61.  
  62.     constant_map = dict() 
  63.     function_map = dict() 
  64.     for key in import_path_map.keys(): 
  65.         v = import_path_map[key] 
  66.         with open(v, 'r') as reader: 
  67.             lines = reader.readlines() 
  68.         src = '\n'.join(lines) 
  69.         try
  70.             res = parser.parse_pyi(src, v, key, 3
  71.         except: 
  72.             continue 
  73.         # Alias 
  74.         # Classes 
  75.         for constant in res.constants: 
  76.             constant_map[constant.name] = constant.type.name 
  77.         for function in res.functions: 
  78.             signatures = function.signatures 
  79.             sig_list = [] 
  80.             for signature in signatures: 
  81.                 sig_list.append((signature.params, signature.return_type)) 
  82.             function_map[function.name] = sig_list 
  83.  
  84.  
  85.     var_type_from_pyi_list = [] 
  86.     for alias in ret.aliases: 
  87.         variable_name = alias.name 
  88.         if alias.type is not None: 
  89.             typename_in_source = alias.type.name 
  90.             typename = typename_in_source 
  91.             # 引入別名的case,把它轉化回來 
  92.             if '.' not in typename: 
  93.                 # 只是普通的別名,不是函數調用的返回值,忽略 
  94.                 continue 
  95.             if typename.split('.')[0] in alias_map: 
  96.                 real_module_name = alias_map[typename.split('.')[0]] 
  97.                 typename = real_module_name + typename[typename.index('.'):] 
  98.             if typename in function_map: 
  99.                 possible_return_types = [item[1].name for item in function_map[typename]] 
  100.                 var_type_from_pyi_list.append((variable_name, possible_return_types)) 
  101.             if typename in constant_map: 
  102.                 possible_return_type = constant_map[typename] 
  103.                 var_type_from_pyi_list.append((variable_name, possible_return_type)) 
  104.                 pass 
  105.     print('\n\n#################################\n\n'
  106.     print('這些都是從PYI文件中分析出來的返回值類型'
  107.     for item in var_type_from_pyi_list: 
  108.         print('變量名:', item[0], '返回類型:', item[1]) 
  109.  
  110.  
  111. if __name__ == '__main__'
  112.     sys.exit(main()) 

被 解析的示例代碼:

  1. # demo.py 
  2. import os as abcdefg 
  3. import re 
  4. from demo import utils 
  5. from demo import refs 
  6.  
  7.  
  8.  
  9.  
  10. cwd = abcdefg.getcwd() 
  11. support_version = abcdefg.supports_bytes_environ 
  12. pattern = re.compile(r'.*'
  13.  
  14.  
  15.  
  16.  
  17. add_res = utils.add(13
  18. mul_res = refs.multi(35
  19.  
  20.  
  21.  
  22.  
  23. c = abs(1

具體步驟

首先pytype利用了Google另一個開源項目:ImportLab。

用于分析文件間的依賴關系,此時可以把typeshed目錄下的文件也放入環境中,importlab能夠生成依賴圖。

  1. env = environment_util.create_importlab_environment(inputs, typeshed) 
  2. import_graph = importlab.graph.ImportGraph.create(env, inputs, trim=True) 
  3. # 如果有pyi文件匹配,則會放入resolved 
  4. # 如果依賴了Build_in依賴,會被跳過,不返回 
  5. # 如果依賴了自定義依賴,會放入unresolved,需要自己進一步解析,定位到項目工程文件 
  6. (resolved, unresolved) = import_graph.get_file_deps(file_name) 

通過import graph我們拿到了變量的來源(包括引用別名,方法調用返回值):

  1. {'ast''ast''astpretty''astpretty''abcdefg''os''re''re''utils''demo.utils''refs''demo.refs''JsonRpcStreamReader''pyls_jsonrpc.streams.JsonRpcStreamReader'

通過依賴圖,還能直接引用的依賴在具體哪個位置:

  1. import_path_map:  {'ast''/Users/zhangxindong/Desktop/search/code/sempy/sempy/typeshed/stdlib/ast.pyi''astpretty''/Users/zhangxindong/Desktop/search/code/sempy/venv/lib/python3.9/site-packages/astpretty.py''os''/Users/zhangxindong/Desktop/search/code/sempy/sempy/typeshed/stdlib/os/__init__.pyi''re''/Users/zhangxindong/Desktop/search/code/sempy/sempy/typeshed/stdlib/re.pyi''utils''/Users/zhangxindong/Desktop/search/code/sempy/sempy/demo/utils.py''refs''/Users/zhangxindong/Desktop/search/code/sempy/sempy/demo/refs/__init__.py''streams''/Users/zhangxindong/Desktop/search/code/sempy/venv/lib/python3.9/site-packages/pyls_jsonrpc/streams.py'

接下來,就是去具體解析對應的文件了。我的需求是獲取一些方法的返回值類型,對于 pyi 文件,pytype能夠幫助我們解析,然后我們通過調用關系去匹配。

  1. print('\n\n\n以下為通過pytype工具,解析pyi文件AST來分析三方依賴返回類型,從而解析出當前變量的類型\n\n'
  2. # 通過pytype的解析,去解析依賴的pyi文件,獲得調用方法的返回值 
  3. fname = '/path/to/parsed_file' 
  4. with open(fname, 'r') as reader: 
  5.     lines = reader.readlines() 
  6. sourcecode = '\n'.join(lines) 
  7. ret = parser.parse_string(sourcecode, filename=fname, python_version=3
  8.  
  9.  
  10. constant_map = dict() 
  11. function_map = dict() 
  12. for key in import_path_map.keys(): 
  13.     v = import_path_map[key] 
  14.     with open(v, 'r') as reader: 
  15.         lines = reader.readlines() 
  16.     src = '\n'.join(lines) 
  17.     try
  18.         res = parser.parse_pyi(src, v, key, 3
  19.     except: 
  20.         continue 
  21.     # Alias 
  22.     # Classes 
  23.     for constant in res.constants: 
  24.         constant_map[constant.name] = constant.type.name 
  25.     for function in res.functions: 
  26.         signatures = function.signatures 
  27.         sig_list = [] 
  28.         for signature in signatures: 
  29.             sig_list.append((signature.params, signature.return_type)) 
  30.         function_map[function.name] = sig_list 
  31.  
  32.  
  33. var_type_from_pyi_list = [] 
  34. for alias in ret.aliases: 
  35.     variable_name = alias.name 
  36.     if alias.type is not None: 
  37.         typename_in_source = alias.type.name 
  38.         typename = typename_in_source 
  39.         # 引入別名的case,把它轉化回來 
  40.         if '.' not in typename: 
  41.             # 只是普通的別名,不是函數調用的返回值,忽略 
  42.             continue 
  43.         if typename.split('.')[0] in alias_map: 
  44.             real_module_name = alias_map[typename.split('.')[0]] 
  45.             typename = real_module_name + typename[typename.index('.'):] 
  46.         if typename in function_map: 
  47.             possible_return_types = [item[1].name for item in function_map[typename]] 
  48.             # print('The possible return type of', typename_in_source, 'is', possible_return_types) 
  49.             var_type_from_pyi_list.append((variable_name, possible_return_types)) 
  50.         if typename in constant_map: 
  51.             possible_return_type = constant_map[typename] 
  52.             var_type_from_pyi_list.append((variable_name, possible_return_type)) 
  53.             pass 

比如:

  1. pattern = re.compile(r'.*'

從/Users/zhangxindong/Desktop/search/code/sempy/sempy/typeshed/stdlib/re.pyi文件中,我們載入了兩個方法都是re.compile,只是入參不同,返回值都是Pattern類型。

于是我們就知道了pattern變量的類型是re.Pattern。

  • 這些都是從 pyi 文件中分析出來的返回值類型。

  • 變量名 cwd 返回類型:['str']

  • 變量名 support_version 返回類型:bool

  • 變量名 pattern 返回類型:['typing.Pattern', 'typing.Pattern']

五、應用

Python語法分析的功能有一部分已經應用在了阿里云Dev Studio的代碼文檔搜索推薦和代碼智能補全中。

1.代碼文檔搜索推薦

當開發者不知道如何使用某個 API 時(如調用方式或方法入參等),可以將鼠標移動到指定 API 上,即可展示智能編碼插件提供的 API 概要信息。開發者點擊“ API 文檔詳情”,能在右側欄看到 API 的官方文檔、代碼示例等詳細信息,也可以直接搜索所需的 API 代碼文檔。目前支持 JavaScript、Python 語言的代碼文檔搜索推薦。

文檔采集過程中,我們能夠拿到API名稱和API所對應的class,在實際代碼中,我們通過語法分析就能基于調用的方法對應到調用的類信息,從而用于文檔搜索。

2.代碼智能補全

開發者在編寫代碼時,智能編碼插件會自動感知代碼上下文,為開發者提供精準的代碼補全候選項,代碼補全候選項中標記有 :sparkles: 符號的為代碼智能補全結果。目前支持 Java、JavaScript、Python 語言的代碼智能補全。

代碼補全過程中,通過語法分析,能夠更加精準地獲悉用戶使用變量的類信息,幫助過濾掉深度學習模型推薦的不合理選項,也能夠基于類的內部方法集合,召回一些合理的補全項。

六、總結

Python靜態類型支持的理念和工具均以完善,但由于歷史包袱太重,社區推動力不足,實際能達到的效果比較有限。另外官方、各大廠以及本地IDE都有自己的實現和分析方式,還沒有達到統一的標準和格式。大家可以根據上述的優劣勢以及配合的工具集與數據集,選擇適合自己的方式做解析。期待Python社區對靜態類型的支持能越來越完善。

 

責任編輯:張燕妮 來源: 阿里技術
相關推薦

2022-04-18 10:20:31

數據映射工具

2011-06-09 11:11:35

QT 靜態庫 動態庫

2025-02-10 07:40:00

Java集合工具類編程

2011-04-14 17:32:21

2010-01-07 17:36:38

Linux靜態庫

2012-04-26 13:44:18

ibmdw

2010-03-12 17:29:16

Python模塊

2010-02-24 14:53:33

Python開發工具

2024-10-29 20:58:38

2009-08-20 14:28:00

C#靜態構造函數

2010-11-22 10:57:22

MySQL字段類型

2023-02-24 07:48:20

PHPGo服務

2013-01-16 14:45:47

HadoopApache Hado

2009-07-01 19:21:00

2009-09-24 14:30:04

DotProject

2010-02-02 16:22:37

Python動態類型語

2025-03-14 10:34:22

2022-07-26 08:00:00

測試工具回歸測試軟件功能

2022-06-28 13:25:19

K8sPrometheusGrafana

2020-10-17 09:48:55

Spinnaker實踐
點贊
收藏

51CTO技術棧公眾號

一区二区三区视频免费视频观看网站| 中日韩一级黄色片| 成人性生交大片免费看网站| 亚洲精品国产精品国| 婷婷综合国产| 一区二区三区在线观看视频| 伊人青青综合网站| 每日在线更新av| 免费福利在线观看| 国产模特精品视频久久久久| 在线看国产精品| 成人在线短视频| 草草影院在线| 久久精品视频一区二区三区| 日本sm极度另类视频| 色无极影院亚洲| 中文字幕资源网在线观看免费 | 红桃成人av在线播放| 国产精品白丝jk白祙喷水网站| 992tv在线成人免费观看| 网爆门在线观看| 欧美亚洲tv| 精品成人在线| 99精品视频一区| 国产欧美日韩高清| 午夜影院在线看| 久久在线电影| 日韩av最新在线观看| 欧美一区免费视频| 精品国产av一区二区三区| 日韩av在线发布| 97精品国产97久久久久久春色| 日本成人精品视频| 国产欧美高清视频在线| 欧美性猛交xxxx黑人交| 国产在线视频在线| 香蕉av在线播放| 粉嫩av亚洲一区二区图片| 国产精品永久在线| 激情五月婷婷网| 一区二区三区福利| 欧美黑人一级爽快片淫片高清| 懂色av粉嫩av浪潮av| 日本黄色免费观看| 18+激情视频在线| 国产精品每日更新| 日韩中文一区二区三区| 国产黄色免费大片| 激情综合五月天| 热久久免费视频精品| 麻豆疯狂做受xxxx高潮视频| 成人影院天天5g天天爽无毒影院| 亚洲精品国精品久久99热一| 伊人免费视频二| 日韩免费福利视频| 天天综合色天天综合| 成人黄色片免费| 久草中文在线观看| 中国av一区二区三区| 小说区图片区图片区另类灬| 成年人在线观看| 国产精品色哟哟| 亚洲日本va午夜在线影院| 欧洲亚洲女同hd| 久久久久亚洲av无码专区| 米奇777超碰欧美日韩亚洲| 欧美日韩国产影片| 自拍偷拍亚洲色图欧美| 青青草在线播放| 久久久精品中文字幕麻豆发布| 久久国产精品久久| 亚洲经典一区二区三区| 国产在线看一区| 成人在线视频网址| 精品国产av 无码一区二区三区| 国产精品亚洲第一| 国产日韩欧美一区二区| 天天色综合天天色| 在线日本视频| 自拍偷拍国产精品| 亚洲成人午夜在线| av毛片在线播放| 日韩美女精品在线| 野外做受又硬又粗又大视频√| 97天天综合网| 色哟哟欧美精品| 国产永久免费网站| 国内精品麻豆美女在线播放视频| 亚洲男人天堂久| 欧美激情精品久久久久久免费 | 一级做a爰片久久毛片16| 国产麻豆视频一区二区| 精品国产一区二区三区日日嗨| 黄色毛片在线观看| 悠悠色在线精品| 国产91在线视频观看| 性生交大片免费看l| 久久久久久久久久久免费视频| 成人综合电影| 国产精品成人一区二区艾草 | 国产欧美综合精品一区二区| 熟妇人妻中文av无码| 国产婷婷色一区二区三区在线| 欧美aaa在线观看| av美女在线观看| 精品国产一区二区三区av片| 精品夜色国产国偷在线| 久久嫩草捆绑紧缚| 在线亚洲国产精品网站| 国产在线精品自拍| 欧美美乳在线| 一区二区在线观看视频| 99视频精品免费| 国产精品一区二区三区美女| 日韩在线小视频| 久久艹精品视频| 麻豆视频一区二区| 欧美日韩天天操| 中文字幕免费高清电视剧网站在线观看| 欧美日韩一二三四五区| 色婷婷狠狠18禁久久| 色999国产精品| 国产91精品久久久久| 精品人妻一区二区三区麻豆91| 国产三级久久久| 蜜桃传媒一区二区三区| 视频欧美一区| 精品国产拍在线观看| 国产情侣小视频| ww久久中文字幕| 亚洲 欧美 日韩 国产综合 在线 | 91福利视频在线| 黄色免费看视频| 激情亚洲网站| http;//www.99re视频| 日本激情视频在线观看| 欧美视频一区二区三区在线观看 | 九九热精品视频在线观看| 欧美激情视频在线观看| 国产伦精品一区二区三区四区| 国产三级一区二区三区| 成人一区二区三| 免费毛片在线不卡| 热久久这里只有精品| 天堂v视频永久在线播放| 亚洲国产一区二区在线播放| 中文字幕无码毛片免费看| 久久久久久久久丰满| 成人a级免费视频| 久久bbxx| 日韩美女视频在线| 精品97人妻无码中文永久在线| 国产剧情一区二区三区| 日本高清视频免费在线观看| www.久久99| 欧美理论电影在线观看| 亚洲h视频在线观看| 一区二区三区久久| 亚洲午夜久久久久久久久| 国语精品一区| 精品一区二区不卡| 亚洲妇女成熟| 国产亚洲视频在线| 国产一区二区三区四区视频| 亚洲精品久久久蜜桃| 国产免费a级片| 国产精品毛片| 日本一区二区免费看| 成人黄色毛片| 久久国产精品免费视频| 性生活免费网站| 精品久久久久久久久久久| 亚洲中文字幕无码一区| 久久久久国内| 亚洲日本精品国产第一区| 国产情侣一区在线| 国模吧一区二区三区| 日本一本草久在线中文| 欧美三级在线播放| 欧美三级在线免费观看| 99久久精品国产一区| 韩国视频一区二区三区| 欧美黄色一级视频| 精品综合久久久| 国产精品99| 久久久久久999| 国产在线一二| 日韩免费看网站| 免费看日批视频| 亚洲精品视频在线| 中文幕无线码中文字蜜桃| 久久精品99国产精品日本| 欧美性潮喷xxxxx免费视频看| 免费黄色成人| av成人午夜| 九色成人搞黄网站| 久久久久亚洲精品| av播放在线| 亚洲精品不卡在线| 国产精品久久免费| 欧美性xxxx18| 免费人成在线观看| 日本一区二区不卡视频| 久久久老熟女一区二区三区91| 青青草国产精品97视觉盛宴| 国产精品成人久久电影| 日韩在线不卡| 欧美日韩在线高清| aiai久久| 亚洲a中文字幕| 日本一道高清亚洲日美韩| 欧美激情一级精品国产| 欧美被日视频| 亚洲色图35p| 欧洲成人一区二区三区| 69久久99精品久久久久婷婷| 欧美亚洲另类小说| 精品国产乱码久久久久酒店| 欧美做爰爽爽爽爽爽爽| 欧美激情一区在线| 亚洲成人日韩在线| aaa国产一区| 日本r级电影在线观看| 美女视频网站久久| 国产淫片av片久久久久久| 一区三区视频| 91精品国产毛片武则天| 国产精品88久久久久久| 神马影院一区二区三区| 中文字幕中文字幕精品| 久久精品ww人人做人人爽| 亚洲综合网狠久久| 97超碰资源| 国产精品美女久久久久| 国产在线观看一区二区三区| 外国电影一区二区| 国产精品白嫩美女在线观看| 亚洲插插视频| 日韩av不卡电影| 国产精品专区免费| 热久久99这里有精品| 欧美xxxxxx| 国产第一区电影| 日韩国产网站| 国产精品第1页| 欧美va在线| 国产精品久久久久久久久| 三上悠亚激情av一区二区三区 | 亚洲午夜小视频| 国产在线一二三| 色综合亚洲精品激情狠狠| 成年人在线视频免费观看| 国产一区二区三区中文| 第九色区av在线| 日韩一区二区三区国产| 在线观看免费高清完整| 日韩中文字幕网址| av大全在线| 欧美激情一级二级| 色综合亚洲图丝熟| 日韩av免费在线播放| 8av国产精品爽爽ⅴa在线观看| 国产精品激情自拍| 亚洲精品三区| 9a蜜桃久久久久久免费| 久久久免费毛片| 欧洲高清一区二区| 日韩av自拍| 最新精品视频| 极品av少妇一区二区| 无码人妻h动漫| 久久精品国产精品亚洲红杏| 巨乳女教师的诱惑| 91色视频在线| www.黄色com| 亚洲国产乱码最新视频 | 欧美日韩免费一区二区三区视频| 国产精品高潮呻吟av| 欧美成人精品二区三区99精品| 五月激情婷婷网| 中文字幕亚洲欧美一区二区三区| av小次郎在线| 欧美在线xxx| 亚洲图片小说区| 久草一区二区| 99久久久久| 成人免费毛片网| 久久99国内精品| 亚洲色图14p| 综合色中文字幕| 51国产偷自视频区视频| 欧美挠脚心视频网站| 五十路在线观看| 欧美成人一区二区三区电影| 在线观看的黄色| 亚洲资源在线看| 成人情趣视频| 久久综合色视频| 国产精品性做久久久久久| 男生草女生视频| 亚洲一二三专区| 在线免费a视频| 亚洲美女av网站| 在线heyzo| 国产在线久久久| 精品国产1区| 麻豆tv在线播放| 国产精品综合网| 五月婷婷六月香| 欧美午夜女人视频在线| 亚洲国产日韩在线观看| 中文字幕日韩av电影| 涩涩在线视频| 99精品国产一区二区| 日韩av在线中文字幕| 精品一卡二卡三卡| 成人精品一区二区三区四区| 手机免费观看av| 一本色道久久综合狠狠躁的推荐| 亚洲成人第一区| 成年人精品视频| 国外成人福利视频| 欧美一区三区二区在线观看| 国产精品一二| 奇米777第四色| 亚洲尤物在线视频观看| 国产又粗又大又黄| 中文字幕日韩综合av| 性感美女一区二区在线观看| 久草一区二区| 国产欧美日韩综合一区在线播放| av不卡中文字幕| 一区二区高清免费观看影视大全| 中文字幕av资源| 在线观看日韩av| 日韩经典一区| 亚洲国产欧美一区二区三区不卡| 日韩中文欧美在线| 一区二区黄色片| 一本大道久久a久久综合| 天堂网www中文在线| 秋霞成人午夜鲁丝一区二区三区| 欧美日韩导航| 成人一级片网站| 久久久久久夜精品精品免费| 日本视频在线观看免费| 亚洲男人天堂久| xxxxx.日韩| 尤物一区二区三区| 国产一区二区久久| 丰满少妇高潮久久三区| 精品欧美黑人一区二区三区| 欧美高清另类hdvideosexjaⅴ| 国产精品免费一区二区三区在线观看| 国产主播精品| 在线免费观看a级片| 一本色道a无线码一区v| 中文字幕日本在线观看| 91精品在线影院| 欧美日本国产| 先锋资源av在线| 日韩欧美在线视频日韩欧美在线视频| 邻家有女韩剧在线观看国语| 国产精品久久久久久av| 91tv精品福利国产在线观看| 中文字幕第10页| 黄色一区二区三区| 国产高清免费av在线| 91精品国产综合久久香蕉最新版| 综合久久十次| 国产精品扒开腿做爽爽爽a片唱戏 亚洲av成人精品一区二区三区 | 欧美久久婷婷综合色| 日韩精品卡一| 欧美精品一区二区三区久久| 蓝色福利精品导航| 久久久精品国产sm调教网站| 亚洲国产一区自拍| 成人一区视频| 丁香色欲久久久久久综合网| www一区二区| 国产又粗又黄又爽的视频| 久久久亚洲精品视频| 精品日韩欧美一区| 中文字幕第六页| 欧美性猛交xxxx| 日p在线观看| 久久99欧美| 经典一区二区三区| 日韩av大片在线观看| 日韩最新中文字幕电影免费看| 99热这里只有精品首页| 激情视频综合网| 夜夜精品视频一区二区| 国产大学生校花援交在线播放| 成人xxxxx色| 免费的国产精品| 毛片在线免费视频| 免费91在线视频| 欧美日韩中文字幕一区二区三区| 午夜影院福利社|