# tabtest
Tableauの`.twb`/`.twbx`ファイルを解析し、pytestでテストを実行できるPythonライブラリです。
## 概要
tabtestは、Tableauワークブックの構造を解析し、pytestを使用してワークブックの内容をテストできるようにするツールです。以下のようなテストが可能です:
- データソースの存在確認
- 計算フィールドの存在確認
- ワークシートの設定確認
- ダッシュボードのレイアウト確認
- パラメータの設定確認
- フィルターの設定確認
## インストール
```bash
pip install tabtest
```
## 基本的な使用方法
### 1. ワークブックの解析
```python
from tabtest import WorkbookParser
# ワークブックを解析
parser = WorkbookParser("./path/to/your/workbook.twb")
workbook = parser.workbook
# 基本情報の確認
print(f"ワークブック名: {workbook.name}")
print(f"データソース数: {len(workbook.datasources)}")
print(f"ワークシート数: {len(workbook.sheets)}")
print(f"ダッシュボード数: {len(workbook.dashboards)}")
```
### 2. pytestでのテスト
```python
import pytest
from tabtest.suite.helpers import (
assert_workbook_has_datasource,
assert_workbook_has_sheet,
assert_workbook_has_dashboard,
assert_datasource_has_calculated_field,
)
def test_workbook_structure(workbook_fixture):
"""ワークブックの基本構造をテスト"""
workbook = workbook_fixture
# データソースの確認
data_ds = assert_workbook_has_datasource(
workbook, "mock_datasource"
)
# 計算フィールドの確認
assert_datasource_has_calculated_field(
data_ds, "mock_calculated_field"
)
# ワークシートの確認
sheet = assert_workbook_has_sheet(workbook, "mock_sheet")
assert sheet.mark_type == "bar"
# ダッシュボードの確認
dashboard = assert_workbook_has_dashboard(workbook, "mock_dashboard")
assert dashboard.size_width == 1200
assert dashboard.size_height == 800
```
### 3. 利用可能なフィクスチャ
#### 汎用フィクスチャ(tabtestライブラリ提供)
pytestで以下の汎用フィクスチャが利用できます:
- `workbook_parser`: カスタムワークブックパーサー
- `workbook`: 解析済みワークブック
- `workbook_fixture`: モックワークブック(tests/assets/mock_workbook.twb)
使用方法:
```python
@pytest.mark.parametrize("workbook_parser", ["./path/to/your/workbook.twb"], indirect=True)
def test_workbook(workbook_parser):
assert workbook_parser.workbook.name == "Expected Name"
@pytest.mark.parametrize("workbook_parser", ["./path/to/your/workbook.twb"], indirect=True)
def test_workbook(workbook):
assert workbook.name == "Expected Name"
assert len(workbook.datasources) > 0
def test_with_mock_workbook(workbook_fixture):
"""モックワークブックを使用したテスト"""
workbook = workbook_fixture
assert workbook.name == "Mock Workbook"
assert len(workbook.datasources) > 0
```
#### ユーザー固有フィクスチャ
ユーザーは`tests/fixtures.py`で固有のフィクスチャを定義できます:
```python
# tests/fixtures.py
import pytest
from tabtest import WorkbookParser
@pytest.fixture
def my_workbook():
"""ユーザー固有のワークブックフィクスチャ"""
parser = WorkbookParser("./path/to/your/workbook.twb")
return parser.workbook
```
### 4. ヘルパー関数
以下のヘルパー関数が利用できます:
```python
from tabtest.suite.helpers import (
# ワークブックレベル
assert_workbook_has_datasource,
assert_workbook_has_sheet,
assert_workbook_has_dashboard,
# データソースレベル
assert_datasource_has_field,
assert_datasource_has_calculated_field,
# ワークシートレベル
assert_sheet_has_field_in_rows,
assert_sheet_has_field_in_columns,
assert_sheet_has_filter,
# ダッシュボードレベル
assert_dashboard_contains_sheet,
)
```
## データモデル
### WorkbookModel
ワークブック全体の情報を表すモデルです。
```python
class WorkbookModel:
name: str # ワークブック名
datasources: List[DatasourceModel] # データソース一覧
sheets: Dict[str, WorksheetModel] # ワークシート一覧
dashboards: List[DashboardModel] # ダッシュボード一覧
parameters: List[ParameterModel] # パラメータ一覧
```
### DatasourceModel
データソースの情報を表すモデルです。
```python
class DatasourceModel:
name: Optional[str] # データソース名
caption: Optional[str] # キャプション
fields: List[DatasourceFieldModel] # フィールド一覧
```
### WorksheetModel
ワークシートの情報を表すモデルです。
```python
class WorksheetModel:
name: str # ワークシート名
datasource_name: str # データソース名
filters: List[FilterModel] # フィルター一覧
rows: List[str] # 行に配置されたフィールド
columns: List[str] # 列に配置されたフィールド
mark_type: Optional[str] # マークタイプ
```
### DashboardModel
ダッシュボードの情報を表すモデルです。
```python
class DashboardModel:
name: Optional[str] # ダッシュボード名
dashboard_sheets: List[DashboardSheetModel] # ダッシュボード内のワークシート
size_width: int # ダッシュボード幅
size_height: int # ダッシュボード高さ
```
## 使用例
詳細な使用例は`examples/`ディレクトリを参照してください:
- `examples/basic_usage.py`: 基本的な使用方法
- `examples/pytest_example.py`: pytestでのテスト例
## 開発
### セットアップ
```bash
# リポジトリをクローン
git clone https://github.com/your-username/tabtest.git
cd tabtest
# 仮想環境を作成
python -m venv .venv
source .venv/bin/activate # Linux/Mac
# または
.venv\Scripts\activate # Windows
# 依存関係をインストール
pip install -e .
pip install -e ".[dev]"
```
### テストの実行
```bash
# すべてのテストを実行
pytest
# 特定のテストファイルを実行
pytest tests/test_workbook_parser.py
# 詳細な出力でテストを実行
pytest -v
```
### コード品質チェック
```bash
# リンターを実行
ruff check .
# 型チェックを実行
mypy .
# フォーマットを実行
ruff format .
```
## ライセンス
このプロジェクトはMITライセンスの下で公開されています。
## 貢献
プルリクエストやイシューの報告を歓迎します。貢献する前に、以下の手順を確認してください:
1. このリポジトリをフォーク
2. 機能ブランチを作成 (`git checkout -b feature/amazing-feature`)
3. 変更をコミット (`git commit -m 'Add some amazing feature'`)
4. ブランチにプッシュ (`git push origin feature/amazing-feature`)
5. プルリクエストを作成
## サポート
問題や質問がある場合は、GitHubのイシューを作成してください。
## ライセンス
MIT License
Raw data
{
"_id": null,
"home_page": null,
"name": "tabtest",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "tableau, twb, twbx, parser, testing",
"author": null,
"author_email": "Kamegrueon <niwaniwaniwaniwatori.gairuze@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/a4/cb/54f8735a0065c153b25a1115167b515814b1560091ce68681050d3ef0ccd/tabtest-0.1.0.tar.gz",
"platform": null,
"description": "# tabtest\n\nTableau\u306e`.twb`/`.twbx`\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u3057\u3001pytest\u3067\u30c6\u30b9\u30c8\u3092\u5b9f\u884c\u3067\u304d\u308bPython\u30e9\u30a4\u30d6\u30e9\u30ea\u3067\u3059\u3002\n\n## \u6982\u8981\n\ntabtest\u306f\u3001Tableau\u30ef\u30fc\u30af\u30d6\u30c3\u30af\u306e\u69cb\u9020\u3092\u89e3\u6790\u3057\u3001pytest\u3092\u4f7f\u7528\u3057\u3066\u30ef\u30fc\u30af\u30d6\u30c3\u30af\u306e\u5185\u5bb9\u3092\u30c6\u30b9\u30c8\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b\u30c4\u30fc\u30eb\u3067\u3059\u3002\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u30c6\u30b9\u30c8\u304c\u53ef\u80fd\u3067\u3059\uff1a\n\n- \u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u5b58\u5728\u78ba\u8a8d\n- \u8a08\u7b97\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u5b58\u5728\u78ba\u8a8d\n- \u30ef\u30fc\u30af\u30b7\u30fc\u30c8\u306e\u8a2d\u5b9a\u78ba\u8a8d\n- \u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u306e\u30ec\u30a4\u30a2\u30a6\u30c8\u78ba\u8a8d\n- \u30d1\u30e9\u30e1\u30fc\u30bf\u306e\u8a2d\u5b9a\u78ba\u8a8d\n- \u30d5\u30a3\u30eb\u30bf\u30fc\u306e\u8a2d\u5b9a\u78ba\u8a8d\n\n## \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\n\n```bash\npip install tabtest\n```\n\n## \u57fa\u672c\u7684\u306a\u4f7f\u7528\u65b9\u6cd5\n\n### 1. \u30ef\u30fc\u30af\u30d6\u30c3\u30af\u306e\u89e3\u6790\n\n```python\nfrom tabtest import WorkbookParser\n\n# \u30ef\u30fc\u30af\u30d6\u30c3\u30af\u3092\u89e3\u6790\nparser = WorkbookParser(\"./path/to/your/workbook.twb\")\nworkbook = parser.workbook\n\n# \u57fa\u672c\u60c5\u5831\u306e\u78ba\u8a8d\nprint(f\"\u30ef\u30fc\u30af\u30d6\u30c3\u30af\u540d: {workbook.name}\")\nprint(f\"\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u6570: {len(workbook.datasources)}\")\nprint(f\"\u30ef\u30fc\u30af\u30b7\u30fc\u30c8\u6570: {len(workbook.sheets)}\")\nprint(f\"\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u6570: {len(workbook.dashboards)}\")\n```\n\n### 2. pytest\u3067\u306e\u30c6\u30b9\u30c8\n\n```python\nimport pytest\nfrom tabtest.suite.helpers import (\n assert_workbook_has_datasource,\n assert_workbook_has_sheet,\n assert_workbook_has_dashboard,\n assert_datasource_has_calculated_field,\n)\n\ndef test_workbook_structure(workbook_fixture):\n \"\"\"\u30ef\u30fc\u30af\u30d6\u30c3\u30af\u306e\u57fa\u672c\u69cb\u9020\u3092\u30c6\u30b9\u30c8\"\"\"\n workbook = workbook_fixture\n \n # \u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u78ba\u8a8d\n data_ds = assert_workbook_has_datasource(\n workbook, \"mock_datasource\"\n )\n \n # \u8a08\u7b97\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u78ba\u8a8d\n assert_datasource_has_calculated_field(\n data_ds, \"mock_calculated_field\"\n )\n \n # \u30ef\u30fc\u30af\u30b7\u30fc\u30c8\u306e\u78ba\u8a8d\n sheet = assert_workbook_has_sheet(workbook, \"mock_sheet\")\n assert sheet.mark_type == \"bar\"\n \n # \u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u306e\u78ba\u8a8d\n dashboard = assert_workbook_has_dashboard(workbook, \"mock_dashboard\")\n assert dashboard.size_width == 1200\n assert dashboard.size_height == 800\n```\n\n### 3. \u5229\u7528\u53ef\u80fd\u306a\u30d5\u30a3\u30af\u30b9\u30c1\u30e3\n\n#### \u6c4e\u7528\u30d5\u30a3\u30af\u30b9\u30c1\u30e3\uff08tabtest\u30e9\u30a4\u30d6\u30e9\u30ea\u63d0\u4f9b\uff09\n\npytest\u3067\u4ee5\u4e0b\u306e\u6c4e\u7528\u30d5\u30a3\u30af\u30b9\u30c1\u30e3\u304c\u5229\u7528\u3067\u304d\u307e\u3059\uff1a\n\n- `workbook_parser`: \u30ab\u30b9\u30bf\u30e0\u30ef\u30fc\u30af\u30d6\u30c3\u30af\u30d1\u30fc\u30b5\u30fc\n- `workbook`: \u89e3\u6790\u6e08\u307f\u30ef\u30fc\u30af\u30d6\u30c3\u30af\n- `workbook_fixture`: \u30e2\u30c3\u30af\u30ef\u30fc\u30af\u30d6\u30c3\u30af\uff08tests/assets/mock_workbook.twb\uff09\n\n\u4f7f\u7528\u65b9\u6cd5\uff1a\n```python\n@pytest.mark.parametrize(\"workbook_parser\", [\"./path/to/your/workbook.twb\"], indirect=True)\ndef test_workbook(workbook_parser):\n assert workbook_parser.workbook.name == \"Expected Name\"\n\n@pytest.mark.parametrize(\"workbook_parser\", [\"./path/to/your/workbook.twb\"], indirect=True)\ndef test_workbook(workbook):\n assert workbook.name == \"Expected Name\"\n assert len(workbook.datasources) > 0\n\ndef test_with_mock_workbook(workbook_fixture):\n \"\"\"\u30e2\u30c3\u30af\u30ef\u30fc\u30af\u30d6\u30c3\u30af\u3092\u4f7f\u7528\u3057\u305f\u30c6\u30b9\u30c8\"\"\"\n workbook = workbook_fixture\n assert workbook.name == \"Mock Workbook\"\n assert len(workbook.datasources) > 0\n```\n\n#### \u30e6\u30fc\u30b6\u30fc\u56fa\u6709\u30d5\u30a3\u30af\u30b9\u30c1\u30e3\n\n\u30e6\u30fc\u30b6\u30fc\u306f`tests/fixtures.py`\u3067\u56fa\u6709\u306e\u30d5\u30a3\u30af\u30b9\u30c1\u30e3\u3092\u5b9a\u7fa9\u3067\u304d\u307e\u3059\uff1a\n\n```python\n# tests/fixtures.py\nimport pytest\nfrom tabtest import WorkbookParser\n\n@pytest.fixture\ndef my_workbook():\n \"\"\"\u30e6\u30fc\u30b6\u30fc\u56fa\u6709\u306e\u30ef\u30fc\u30af\u30d6\u30c3\u30af\u30d5\u30a3\u30af\u30b9\u30c1\u30e3\"\"\"\n parser = WorkbookParser(\"./path/to/your/workbook.twb\")\n return parser.workbook\n```\n\n### 4. \u30d8\u30eb\u30d1\u30fc\u95a2\u6570\n\n\u4ee5\u4e0b\u306e\u30d8\u30eb\u30d1\u30fc\u95a2\u6570\u304c\u5229\u7528\u3067\u304d\u307e\u3059\uff1a\n\n```python\nfrom tabtest.suite.helpers import (\n # \u30ef\u30fc\u30af\u30d6\u30c3\u30af\u30ec\u30d9\u30eb\n assert_workbook_has_datasource,\n assert_workbook_has_sheet,\n assert_workbook_has_dashboard,\n \n # \u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30ec\u30d9\u30eb\n assert_datasource_has_field,\n assert_datasource_has_calculated_field,\n \n # \u30ef\u30fc\u30af\u30b7\u30fc\u30c8\u30ec\u30d9\u30eb\n assert_sheet_has_field_in_rows,\n assert_sheet_has_field_in_columns,\n assert_sheet_has_filter,\n \n # \u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u30ec\u30d9\u30eb\n assert_dashboard_contains_sheet,\n)\n```\n\n## \u30c7\u30fc\u30bf\u30e2\u30c7\u30eb\n\n### WorkbookModel\n\n\u30ef\u30fc\u30af\u30d6\u30c3\u30af\u5168\u4f53\u306e\u60c5\u5831\u3092\u8868\u3059\u30e2\u30c7\u30eb\u3067\u3059\u3002\n\n```python\nclass WorkbookModel:\n name: str # \u30ef\u30fc\u30af\u30d6\u30c3\u30af\u540d\n datasources: List[DatasourceModel] # \u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u4e00\u89a7\n sheets: Dict[str, WorksheetModel] # \u30ef\u30fc\u30af\u30b7\u30fc\u30c8\u4e00\u89a7\n dashboards: List[DashboardModel] # \u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u4e00\u89a7\n parameters: List[ParameterModel] # \u30d1\u30e9\u30e1\u30fc\u30bf\u4e00\u89a7\n```\n\n### DatasourceModel\n\n\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u60c5\u5831\u3092\u8868\u3059\u30e2\u30c7\u30eb\u3067\u3059\u3002\n\n```python\nclass DatasourceModel:\n name: Optional[str] # \u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d\n caption: Optional[str] # \u30ad\u30e3\u30d7\u30b7\u30e7\u30f3\n fields: List[DatasourceFieldModel] # \u30d5\u30a3\u30fc\u30eb\u30c9\u4e00\u89a7\n```\n\n### WorksheetModel\n\n\u30ef\u30fc\u30af\u30b7\u30fc\u30c8\u306e\u60c5\u5831\u3092\u8868\u3059\u30e2\u30c7\u30eb\u3067\u3059\u3002\n\n```python\nclass WorksheetModel:\n name: str # \u30ef\u30fc\u30af\u30b7\u30fc\u30c8\u540d\n datasource_name: str # \u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d\n filters: List[FilterModel] # \u30d5\u30a3\u30eb\u30bf\u30fc\u4e00\u89a7\n rows: List[str] # \u884c\u306b\u914d\u7f6e\u3055\u308c\u305f\u30d5\u30a3\u30fc\u30eb\u30c9\n columns: List[str] # \u5217\u306b\u914d\u7f6e\u3055\u308c\u305f\u30d5\u30a3\u30fc\u30eb\u30c9\n mark_type: Optional[str] # \u30de\u30fc\u30af\u30bf\u30a4\u30d7\n```\n\n### DashboardModel\n\n\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u306e\u60c5\u5831\u3092\u8868\u3059\u30e2\u30c7\u30eb\u3067\u3059\u3002\n\n```python\nclass DashboardModel:\n name: Optional[str] # \u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u540d\n dashboard_sheets: List[DashboardSheetModel] # \u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u5185\u306e\u30ef\u30fc\u30af\u30b7\u30fc\u30c8\n size_width: int # \u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u5e45\n size_height: int # \u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u9ad8\u3055\n```\n\n## \u4f7f\u7528\u4f8b\n\n\u8a73\u7d30\u306a\u4f7f\u7528\u4f8b\u306f`examples/`\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\uff1a\n\n- `examples/basic_usage.py`: \u57fa\u672c\u7684\u306a\u4f7f\u7528\u65b9\u6cd5\n- `examples/pytest_example.py`: pytest\u3067\u306e\u30c6\u30b9\u30c8\u4f8b\n\n## \u958b\u767a\n\n### \u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\n\n```bash\n# \u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u30af\u30ed\u30fc\u30f3\ngit clone https://github.com/your-username/tabtest.git\ncd tabtest\n\n# \u4eee\u60f3\u74b0\u5883\u3092\u4f5c\u6210\npython -m venv .venv\nsource .venv/bin/activate # Linux/Mac\n# \u307e\u305f\u306f\n.venv\\Scripts\\activate # Windows\n\n# \u4f9d\u5b58\u95a2\u4fc2\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\npip install -e .\npip install -e \".[dev]\"\n```\n\n### \u30c6\u30b9\u30c8\u306e\u5b9f\u884c\n\n```bash\n# \u3059\u3079\u3066\u306e\u30c6\u30b9\u30c8\u3092\u5b9f\u884c\npytest\n\n# \u7279\u5b9a\u306e\u30c6\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u5b9f\u884c\npytest tests/test_workbook_parser.py\n\n# \u8a73\u7d30\u306a\u51fa\u529b\u3067\u30c6\u30b9\u30c8\u3092\u5b9f\u884c\npytest -v\n```\n\n### \u30b3\u30fc\u30c9\u54c1\u8cea\u30c1\u30a7\u30c3\u30af\n\n```bash\n# \u30ea\u30f3\u30bf\u30fc\u3092\u5b9f\u884c\nruff check .\n\n# \u578b\u30c1\u30a7\u30c3\u30af\u3092\u5b9f\u884c\nmypy .\n\n# \u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3092\u5b9f\u884c\nruff format .\n```\n\n## \u30e9\u30a4\u30bb\u30f3\u30b9\n\n\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306fMIT\u30e9\u30a4\u30bb\u30f3\u30b9\u306e\u4e0b\u3067\u516c\u958b\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n\n## \u8ca2\u732e\n\n\u30d7\u30eb\u30ea\u30af\u30a8\u30b9\u30c8\u3084\u30a4\u30b7\u30e5\u30fc\u306e\u5831\u544a\u3092\u6b53\u8fce\u3057\u307e\u3059\u3002\u8ca2\u732e\u3059\u308b\u524d\u306b\u3001\u4ee5\u4e0b\u306e\u624b\u9806\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\uff1a\n\n1. \u3053\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u30d5\u30a9\u30fc\u30af\n2. \u6a5f\u80fd\u30d6\u30e9\u30f3\u30c1\u3092\u4f5c\u6210 (`git checkout -b feature/amazing-feature`)\n3. \u5909\u66f4\u3092\u30b3\u30df\u30c3\u30c8 (`git commit -m 'Add some amazing feature'`)\n4. \u30d6\u30e9\u30f3\u30c1\u306b\u30d7\u30c3\u30b7\u30e5 (`git push origin feature/amazing-feature`)\n5. \u30d7\u30eb\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u4f5c\u6210\n\n## \u30b5\u30dd\u30fc\u30c8\n\n\u554f\u984c\u3084\u8cea\u554f\u304c\u3042\u308b\u5834\u5408\u306f\u3001GitHub\u306e\u30a4\u30b7\u30e5\u30fc\u3092\u4f5c\u6210\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\n## \u30e9\u30a4\u30bb\u30f3\u30b9\n\nMIT License\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Tableau \u306e .twb .twbx \u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u30fb\u30c6\u30b9\u30c8\u3059\u308b\u30c4\u30fc\u30eb",
"version": "0.1.0",
"project_urls": {
"Documentation": "https://github.com/Kamegrueon/tabtest#readme",
"Homepage": "https://github.com/Kamegrueon/tabtest",
"Issues": "https://github.com/Kamegrueon/tabtest/issues",
"Repository": "https://github.com/Kamegrueon/tabtest"
},
"split_keywords": [
"tableau",
" twb",
" twbx",
" parser",
" testing"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "bfbc4429b1552492bc81b8cba0773505548c3ad004daa41430fbb4396d3da654",
"md5": "5bcd9d4410e670fc57a24831ec9bd4be",
"sha256": "e19821464af59e2576ffca4c800d0578754b0489549eb769b3161c525cf7a6aa"
},
"downloads": -1,
"filename": "tabtest-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "5bcd9d4410e670fc57a24831ec9bd4be",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 29562,
"upload_time": "2025-08-31T14:53:10",
"upload_time_iso_8601": "2025-08-31T14:53:10.705978Z",
"url": "https://files.pythonhosted.org/packages/bf/bc/4429b1552492bc81b8cba0773505548c3ad004daa41430fbb4396d3da654/tabtest-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "a4cb54f8735a0065c153b25a1115167b515814b1560091ce68681050d3ef0ccd",
"md5": "a055672a792ee0c1ca3b30f6210d76de",
"sha256": "5e2029b132d347210c7cbf0a966facf20d6298deb882814e66fea5c71a964368"
},
"downloads": -1,
"filename": "tabtest-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "a055672a792ee0c1ca3b30f6210d76de",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 32774,
"upload_time": "2025-08-31T14:53:12",
"upload_time_iso_8601": "2025-08-31T14:53:12.272356Z",
"url": "https://files.pythonhosted.org/packages/a4/cb/54f8735a0065c153b25a1115167b515814b1560091ce68681050d3ef0ccd/tabtest-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-31 14:53:12",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Kamegrueon",
"github_project": "tabtest#readme",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "lxml",
"specs": [
[
">=",
"5.4.0"
]
]
},
{
"name": "pydantic",
"specs": [
[
">=",
"2.11.7"
]
]
},
{
"name": "pytest",
"specs": [
[
">=",
"8.4.1"
]
]
}
],
"lcname": "tabtest"
}