Pythonでの構成の編集





他の人の構成ファイルを解析し、プログラムで変更する必要がありましたか? そして、NSDやBIND9のような異常な形式のファイルでは? そして、形式が改行、意味的なインデント、およびコメントの保存を提供する場合、タスクはすぐに些細なカテゴリを離れます。



それが、 python-reconfigureライブラリをあなたと共有している理由です。





このライブラリは、設定ファイルのテキストとpythonオブジェクトの間のオブジェクトマッピングを提供します。

再構成はファイルを決して「壊す」ことはなく、内部のなじみのないブロックやオプションを恥ずかしがらず、コメントも保存します。



例に移りましょう:



>>> from reconfigure.configs import FSTabConfig >>> from reconfigure.items.fstab import FilesystemData >>> >>> config = FSTabConfig(path='/etc/fstab') >>> config.load() >>> print config.tree { "filesystems": [ { "passno": "0", "device": "proc", "mountpoint": "/proc", "freq": "0", "type": "proc", "options": "nodev,noexec,nosuid" }, { "passno": "1", "device": "UUID=dfccef1e-d46c-45b8-969d-51391898c55e", "mountpoint": "/", "freq": "0", "type": "ext4", "options": "errors=remount-ro" } ] } >>> tmpfs = FilesystemData() >>> tmpfs.mountpoint = '/srv/cache' >>> tmpfs.type = 'tmpfs' >>> tmpfs.device = 'none' >>> config.tree.filesystems.append(tmpfs) >>> config.save() >>> quit() $ cat /etc/fstab proc /proc proc nodev,noexec,nosuid 0 0 UUID=dfccef1e-d46c-45b8-969d-51391898c55e / ext4 errors=remount-ro 0 1 none /srv/cache tmpfs none 0 0
      
      







再構成はモジュラーシステムであり、*構成クラスはいくつかの内部ロジックを隠します。

前の例が「内部」でどのように機能するかを検討してください。

最初に、ファイルのテキストはパーサーによって抽象的な構文ツリーに変換されます。



 >>> from reconfigure.parsers import SSVParser >>> from reconfigure.builders import BoundBuilder >>> content = open('/etc/fstab').read() >>> syntax_tree = SSVParser().parse(content) >>> syntax_tree <reconfigure.nodes.RootNode object at 0x7f1319eeec50> >>> print syntax_tree (None) (line) (token) value = proc (token) value = /proc (token) value = proc (token) value = nodev,noexec,nosuid (token) value = 0 (token) value = 0 (line) (token) value = UUID=83810b56-ef4b-44de-85c8-58dc589aef48 (token) value = / (token) value = ext4 (token) value = errors=remount-ro (token) value = 0 (token) value = 1
      
      







次に、Builderクラスは通常のpythonオブジェクトを作成し、それらを構文ツリーにバインドします。



 >>> builder = BoundBuilder(FSTabData) >>> data_tree = builder.build(syntax_tree) >>> print data_tree { "filesystems": [ { "passno": "0", "device": "proc", "mountpoint": "/proc", "freq": "0", "type": "proc", "options": "nodev,noexec,nosuid" }, { "passno": "1", "device": "UUID=83810b56-ef4b-44de-85c8-58dc589aef48", "mountpoint": "/", "freq": "0", "type": "ext4", "options": "errors=remount-ro" } ] }
      
      







実際、作成されたオブジェクトはプロキシクラスであり、そのすべてのフィールドはプロパティであり、変更すると、構文ツリーの値が変更されます。



 >>> syntax_tree.children[0] <reconfigure.nodes.Node object at 0x7f51c63b9f10> >>> print syntax_tree.children[0] (line) (token) value = proc (token) value = /proc (token) value = proc (token) value = nodev,noexec,nosuid (token) value = 0 (token) value = 0 >>> data_tree.filesystems[0].options += ',rw' >>> print syntax_tree.children[0] (line) (token) value = proc (token) value = /proc (token) value = proc (token) value = nodev,noexec,nosuid,rw (token) value = 0 (token) value = 0
      
      







ツリー要素をクラスフィールドにバインドするためのルールは、*データクラスで設定されます。

/etc/resolv.confファイル内のデータのバインディングの例:



 from reconfigure.nodes import Node, PropertyNode from reconfigure.items.bound import BoundData class ResolvData (BoundData): pass class ItemData (BoundData): def template(self): return Node('line', children=[ Node('token', children=[PropertyNode('value', 'nameserver')]), Node('token', children=[PropertyNode('value', '8.8.8.8')]), ]) ResolvData.bind_collection('items', item_class=ItemData) ItemData.bind_property('value', 'name', path=lambda x: x.children[0]) ItemData.bind_property('value', 'value', path=lambda x: x.children[1])
      
      







このファイルの内容、構文、およびデータツリーは次のとおりです。



 >>> print open('/etc/resolv.conf').read() # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8) # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN nameserver 127.0.0.1 >>> print syntax_tree (None) (line) (Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8) DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN) (token) value = nameserver (token) value = 127.0.0.1 >>> print data_tree { "items": [ { "name": "nameserver", "value": "127.0.0.1" } ] }
      
      







さらに、Reconfigureは一部のファイルにincludeディレクティブが存在することを認識し、どのファイルに含まれていたかを記憶します。



再構成は、独自のパーサー、ビルダー、インクルーダーを使用て簡単に拡張できます。



現在、再構成はAjenti 1.0 Betaの中心ですが、次回はさらに詳しく説明します:)



Github

PYPI

ドキュメント

Ajentiリポジトリで利用可能なDEBおよびRPMパッケージ



All Articles