Skip to content

属性制約向けの意味ベースASTと可読表示を追加#752

Merged
yuji38kwmt merged 47 commits intomainfrom
20260428-1
Apr 29, 2026
Merged

属性制約向けの意味ベースASTと可読表示を追加#752
yuji38kwmt merged 47 commits intomainfrom
20260428-1

Conversation

@yuji38kwmt
Copy link
Copy Markdown
Collaborator

概要

  • 属性制約を名前ベースで扱える RestrictionAst を追加
  • Restriction と AST の相互変換、human-readable 表示、属性カタログ出力を追加
  • 既存の fluent API は維持したまま、LLM/CLI 連携しやすい層を追加

変更内容

  • Restriction.to_ast(), Restriction.from_ast(), Restriction.to_human_readable() を追加
  • RestrictionAst に to_dict(), from_dict(), to_restriction(), to_human_readable() を追加
  • get_attribute_restriction_catalog() を追加し、属性型ごとの許可AST種別や選択肢名を取得できるようにした
  • annotation_specs を使った妥当性検証を維持しつつ、AST から既存の Restriction / API JSON へ変換できるようにした
  • 関連テストを追加し、AST の round-trip・不正ケース・可読表示・catalog 出力を検証した

動作確認

  • pytest tests/util/test_attribute_restrictions.py

Copilot AI review requested due to automatic review settings April 28, 2026 15:08
@kci-pr-agent
Copy link
Copy Markdown

kci-pr-agent Bot commented Apr 28, 2026

Title

属性制約向けの意味ベースASTと可読表示を追加


Description

  • Restrictionにfrom_dict等変換メソッド追加

  • 意味ベースASTクラスRestrictionAstを導入

  • 属性カタログ取得関数を追加

  • 関連テストケースを大幅に追加


Changes walkthrough 📝

Relevant files
Enhancement
attribute_restrictions.py
制約ASTと変換メソッド追加                                                                                     

