AttributeError: 'NoneType' object has no attribute 'label'
trac.ini に設定している [ticket-submit-policy] の内容が正しくないように見えます。その内容も記述していただけますか?
trac.iniは以下を設定しています。 これはtrac管理画面の「サブミットポリシー」で設定した結果、自動的にiniにセットされたようで直接編集したものではありません。
[ticket-submit-policy] policy1.condition = status is accepted policy1.readonly = summary, shokuban, shimei, s_assy, nozu, inflink, memo policy2.condition = type is 報告 policy2.readonly = owner, description, type policy2.requires = summary, shokuban, shimei, s_assy, nozu
何度か試してみましたが、再現しません。またコードから見えても再現しそうにありません。
https://trac-hacks.org/wiki/TicketSubmitPolicyPlugin を元に日本語化したものなのは確かですが、オリジナルのほうには該当部分にあたるコードはなく、また、日本語化の作業分のログが完全にないため、修正内容の意味がまったく追跡できません。
とりあえず、以下のように変更してみて、再発時に再度スタックトレースを送って頂けますか。
diff --git a/ticketsubmitpolicy/ticketsubmitpolicy.py b/ticketsubmitpolicy/ticketsubmitpolicy.py index cbb1381ca..8f1a57ccd 100644 --- a/ticketsubmitpolicy/ticketsubmitpolicy.py +++ b/ticketsubmitpolicy/ticketsubmitpolicy.py @@ -136,7 +136,7 @@ class TicketSubmitPolicyPlugin(Component): if not policies[name].has_key('actions'): policies[name]['actions'] = [] args = parse_list(section[key]) - policies[name]['actions'].append({'name': action, 'args': args, 'label': policy_dict.get(action).label()}) + policies[name]['actions'].append({'name': action, 'args': args, 'label': policy_dict[action].label()}) for policy in policies: # empty condition ==> true
もしくはこれを使う事自体を放棄して、オリジナル https://trac-hacks.org/wiki/TicketSubmitPolicyPlugin のほうを試してみるのが妥当かも知れません。
ticketsubmitpolicy.pyを指示通り変更、コンパイルして試してみましたがそもそものポリシーが適用されなくなりました。
具体的には、ステータスがacceptedの状態にもかかわらず入力項目が読み取り専用ではなくなります。
オリジナルも過去に試したのですが、上記と同様にポリシーが効かなくなるため0.13を利用させてもらったという経緯があります。
いまの修正だけで動かなくなるとは到底思えないのですが…。手元 (添付 20170228T143121.png) では summary が readonly になっています。
修正に間違いはないはずなのですが、こちらの環境ではどの項目もreadonlyとなりません。
if not policies[name].has_key('actions'): policies[name]['actions'] = [] args = parse_list(section[key]) # policies[name]['actions'].append({'name': action, 'args': args, 'label': policy_dict.get(action).label()}) #2017.2.28 policies[name]['actions'].append({'name': action, 'args': args, 'label': policy_dict[action].label()}) for policy in policies: # empty condition ==> true
if not policies[name].has_key('actions'): policies[name]['actions'] = [] args = parse_list(section[key]) # policies[name]['actions'].append({'name': action, 'args': args, 'label': policy_dict.get(action).label()}) #2017.2.28 policies[name]['actions'].append({'name': action, 'args': args, 'label': policy_dict[action].label()}) ^ インデントずれていますが、これだと syntax error が吐かれているはずです。ここに貼り付ける際のミスでしょうか for policy in policies: # empty condition ==> true
svn revert - R . を実行して変更を破棄したら、添付ファイルの r821.diff を使って patch -p1 < r821.diff を実行してください。適用したら svn diff で変更が妥当か確認してください。
申し訳ありません。
こちらのミスがありました。
この状態で動作させ、再現しましたら再度ログを記載いたします。
アドバイスいただいたソースに変更後、再現しました。
ログを添付します。(が、前と出力内容は同様です。)
2017-03-02 13:21:03,824 Trac[main] ERROR: Internal Server Error: Traceback (most recent call last): File "/usr/lib/python2.4/site-packages/trac/web/main.py", line 511, in _dispatch_request dispatcher.dispatch(req) File "/usr/lib/python2.4/site-packages/trac/web/main.py", line 258, in dispatch content_type) File "/usr/lib/python2.4/site-packages/trac/web/chrome.py", line 840, in render_template stream |= self._filter_stream(req, method, filename, stream, data) File "build/bdist.linux-i686/egg/genshi/core.py", line 132, in __or__ File "/usr/lib/python2.4/site-packages/trac/web/chrome.py", line 991, in inner data) File "build/bdist.linux-i686/egg/ticketsubmitpolicy/ticketsubmitpolicy.py", line 167, in filter_stream File "build/bdist.linux-i686/egg/ticketsubmitpolicy/ticketsubmitpolicy.py", line 139, in parse AttributeError: 'NoneType' object has no attribute 'label'
パッチでは以下のように変更しました。
-policy_dict.get(action).label() +policy_dict[action].label()ここで相変わらず AttributeError が上がってくるということは policy_dict[action] が None であるということなのですが、policy_dict は self.policy_dict() の戻り値で、
94 policies = {} 95 policy_dict = self.policy_dict()こういう実装になっています。dict に入っている値が None になっているかどうかで言えば、ここでは self.policies のリストから None が出てくる必要があります。しかし policy.name() をキーにしているので None であれば、そもそもここでエラーを吐くはずです。
52 def policy_dict(self): 53 retval = {} 54 for policy in self.policies: 55 retval[policy.name()] = policy 56 return retval要は、そのパッチを当てたソースはちゃんとインストールできていますか。
単に policy_dict と action の値が確認したいだけなので、以下のパッチに差し替えます。これで再現したら、その変数もログに出力されるはずですので、それも投稿してください。
適用できているかは、チケットページなどを参照した際に 2017-03-02 14:47:26 というログが出力されるはずですので、それでチェックしてください。
diff --git a/ticketsubmitpolicy/ticketsubmitpolicy.py b/ticketsubmitpolicy/ticketsubmitpolicy.py index cbb1381ca..aaa22d2e8 100644 --- a/ticketsubmitpolicy/ticketsubmitpolicy.py +++ b/ticketsubmitpolicy/ticketsubmitpolicy.py @@ -53,6 +53,7 @@ class TicketSubmitPolicyPlugin(Component): retval = {} for policy in self.policies: retval[policy.name()] = policy + self.log.warning('policy_dict: %r', retval) return retval def save(self, policies): @@ -85,6 +86,7 @@ class TicketSubmitPolicyPlugin(Component): """ parse the [ticket-submit-policy] section of the config for policy rules """ + self.log.warning('2017-03-02 14:47:26') section = dict([i for i in self.config.options('ticket-submit-policy')]) @@ -136,7 +138,8 @@ class TicketSubmitPolicyPlugin(Component): if not policies[name].has_key('actions'): policies[name]['actions'] = [] args = parse_list(section[key]) - policies[name]['actions'].append({'name': action, 'args': args, 'label': policy_dict.get(action).label()}) + self.log.warning('policy_dict: %r, action: %r', policy_dict, action) + policies[name]['actions'].append({'name': action, 'args': args, 'label': policy_dict[action].label()}) for policy in policies: # empty condition ==> true
いただいた情報を適用し再現しました。以下にログを添付いたします。
「2017-03-02 14:47:26 」の情報が出力されているため間違いないかと思いますが、trac、pythonについてまだ勉強中で不慣れなもので 何か間違いあるようでしたら指摘よろしくお願いします。
2017-03-03 10:23:26,621 Trac[ticketsubmitpolicy] WARNING: 2017-03-02 14:47:26 2017-03-03 10:23:26,621 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.TicketExcludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'requires': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>} 2017-03-03 10:23:26,621 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.TicketExcludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'requires': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>}, action: u'readonly' 2017-03-03 10:23:26,622 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.TicketExcludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'requires': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>}, action: u'readonly' 2017-03-03 10:23:26,622 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>}, action: u'requires' 2017-03-03 10:23:31,152 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>} 2017-03-03 10:23:31,153 Trac[ticketsubmitpolicy] WARNING: 2017-03-02 14:47:26 2017-03-03 10:23:31,153 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>} 2017-03-03 10:23:31,153 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>}, action: u'readonly' 2017-03-03 10:23:31,154 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>}, action: u'readonly' 2017-03-03 10:23:31,154 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>}, action: u'requires' 2017-03-03 10:23:32,947 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>} 2017-03-03 10:23:32,947 Trac[ticketsubmitpolicy] WARNING: 2017-03-02 14:47:26 2017-03-03 10:23:32,948 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>} 2017-03-03 10:23:32,948 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>}, action: u'readonly' 2017-03-03 10:23:32,948 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>}, action: u'readonly' 2017-03-03 10:23:32,948 Trac[ticketsubmitpolicy] WARNING: policy_dict: {'excludes': <ticketsubmitpolicy.policies.Ticket Excludes object at 0x1172372c>, 'readonly': <ticketsubmitpolicy.policies.TicketReadOnly object at 0x117238cc>, 'require s': <ticketsubmitpolicy.policies.TicketRequires object at 0x11723a4c>}, action: u'requires' 2017-03-03 10:23:59,335 Trac[main] ERROR: Internal Server Error: Traceback (most recent call last): File "/usr/lib/python2.4/site-packages/trac/web/main.py", line 511, in _dispatch_request dispatcher.dispatch(req) File "/usr/lib/python2.4/site-packages/trac/web/main.py", line 258, in dispatch content_type) File "/usr/lib/python2.4/site-packages/trac/web/chrome.py", line 840, in render_template stream |= self._filter_stream(req, method, filename, stream, data) File "build/bdist.linux-i686/egg/genshi/core.py", line 132, in __or__ File "/usr/lib/python2.4/site-packages/trac/web/chrome.py", line 991, in inner data) File "build/bdist.linux-i686/egg/ticketsubmitpolicy/ticketsubmitpolicy.py", line 167, in filter_stream File "build/bdist.linux-i686/egg/ticketsubmitpolicy/ticketsubmitpolicy.py", line 139, in parse AttributeError: 'NoneType' object has no attribute 'label'
例外が起きた場所よりも前の箇所にログ出力のコードを足したので同じ例外が起きた場合、その行数が変わるはずであるにも関わらず、変わっていません。
File "build/bdist.linux-i686/egg/ticketsubmitpolicy/ticketsubmitpolicy.py", line 139, in parse AttributeError: 'NoneType' object has no attribute 'label'ログ追加したモジュールと件の例外を起こしているモジュールは別の場所にあり、別々にロードされていると考えます。 そもそも件の例外ではソースの一部が表示されていません。(139行目のコードが出力されるはずが見えない)
そもそもインストール手順が間違っているのではないでしょうか。
お手数おかけして申し訳ありません。
インストールは以下のようにして実施しております。
・既存のプラグインをプロジェクトから削除 ・apachectl graceful
・ダウンロード svn co http://svn.sourceforge.jp/svnroot/shibuya-trac/plugins/ticketsubmitpolicy/trunk
・指示があった通りticketsubmitpolicy.pyを修正
・コンパイル python setup.py bdist_egg
・/var/trac/project/xxx/trac/plugins/配下にeggをコピー ※プロジェクト単位でプラグインを動作させています。
apachectl graceful
以下は具体的に教えていただいてよろしいでしょうか。 •egg-cache 上に展開されているものがあれば、それも完全に捨ててください。
/var/trac/project/xxx/trac/plugins/配下にeggをコピー ※プロジェクト単位でプラグインを動作させています。
ここがおかしいです。これはすべてのプロジェクトにコピーしているんでしょうか。
Apache の設定はどのようにしてありますか。mod_wsgi か mod_python で TRAC_ENV_PARENT_DIR または trac.env_parent_dir を設定して複数プロジェクトにアクセスできるようにしてあると推測しています。が、この場合に、Trac プロジェクトごとに python プロセスが生成されるのではないため、egg ファイルを投入したプロジェクト以外からもそのプラグインはロードされています。
複数の Trac プロジェクトの plugins ディレクトリに同じでないプラグインが配置してあると妙なことが起きるはずです。
こういう場合は、プロジェクトにある plugins ディレクトリは使わずに、プラグインを配置するディレクトリを用意して [inherit] plugins_dir オプションに指定するほうがよいです。([inherit] file を使っていれば、そのファイルにだけ指定するようにもできます)
これとは違う状況であれば、Apache の設定を教えてください。
p.s. 謝罪は不要です
ご推察の通りです。
trac.env_parent_dirを設定してプロジェクト単位にて設定しております。
が、pythonのプロセスは生成されないとのこと、今回のエラーはこちらの環境に依存して発生しているということですね。
プラグインディレクトリの配置変更を検討いたします。 ありがとうございました。
TicketSubmitPolicy-0.13-py2.4に不具合と思われる事象発生のため起票いたします。 「チケット登録」や「チケットを見る」をクリックすると不定期で発生する。 apachectl gracefulを実施すると発生頻度が少なくなる。
ログは以下の通り