2014-02-21 61 views
7

在我目前的工作環境中,我們生產大量供內部使用的Python包(如果不是100s,則爲10s)。每個軟件包都有一些依賴關係,通常是內部和外部軟件包的混合體,其中一些依賴關係是共享的。Python API兼容性檢查器

當我們接近dependency hell時,更新依賴關係成爲一個耗時的過程。雖然我們關心新版本可能引入的功能更改,但同等(如果不是更多)重要的是破壞代碼的API更改。

雖然針對較新版本的依賴項運行單元/集成測試有助於我們發現一些問題,但我們的覆蓋率還不足以達到100%,因此無法實現這一穩健策略。發行說明和更改日誌可幫助識別高級別的主要更改,但這些更改很少存在於內部開發的工具中,或者詳細瞭解新版本對(公共)API的影響。

我正在看其他方面來自動執行此過程。

我希望能夠自動比較兩個版本的Python軟件包並報告它們之間的API差異。特別是,這將包括向後不兼容的更改,例如刪除函數/方法/類/模塊,向函數/方法/類添加位置參數以及更改函數/方法返回的項目數。作爲一名開發人員,基於此報告生成的報告,我應該更深入地瞭解此版本更改將引入的代碼級別影響,因此需要整合它。

在其他地方,我們使用C++ abi-compliance-checker並正在尋找Java api-compliance-checker來幫助完成此過程。是否有類似的工具可用於Python?我發現了很多皮棉/分析/重構工具,但沒有提供這種級別的功能。我知道Python的動態輸入將會使綜合報告變得不可能。

如果這樣的工具不存在,他們是否可以幫助實施解決方案的任何庫?例如,我目前的方法是使用ast.NodeVisitor來遍歷包並構建一個樹,其中每個節點表示一個模塊/類/方法/函數,然後將該樹與另一個版本的樹相比較,以查找相同的包。

編輯:自發布問題我發現pysdiff其中涵蓋了我的一些要求,但有興趣看到替代品。

編輯:也找到了Upstream-Tracker這是我想結束的那種信息的一個很好的例子。

回答

2

也許你可以通過使用inspect模塊

import inspect 
import types 
def genFunctions(module): 
    moduleDict = module.__dict__ 
    for name in dir(module): 
     if name.startswith('_'): 
      continue 
     element = moduleDict[name] 
     if isinstance(element, types.FunctionType): 
      argSpec = inspect.getargspec(element) 
      argList = argSpec.args 
      print "{}.{}({})".format(module.__name__, name, ", ".join(argList)) 

這會給你的「公共」(不帶下劃線開始)與他們的參數列表的函數列表中開始。您可以添加更多的東西打印kwargs,類等

一旦你所有你關心的封裝/模塊,在新老版本的運行,你將有兩個列表如下:

myPackage.myModule.myFunction1(foo, bar) 
myPackage.myModule.myFunction2(baz) 

然後,您可以對它們進行排序和比較,或者在Python中編寫一些更智能的工具來實際比較所有名稱,例如允許附加的可選參數但拒絕新的強制性參數。

+1

這種方法看起來相當簡單,並且很容易擴展到覆蓋types.ClassType和types.MethodType等。但我寧願不必導入正在檢查的模塊(我應該把它放在原始問題中)。我認爲靜態分析會更好,因爲它簡化了比較的運行時環境(例如,我認爲pylint是這樣工作的)。 –

0

查看zope.interfaces(你可以從PyPI獲取它)。然後,您可以將模塊支持接口的單元測試合併到您的單元測試中。可能需要一段時間才能適應復古風格 - 這也不是銀彈。

+0

所以這個想法是將zope.interface對象中的每個依賴包裝在一起,構成我針對新版本運行的驗收單元測試套件的一部分?這聽起來像是對綠地項目非常有效,但我認爲我現在的狀況會持續太久。 –

+0

是的。我認爲這是一個相當不錯的總結。我想我是在暗示你封鎖了接口背後的大部分代碼。我會有一個答案:) –

5

如何使用AST模塊解析文件?

import ast 

with file("test.py") as f: 
    python_src = f.read() 

    node = ast.parse(python_src) # Note: doesn't compile the src 
    print ast.dump(node) 

的astdump可能工作(可PyPI上)的AST節點(描述http://docs.python.org/2/library/ast.html

這種過時漂亮打印機 http://code.activestate.com/recipes/533146-ast-pretty-printer/

的文檔上的走法工具獅身人面像也提取您正在尋找的信息。也許給一看。

因此,走AST並用你想要的信息構建一棵樹。一旦你有了一棵樹,你可以醃製它,稍後再進行比較,或者將樹轉換爲 文本文件中的文本表示,您可以使用difftools或某個外部diff程序進行比較。

ast有parse()和compile()方法。唯一的問題是,我並不完全確定解析後有多少信息可用(因爲您不想編譯())。