annofabapi/util/attribute_restrictions.py

  • Restrictionクラスにdict↔オブジェクト変換メソッド追加
  • to_python_expr, to_ast, to_human_readable導入
  • RestrictionAstクラスおよび関連ユーティリティ実装
  • get_attribute_restriction_catalog関数追加
  • +743/-51
    Tests
    test_attribute_restrictions.py
    制約AST関連テスト追加・拡充                                                                                   

    tests/util/test_attribute_restrictions.py

  • Restriction, RestrictionAstのテストケース追加
  • to_python_exprやto_human_readable検証
  • get_attribute_restriction_catalogテスト実装
  • +239/-1 

    Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • @kci-pr-agent
    Copy link
    Copy Markdown

    kci-pr-agent Bot commented Apr 28, 2026

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    属性種別サポート

    _get_allowed_ast_types_from_condition_dict_with_validation がすべてのアノテーション仕様の属性種別をカバーしているか確認してください。将来の仕様追加時に未対応例外が発生しないか要検討です。

    def _get_allowed_ast_types(attribute_type: str) -> list[str]:
        if attribute_type == "flag":
            return ["can_input", "checked", "unchecked"]
        if attribute_type in {"text", "comment"}:
            return ["can_input", "is_empty", "is_not_empty", "equals_string", "not_equals_string", "matches_string", "not_matches_string"]
        if attribute_type == "integer":
            return ["can_input", "is_empty", "is_not_empty", "equals_integer", "not_equals_integer"]
        if attribute_type == "link":
            return ["can_input", "is_empty", "is_not_empty", "has_label"]
        if attribute_type == "tracking":
            return ["can_input", "is_empty", "is_not_empty", "equals_string", "not_equals_string"]
        if attribute_type in {"choice", "select"}:
            return ["can_input", "is_empty", "is_not_empty", "has_choice", "not_has_choice"]
        raise ValueError(f"未対応の属性種類です。 :: attribute_type='{attribute_type}'")
    例外メッセージ整合性

    _validate_restriction_ast_raise_invalid_restriction の日本語メッセージがテストの正規表現と常に一致するか確認してください。不一致だとテストが壊れる可能性があります。

    def _validate_restriction_ast(ast: RestrictionAst) -> None:
        type_to_fields = {
            "checked": {"attribute_name"},
            "unchecked": {"attribute_name"},
            "is_empty": {"attribute_name"},
            "is_not_empty": {"attribute_name"},
            "equals_string": {"attribute_name", "value"},
            "not_equals_string": {"attribute_name", "value"},
            "matches_string": {"attribute_name", "value"},
            "not_matches_string": {"attribute_name", "value"},
            "equals_integer": {"attribute_name", "value"},
            "not_equals_integer": {"attribute_name", "value"},
            "has_choice": {"attribute_name", "choice_name"},
            "not_has_choice": {"attribute_name", "choice_name"},
            "has_label": {"attribute_name", "label_names"},
            "can_input": {"attribute_name", "enable"},
            "imply": {"premise", "conclusion"},
        }
        required_fields = type_to_fields.get(ast.type)
        if required_fields is None:
            raise ValueError(f"未知のAST種別です。 :: type='{ast.type}'")
    
        actual_fields = {
            field_name
            for field_name, value in (
                ("attribute_name", ast.attribute_name),
                ("value", ast.value),
                ("choice_name", ast.choice_name),
                ("enable", ast.enable),
                ("label_names", ast.label_names),
                ("premise", ast.premise),
                ("conclusion", ast.conclusion),
            )
            if value is not None
        }
        if actual_fields != required_fields:
            raise ValueError(
                f"AST種別'{ast.type}'のフィールドが不正です。 :: required={sorted(required_fields)}, actual={sorted(actual_fields)}"
            )
    ドキュメント例示

    モジュールレベルの Example: 部分がコードブロックとしてマークアップされていません。可読性向上のために適切なドキュメント形式(pythonなど)の追加を検討してください。

    Example:
        >>> import annofabapi
        >>> from annofabapi.util.attribute_restrictions import AttributeFactory
        >>> service = annofabapi.build()
        >>> annotation_specs, _ = service.api.get_annotation_specs("prj1", query_params={"v": "3"})
        >>> fac = AttributeFactory(annotation_specs)
    
        >>> premise_restriction = fac.checkbox(attribute_name="occluded").checked()
        >>> conclusion_restriction = fac.string_textbox(attribute_name="note").is_not_empty()
        >>> restriction = premise_restriction.imply(conclusion_restriction)
        >>> restriction.to_dict()
        {
            "additional_data_definition_id": "9b05648d-1e16-4ea2-ab79-48907f5eed00",
            "condition": {
                "_type": "Imply",
                "premise": {
                    "additional_data_definition_id": "2517f635-2269-4142-8ef4-16312b4cc9f7",
                    "condition": {"_type": "Equals", "value": "true"},
                },
                "condition": {"_type": "NotEquals", "value": ""},
            },
        }

    Comment thread annofabapi/util/attribute_restrictions.py Outdated
    Copy link
    Copy Markdown

    Copilot AI left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Pull request overview

    属性制約(annotation_specs の restrictions)を、従来の fluent API を維持しつつ、LLM/CLI 連携しやすい「名前ベースの意味AST」と「可読表示」に変換できる層を追加するPRです。

    Changes:

    • Restriction に dict/AST/Python式/可読表示への変換・復元APIを追加
    • RestrictionAst と、属性型ごとの許可AST種別等を返す catalog 生成を追加
    • 追加機能の round-trip・不正ケース・可読表示・catalog のテストを追加

    Reviewed changes

    Copilot reviewed 2 out of 2 changed files in this pull request and generated 11 comments.

    File Description
    annofabapi/util/attribute_restrictions.py Restriction/AST 相互変換・可読表示・catalog 出力などの中核実装を追加
    tests/util/test_attribute_restrictions.py 新API(from/to dict, AST, human readable, catalog)のテストを追加

    Comment thread annofabapi/util/attribute_restrictions.py Outdated
    Comment thread annofabapi/util/attribute_restrictions.py Outdated
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Comment thread annofabapi/util/attribute_restrictions.py Outdated
    Comment thread annofabapi/util/attribute_restrictions.py Outdated
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Comment thread annofabapi/util/attribute_restrictions.py
    Comment thread annofabapi/util/attribute_restrictions.py Outdated
    Copilot AI review requested due to automatic review settings April 28, 2026 15:31
    Copy link
    Copy Markdown

    Copilot AI left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Pull request overview

    属性制約を「属性名ベース」で扱える意味ベースAST(RestrictionAst)層を追加し、既存の fluent API(Restriction)と相互変換・可読表示・LLM向けカタログ出力を可能にする変更です。Annofab API の restrictions JSON と、人間/LLM/CLI が扱いやすい表現の橋渡しを annofabapi.util に組み込みます。

    Changes:

    • Restriction に AST 変換(to_ast / from_ast)と可読表示(to_human_readable)、dict復元(from_dict)を追加
    • RestrictionAst(dataclass)と、属性ごとの利用可能AST種別などを返す get_attribute_restriction_catalog() を追加
    • round-trip / 不正ケース / 可読表示 / catalog 出力のテストを追加

    Reviewed changes

    Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

    Show a summary per file
    File Description
    annofabapi/util/attribute_restrictions.py Restriction↔AST変換、可読表示、カタログ生成、dict復元などを追加
    tests/util/test_attribute_restrictions.py AST round-trip・不正系・可読表示・カタログ出力のテストを追加
    AGENTS.md エージェント向けの作業/レビュー方針を追加
    .github/copilot-instructions.md 参照先を AGENTS.md / .agents/skills/ に変更
    .codex/config.toml Codex 実行用の設定を追加
    .agents/skills/test-writing/SKILL.md テスト方針(pytest.raisesの扱い等)を追加
    .agents/skills/python-coding-style/SKILL.md Python コーディングスタイルの方針を追加

    Comment thread annofabapi/util/attribute_restrictions.py Outdated
    Comment thread annofabapi/util/attribute_restrictions.py Outdated
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Comment on lines +409 to +410
    with pytest.raises(ValueError, match="属性'tracking'\\(type='tracking'\\)ではAST種別'matches_string'を利用できません。"):
    ast.to_restriction(accessor.annotation_specs)
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Copilot AI review requested due to automatic review settings April 28, 2026 17:27
    Copy link
    Copy Markdown

    Copilot AI left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Pull request overview

    属性制約(additional_data の restrictions)を、属性IDベースの既存 fluent API を維持したまま「属性名ベースで扱える意味ベースAST」に変換・復元できる層を追加し、CLI/LLM 連携や人間向け表示、カタログ出力を可能にするPRです。

    Changes:

    • RestrictionRestrictionAst の相互変換(AST種別 RestrictionAstType)と human-readable 表示を追加
    • 属性型ごとの許可AST種別や選択肢/ラベル名を返す get_attribute_restriction_catalog() を追加
    • annotation_specs ユーティリティに TypedDict を導入し、テストを拡充(round-trip / 不正ケース / 表示 / catalog)

    Reviewed changes

    Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.

    Show a summary per file
    File Description
    annofabapi/util/attribute_restrictions.py RestrictionAst/変換/可読表示/カタログ出力の実装を追加
    annofabapi/util/annotation_specs.py annotation_specs 周りを TypedDict で型付けし、choice/label/attribute取得関数を更新
    tests/util/test_attribute_restrictions.py AST round-trip・不正ケース・可読表示・catalog のテストを追加
    tests/util/test_annotation_specs.py choice の型注釈を追加し、TypedDict導入に追従
    AGENTS.md エージェント運用・作業方針のドキュメントを追加
    .github/copilot-instructions.md 参照先を AGENTS.md / .agents/skills/ に整理
    .codex/config.toml Codex 実行設定(sandbox/ネットワーク/承認ポリシー等)を追加
    .agents/skills/test-writing/SKILL.md テスト方針(pytest.raises等)を明文化
    .agents/skills/python-coding-style/SKILL.md Python コーディングスタイルを明文化

    Comment thread .codex/config.toml
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Comment thread tests/util/test_attribute_restrictions.py Outdated
    Comment thread annofabapi/util/attribute_restrictions.py
    Comment thread annofabapi/util/attribute_restrictions.py
    Comment on lines +626 to +635
    for attribute in accessor.additionals:
    attribute_type = attribute["type"]
    choice_names = None
    label_names = None
    match attribute_type:
    case "choice" | "select":
    choice_names = [get_english_message(choice["name"]) for choice in _get_attribute_choices(attribute)]
    case "link":
    label_names = [get_english_message(label["label_name"]) for label in accessor.labels]
    item = AttributeRestrictionCatalogItem(
    Comment thread .codex/config.toml
    @yuji38kwmt yuji38kwmt requested a review from Copilot April 28, 2026 18:16
    Copy link
    Copy Markdown

    Copilot AI left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Pull request overview

    属性制約を「IDベースのRestriction(JSON)」だけでなく「属性名ベースの意味AST(RestrictionAst)」として扱える層を追加し、LLM/CLI連携や人間向け表示・属性カタログ出力を可能にするPRです。

    Changes:

    • RestrictionRestrictionAst の相互変換と、human-readable 表示を追加
    • 属性型ごとの許可AST種別・選択肢/ラベル名を返すカタログAPIを追加
    • annotation_specs 周りの型(TypedDict)強化と、上記機能のテスト追加

    Reviewed changes

    Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

    Show a summary per file
    File Description
    annofabapi/util/attribute_restrictions.py 意味ベースAST・相互変換・human-readable・属性カタログ生成を追加
    annofabapi/util/annotation_specs.py AttributeDefinition等のTypedDict導入、関連関数/Accessorの型を具体化
    tests/util/test_attribute_restrictions.py AST round-trip、妥当性違反、可読表示、catalog出力のテストを追加
    tests/util/test_annotation_specs.py AttributeChoice 型注釈の追加
    AGENTS.md エージェント作業/方針ドキュメントを追加
    .github/copilot-instructions.md 参照先を AGENTS.md 等に集約
    .codex/config.toml Codex実行設定を追加
    .agents/skills/test-writing/SKILL.md テスト作法のスキル定義を追加
    .agents/skills/python-coding-style/SKILL.md Pythonコーディング作法のスキル定義を追加

    Comment thread annofabapi/util/attribute_restrictions.py
    Comment thread tests/util/test_attribute_restrictions.py
    Comment thread tests/util/test_attribute_restrictions.py
    Comment thread tests/util/test_attribute_restrictions.py
    Copilot AI review requested due to automatic review settings April 29, 2026 01:08
    Copy link
    Copy Markdown

    Copilot AI left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Pull request overview

    属性制約を「属性ID中心のAPI JSON」だけでなく「属性名中心の意味ベースAST」として扱えるようにし、LLM/CLI連携しやすい変換・可読表示・カタログ出力までを annofabapi.util 層に追加するPRです。

    Changes:

    • 属性制約の意味ベースAST(RestrictionAst/RestrictionAstType)と、Restriction ⇄ AST の相互変換・可読表示を追加
    • 属性型ごとの許可AST種別や choice/label 名一覧を返すカタログ出力(get_attribute_restriction_catalog)を追加
    • annotation_specs の型情報(TypedDict)を拡充し、関連テストを追加・既存テスト方針(例外メッセージ一致検証をしない)に合わせて更新

    Reviewed changes

    Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

    Show a summary per file
    File Description
    tests/util/test_page.py pytest.raises(..., match=...) をやめ、例外型のみ検証するテスト方針に合わせて修正
    tests/util/test_attribute_restrictions.py AST round-trip、妥当性、可読表示、catalog出力のテストを追加
    tests/util/test_annotation_specs.py AttributeChoice 型導入に合わせてテストの型注釈を更新
    annofabapi/util/attribute_restrictions.py RestrictionAst/カタログ/相互変換/可読表示などの主要機能を実装
    annofabapi/util/annotation_specs.py TypedDict導入と AnnotationSpecsAccessor の型付け強化
    AGENTS.md エージェント実行環境・進め方ガイドを追加
    .github/copilot-instructions.md 参照先を AGENTS.md / .agents/skills/ に集約
    .codex/config.toml Codex用のsandbox/approval設定を追加
    .agents/skills/test-writing/SKILL.md テスト方針(例外メッセージ一致検証しない等)を明文化
    .agents/skills/python-coding-style/SKILL.md Pythonコーディングスタイル(match推奨等)を明文化

    Comment thread annofabapi/util/attribute_restrictions.py
    @yuji38kwmt yuji38kwmt merged commit f9d3b7d into main Apr 29, 2026
    13 checks passed
    @yuji38kwmt yuji38kwmt deleted the 20260428-1 branch April 29, 2026 01:30
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Labels

    None yet

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    2 participants