Odoo13源碼-002:command.py

from __future__ import print_function
import logging
import sys
import os
from os.path import join as joinpath, isdir

import odoo
from odoo.modules import get_modules, get_module_path

commands = {}

"""
元類CommandType.
可以看到Command類裏定義了一個空run方法就沒了。但由於它的元類是CommandType(注意所有自定義的元類都要繼承自type),
在解釋器執行到Command類時,先收集代碼中定義的Command類的屬性,繼承列表等,然後由於這裏定義了元類,就不是直接調用type來創建一個了類了。
而是會調用元類的new方法,來創建一個類,然後調用元類的init方法。
這裏由於CommandType類沒有定義new方法,會直接調用其父類也就是type的new方法創建一個類,
然後傳給init方法執行初始化。在初始化的時候傳入了Command類的屬性,裝進了commands這個字典裏。
稍後到了Help類,由於其繼承自Command,也繼承了它的元類屬性,所以也會執行剛剛Command類創建時的一些操作,
從而也將Help類的一些屬性裝進了commands裏,server.py, shell.py中的繼承自Command的類也是如此。
然後後面main方法在遍歷commands字典,根據參數取出相應的類來執行其方法。這就實現了一種模式,
任何想要拓展commands的行爲,只需要繼承Command類,然後定義run方法就行了。感覺很不錯的思路。
"""
class CommandType(type):
    def __init__(cls, name, bases, attrs):
        super(CommandType, cls).__init__(name, bases, attrs)
        name = getattr(cls, name, cls.__name__.lower())
        cls.name = name
        if name != 'command':
            commands[name] = cls

Command = CommandType('Command', (object,), {'run': lambda self, args: None})

class Help(Command):
    """Display the list of available commands"""
    def run(self, args):
        print("Available commands:\n")
        names = list(commands)
        padding = max([len(k) for k in names]) + 2
        for k in sorted(names):
            name = k.ljust(padding, ' ')
            doc = (commands[k].__doc__ or '').strip()
            print("    %s%s" % (name, doc))
        print("\nUse '%s <command> --help' for individual command help." % sys.argv[0].split(os.path.sep)[-1])

"""
Main 主要過程:
1.獲取系統啓動參數
2.獲取模塊信息並導入
3.根據命令,實例化服務並啓動

"""

def main():
    args = sys.argv[1:]
    # 此處是獲取啓動參數

    # The only shared option is '--addons-path=' needed to discover additional
    # commands from modules
    """
    一般啓動odoo server的時候有多種方式,所需的一些參數我們可以直接在啓動命令上帶上,
    也可以寫到配置文件裏,然後啓動的時候用”-c”指定配置文件就行了.
    用得比較多的是啓動的時候只指定配置文件,所以以下開發直到 args = args[1:]不會被執行.
    """
    if len(args) > 1 and args[0].startswith('--addons-path=') and not args[1].startswith("-"):
        # parse only the addons-path, do not setup the logger...
        odoo.tools.config._parse_config([args[0]])
        args = args[1:]

    # Default legacy command  # 默認啓動命令的方式 爲‘server’
    command = "server"

    # TODO: find a way to properly discover addons subcommands without importing the world
    # Subcommand discovery
    if len(args) and not args[0].startswith("-"):
        logging.disable(logging.CRITICAL)
        for module in get_modules():  # 獲取模塊
            if isdir(joinpath(get_module_path(module), 'cli')):
                __import__('odoo.addons.' + module)  # 導入模塊
        logging.disable(logging.NOTSET)
        command = args[0]
        args = args[1:]

    if command in commands:
        """
        程序執行到這裏會發現,command默認值爲’server’是會在commands裏的.

        """
        o = commands[command]() # 獲取命令並執行, 實際是實例了一個 Server對象
        o.run(args)  # 調用Server的run()方法, 程序會執行到odoo.cli.server.main()方法
    else:
        sys.exit('Unknow command %r' % (command,))

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章