fiqhboard 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fiqhboard-0.0.1/.github/workflows/publish.yml +99 -0
- fiqhboard-0.0.1/.gitignore +31 -0
- fiqhboard-0.0.1/CHANGELOG.md +13 -0
- fiqhboard-0.0.1/LICENSE +21 -0
- fiqhboard-0.0.1/PKG-INFO +123 -0
- fiqhboard-0.0.1/README.md +97 -0
- fiqhboard-0.0.1/pyproject.toml +50 -0
- fiqhboard-0.0.1/src/fiqhboard/__init__.py +4 -0
- fiqhboard-0.0.1/src/fiqhboard/__main__.py +3 -0
- fiqhboard-0.0.1/src/fiqhboard/cli.py +67 -0
- fiqhboard-0.0.1/src/fiqhboard/gui/__init__.py +1 -0
- fiqhboard-0.0.1/src/fiqhboard/gui/main_window.py +98 -0
- fiqhboard-0.0.1/src/fiqhboard/main.py +59 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# One release, everywhere at once. A tag v* → check → build → PyPI → GitHub Release.
|
|
2
|
+
# Nothing is published unless the check and the build succeed, so GitHub and PyPI never differ.
|
|
3
|
+
# The file name (publish.yml) and the "pypi" environment are what PyPI's trusted publishing is tied to: keep them.
|
|
4
|
+
# (The desktop applications — portable exe, AppImage, macOS — join this pipeline in P1.)
|
|
5
|
+
name: Release
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags:
|
|
10
|
+
- "v*"
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
check:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v7
|
|
20
|
+
- uses: actions/setup-python@v7
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
- name: One version everywhere, and its CHANGELOG section
|
|
24
|
+
run: |
|
|
25
|
+
python - "${GITHUB_REF_NAME}" <<'EOF'
|
|
26
|
+
import json, re, sys, pathlib
|
|
27
|
+
tag = sys.argv[1]
|
|
28
|
+
want = tag[1:] if tag.startswith("v") else tag
|
|
29
|
+
found = {
|
|
30
|
+
"src/fiqhboard/__init__.py": re.search(r'__version__ = "([^"]+)"', pathlib.Path("src/fiqhboard/__init__.py").read_text()).group(1),
|
|
31
|
+
"js/package.json": json.loads(pathlib.Path("js/package.json").read_text())["version"],
|
|
32
|
+
"js/index.js": re.search(r'export const version = "([^"]+)"', pathlib.Path("js/index.js").read_text()).group(1),
|
|
33
|
+
}
|
|
34
|
+
bad = {k: v for k, v in found.items() if v != want}
|
|
35
|
+
if bad:
|
|
36
|
+
sys.exit(f"tag {tag} but: {bad}")
|
|
37
|
+
text = pathlib.Path("CHANGELOG.md").read_text(encoding="utf-8")
|
|
38
|
+
m = re.search(r"^## \[" + re.escape(want) + r"\][^\n]*\n(.*?)(?=^## \[|\Z)", text, re.S | re.M)
|
|
39
|
+
if not m:
|
|
40
|
+
sys.exit(f"CHANGELOG.md has no section ## [{want}]")
|
|
41
|
+
pathlib.Path("release-notes.md").write_text(m.group(1).strip() + "\n", encoding="utf-8")
|
|
42
|
+
print(f"one version everywhere: {want}; CHANGELOG.md has the {want} section")
|
|
43
|
+
EOF
|
|
44
|
+
- uses: actions/upload-artifact@v7
|
|
45
|
+
with:
|
|
46
|
+
name: release-notes
|
|
47
|
+
path: release-notes.md
|
|
48
|
+
|
|
49
|
+
python:
|
|
50
|
+
needs: check
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v7
|
|
54
|
+
- uses: actions/setup-python@v7
|
|
55
|
+
with:
|
|
56
|
+
python-version: "3.12"
|
|
57
|
+
- run: python -m pip install --upgrade build twine
|
|
58
|
+
- run: python -m build
|
|
59
|
+
- run: python -m twine check dist/*
|
|
60
|
+
- uses: actions/upload-artifact@v7
|
|
61
|
+
with:
|
|
62
|
+
name: dist
|
|
63
|
+
path: dist/
|
|
64
|
+
|
|
65
|
+
publish:
|
|
66
|
+
needs: python
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
environment: pypi
|
|
69
|
+
permissions:
|
|
70
|
+
id-token: write
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/download-artifact@v8
|
|
73
|
+
with:
|
|
74
|
+
name: dist
|
|
75
|
+
path: dist/
|
|
76
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
77
|
+
|
|
78
|
+
github-release:
|
|
79
|
+
needs: publish
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
permissions:
|
|
82
|
+
contents: write
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/download-artifact@v8
|
|
85
|
+
with:
|
|
86
|
+
path: artifacts/
|
|
87
|
+
- name: Gather the files and their checksums
|
|
88
|
+
run: |
|
|
89
|
+
mkdir release
|
|
90
|
+
find artifacts -type f \( -name '*.whl' -o -name '*.tar.gz' \) -exec cp {} release/ \;
|
|
91
|
+
cd release && sha256sum * > SHA256SUMS.txt && cat SHA256SUMS.txt
|
|
92
|
+
- name: Create the GitHub Release
|
|
93
|
+
env:
|
|
94
|
+
GH_TOKEN: ${{ github.token }}
|
|
95
|
+
run: |
|
|
96
|
+
gh release create "${GITHUB_REF_NAME}" release/* \
|
|
97
|
+
--repo "${GITHUB_REPOSITORY}" \
|
|
98
|
+
--title "fiqhboard ${GITHUB_REF_NAME#v}" \
|
|
99
|
+
--notes-file artifacts/release-notes/release-notes.md
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Local-only project notes — never pushed
|
|
2
|
+
FiqhBoard_Handoff.md
|
|
3
|
+
FIQHBOARD_TODO.md
|
|
4
|
+
|
|
5
|
+
# Python
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*.egg-info/
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
|
|
14
|
+
# Data built locally (shipped separately, never committed raw)
|
|
15
|
+
*.sqlite
|
|
16
|
+
*.sqlite3
|
|
17
|
+
*.db
|
|
18
|
+
|
|
19
|
+
# Node / npm
|
|
20
|
+
node_modules/
|
|
21
|
+
*.tgz
|
|
22
|
+
package-lock.json
|
|
23
|
+
|
|
24
|
+
# Editors / OS
|
|
25
|
+
.vscode/
|
|
26
|
+
.idea/
|
|
27
|
+
.DS_Store
|
|
28
|
+
Thumbs.db
|
|
29
|
+
|
|
30
|
+
# desktop builds
|
|
31
|
+
dist-app/
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Every release of fiqhboard, newest first. The same version number is published on PyPI, npm and GitHub.
|
|
4
|
+
|
|
5
|
+
## [0.0.1] — 2026-10-19
|
|
6
|
+
|
|
7
|
+
The first release: it reserves the name.
|
|
8
|
+
|
|
9
|
+
- The `fiqhboard` package with the commands `fiqhboard` and `fqb` (no arguments: the window; with arguments: the command line) and `fiqhboard-gui` (the window, without a console on Windows).
|
|
10
|
+
- A welcome window that says what fiqhboard is and what comes next.
|
|
11
|
+
- `fqb -V` / `--version` / `version`, and `fqb -h`.
|
|
12
|
+
- The README: why fiqhboard, how a comparison is built (one question per row, each school in its own terms, nothing without a source), and the roadmap.
|
|
13
|
+
- The npm package `fiqhboard` 0.0.1, a placeholder that reserves the name.
|
fiqhboard-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bayram Kotan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
fiqhboard-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: fiqhboard
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Comparative fiqh of the four Sunni schools: side-by-side matrices, every ruling with its source and evidence, a glossary and decision diagrams
|
|
5
|
+
Project-URL: Homepage, https://github.com/bayramkotan/fiqhboard
|
|
6
|
+
Project-URL: Repository, https://github.com/bayramkotan/fiqhboard
|
|
7
|
+
Project-URL: Issues, https://github.com/bayramkotan/fiqhboard/issues
|
|
8
|
+
Author: Bayram Kotan
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: fiqh,hanafi,hanbali,islamic law,islamic studies,madhhab,maliki,shafii
|
|
12
|
+
Classifier: Development Status :: 1 - Planning
|
|
13
|
+
Classifier: Environment :: X11 Applications :: Qt
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Natural Language :: Arabic
|
|
17
|
+
Classifier: Natural Language :: English
|
|
18
|
+
Classifier: Natural Language :: Turkish
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Topic :: Education
|
|
22
|
+
Classifier: Topic :: Religion
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: pyside6>=6.6
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
<h1 align="center">⚖️ fiqhboard <sub>الفقه المقارن</sub></h1>
|
|
28
|
+
|
|
29
|
+
<p align="center">
|
|
30
|
+
<strong>Comparative fiqh of the four Sunni schools</strong><br>
|
|
31
|
+
<sub>Hanafi, Maliki, Shafi'i and Hanbali side by side — every ruling in its school's own words, with its source and its evidence</sub>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
<p align="center">
|
|
35
|
+
<a href="https://pypi.org/project/fiqhboard/">
|
|
36
|
+
<img src="https://img.shields.io/badge/PyPI-v0.0.1-1D4777?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI">
|
|
37
|
+
</a>
|
|
38
|
+
<img src="https://img.shields.io/badge/Python-3.10%2B-A47E24?style=for-the-badge&logo=python&logoColor=white" alt="Python">
|
|
39
|
+
<img src="https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20macOS-5B6878?style=for-the-badge" alt="Platform">
|
|
40
|
+
<a href="https://www.npmjs.com/package/fiqhboard">
|
|
41
|
+
<img src="https://img.shields.io/badge/npm-v0.0.1-14304F?style=for-the-badge&logo=npm" alt="npm">
|
|
42
|
+
</a>
|
|
43
|
+
<img src="https://img.shields.io/badge/License-MIT-D6B25E?style=for-the-badge" alt="License">
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
<p align="center">
|
|
47
|
+
<a href="#-why-fiqhboard">Why</a> •
|
|
48
|
+
<a href="#-how-a-comparison-is-built">How</a> •
|
|
49
|
+
<a href="#-install">Install</a> •
|
|
50
|
+
<a href="#%EF%B8%8F-command-line">Command line</a> •
|
|
51
|
+
<a href="#-roadmap">Roadmap</a> •
|
|
52
|
+
<a href="#-license">License</a>
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
> **Planning (0.0.1).** This first release reserves the name and opens a welcome window. The comparison matrices, the evidence drawer, the glossary and the diagrams follow, release by release.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 💡 Why fiqhboard
|
|
60
|
+
|
|
61
|
+
Comparing the four schools usually means reading four books, each in its own vocabulary. fiqhboard puts them in one table — without flattening them into one vocabulary:
|
|
62
|
+
|
|
63
|
+
- **One question per row.** A row does not ask "is it fard?"; it asks something every school can answer, such as *"Is wudu valid without an intention?"* The colours and the agree/disagree filter come from that answer.
|
|
64
|
+
- **Each school in its own terms.** The Hanafi *wajib* is not the Shafi'i *wajib*; a Hanbali *shart* is not a *fard*. Every cell shows the school's own term, in Arabic and in transliteration, and no term is mapped onto another school's.
|
|
65
|
+
- **The relied-upon view, and the others.** A cell shows the school's relied-upon position (*mu'tamad*, *mufta bihi*, *mashhur*, *asahh*) and says so; other views within the school stay one click away.
|
|
66
|
+
- **Nothing without a source.** Every position names the book, volume and page it comes from; every piece of evidence — verse, hadith, principle — is cited.
|
|
67
|
+
- **Agreement of the four is not ijma'.** When the four schools agree, fiqhboard says *the four schools agree*. Ijma' is shown only where a source claims it, attributed to that source.
|
|
68
|
+
- **For learning, not fatwa.** The decision diagrams teach how each school reasons; for your own situation, ask a qualified scholar.
|
|
69
|
+
|
|
70
|
+
## 🧩 How a comparison is built
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
topic wudu › its obligatory acts
|
|
74
|
+
question Is wudu valid without an intention?
|
|
75
|
+
answers valid · invalid
|
|
76
|
+
┌──────────────┬──────────────┬──────────────┬──────────────┐
|
|
77
|
+
│ Hanafi │ Maliki │ Shafi'i │ Hanbali │
|
|
78
|
+
├──────────────┼──────────────┼──────────────┼──────────────┤
|
|
79
|
+
answer │ valid │ invalid │ invalid │ invalid │
|
|
80
|
+
own term │ sunna سنة │ fard فرض │ fard فرض │ shart شرط │
|
|
81
|
+
source │ book, vol, p │ book, vol, p │ book, vol, p │ book, vol, p │
|
|
82
|
+
└──────────────┴──────────────┴──────────────┴──────────────┘
|
|
83
|
+
evidence hadith bukhari:1 · Qur'an 5:6
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The data lives as JSON in a separate repository, is checked by a validator (no source, no publication), and is read into SQLite so the application works offline. Hadith evidence uses the same references as [isnady](https://github.com/bayramkotan/isnady) and its data.
|
|
87
|
+
|
|
88
|
+
## 📦 Install
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pip install fiqhboard
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
On Linux distributions that protect the system Python (Arch, CachyOS, Debian, Ubuntu), use `pipx install fiqhboard`, a virtual environment, or add `--break-system-packages`.
|
|
95
|
+
|
|
96
|
+
Portable applications (Windows exe, Linux AppImage, macOS) join the GitHub Releases in a coming version.
|
|
97
|
+
|
|
98
|
+
## ⌨️ Command line
|
|
99
|
+
|
|
100
|
+
| Short | Full | What it does |
|
|
101
|
+
|---|---|---|
|
|
102
|
+
| `fqb` | `fiqhboard` | Opens the window |
|
|
103
|
+
| `fqb -V` | `fiqhboard --version` | Prints the version (`-v`, `-V`, `--version`, `version`) |
|
|
104
|
+
| `fqb -h` | `fiqhboard -h` | Help |
|
|
105
|
+
| | `fiqhboard-gui` | The window, without a console on Windows |
|
|
106
|
+
|
|
107
|
+
The command line never loads Qt, so it runs over SSH and in scripts. Every feature of the window will also be on the command line.
|
|
108
|
+
|
|
109
|
+
## 🗺️ Roadmap
|
|
110
|
+
|
|
111
|
+
- [x] **0.0.1** — the name, the package, a welcome window
|
|
112
|
+
- [ ] The application skeleton: settings, themes, interface languages (English, Turkish, Arabic first), portable applications
|
|
113
|
+
- [ ] The data format and its validator; the data repository
|
|
114
|
+
- [ ] The first topic end to end: the obligatory acts of wudu, every cell sourced
|
|
115
|
+
- [ ] The comparison matrix and the evidence drawer
|
|
116
|
+
- [ ] The glossary, with a definition under every term
|
|
117
|
+
- [ ] Decision diagrams, one per school (the prostration of forgetfulness first)
|
|
118
|
+
- [ ] Export to PDF, PNG and Markdown
|
|
119
|
+
- [ ] Purity (*taharah*) and prayer (*salat*) in full
|
|
120
|
+
|
|
121
|
+
## 📄 License
|
|
122
|
+
|
|
123
|
+
The application is released under the [MIT License](LICENSE). Quoted works keep their own licences; modern works under copyright are cited, never reproduced.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<h1 align="center">⚖️ fiqhboard <sub>الفقه المقارن</sub></h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>Comparative fiqh of the four Sunni schools</strong><br>
|
|
5
|
+
<sub>Hanafi, Maliki, Shafi'i and Hanbali side by side — every ruling in its school's own words, with its source and its evidence</sub>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://pypi.org/project/fiqhboard/">
|
|
10
|
+
<img src="https://img.shields.io/badge/PyPI-v0.0.1-1D4777?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI">
|
|
11
|
+
</a>
|
|
12
|
+
<img src="https://img.shields.io/badge/Python-3.10%2B-A47E24?style=for-the-badge&logo=python&logoColor=white" alt="Python">
|
|
13
|
+
<img src="https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20macOS-5B6878?style=for-the-badge" alt="Platform">
|
|
14
|
+
<a href="https://www.npmjs.com/package/fiqhboard">
|
|
15
|
+
<img src="https://img.shields.io/badge/npm-v0.0.1-14304F?style=for-the-badge&logo=npm" alt="npm">
|
|
16
|
+
</a>
|
|
17
|
+
<img src="https://img.shields.io/badge/License-MIT-D6B25E?style=for-the-badge" alt="License">
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
<a href="#-why-fiqhboard">Why</a> •
|
|
22
|
+
<a href="#-how-a-comparison-is-built">How</a> •
|
|
23
|
+
<a href="#-install">Install</a> •
|
|
24
|
+
<a href="#%EF%B8%8F-command-line">Command line</a> •
|
|
25
|
+
<a href="#-roadmap">Roadmap</a> •
|
|
26
|
+
<a href="#-license">License</a>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
> **Planning (0.0.1).** This first release reserves the name and opens a welcome window. The comparison matrices, the evidence drawer, the glossary and the diagrams follow, release by release.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 💡 Why fiqhboard
|
|
34
|
+
|
|
35
|
+
Comparing the four schools usually means reading four books, each in its own vocabulary. fiqhboard puts them in one table — without flattening them into one vocabulary:
|
|
36
|
+
|
|
37
|
+
- **One question per row.** A row does not ask "is it fard?"; it asks something every school can answer, such as *"Is wudu valid without an intention?"* The colours and the agree/disagree filter come from that answer.
|
|
38
|
+
- **Each school in its own terms.** The Hanafi *wajib* is not the Shafi'i *wajib*; a Hanbali *shart* is not a *fard*. Every cell shows the school's own term, in Arabic and in transliteration, and no term is mapped onto another school's.
|
|
39
|
+
- **The relied-upon view, and the others.** A cell shows the school's relied-upon position (*mu'tamad*, *mufta bihi*, *mashhur*, *asahh*) and says so; other views within the school stay one click away.
|
|
40
|
+
- **Nothing without a source.** Every position names the book, volume and page it comes from; every piece of evidence — verse, hadith, principle — is cited.
|
|
41
|
+
- **Agreement of the four is not ijma'.** When the four schools agree, fiqhboard says *the four schools agree*. Ijma' is shown only where a source claims it, attributed to that source.
|
|
42
|
+
- **For learning, not fatwa.** The decision diagrams teach how each school reasons; for your own situation, ask a qualified scholar.
|
|
43
|
+
|
|
44
|
+
## 🧩 How a comparison is built
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
topic wudu › its obligatory acts
|
|
48
|
+
question Is wudu valid without an intention?
|
|
49
|
+
answers valid · invalid
|
|
50
|
+
┌──────────────┬──────────────┬──────────────┬──────────────┐
|
|
51
|
+
│ Hanafi │ Maliki │ Shafi'i │ Hanbali │
|
|
52
|
+
├──────────────┼──────────────┼──────────────┼──────────────┤
|
|
53
|
+
answer │ valid │ invalid │ invalid │ invalid │
|
|
54
|
+
own term │ sunna سنة │ fard فرض │ fard فرض │ shart شرط │
|
|
55
|
+
source │ book, vol, p │ book, vol, p │ book, vol, p │ book, vol, p │
|
|
56
|
+
└──────────────┴──────────────┴──────────────┴──────────────┘
|
|
57
|
+
evidence hadith bukhari:1 · Qur'an 5:6
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The data lives as JSON in a separate repository, is checked by a validator (no source, no publication), and is read into SQLite so the application works offline. Hadith evidence uses the same references as [isnady](https://github.com/bayramkotan/isnady) and its data.
|
|
61
|
+
|
|
62
|
+
## 📦 Install
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install fiqhboard
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
On Linux distributions that protect the system Python (Arch, CachyOS, Debian, Ubuntu), use `pipx install fiqhboard`, a virtual environment, or add `--break-system-packages`.
|
|
69
|
+
|
|
70
|
+
Portable applications (Windows exe, Linux AppImage, macOS) join the GitHub Releases in a coming version.
|
|
71
|
+
|
|
72
|
+
## ⌨️ Command line
|
|
73
|
+
|
|
74
|
+
| Short | Full | What it does |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| `fqb` | `fiqhboard` | Opens the window |
|
|
77
|
+
| `fqb -V` | `fiqhboard --version` | Prints the version (`-v`, `-V`, `--version`, `version`) |
|
|
78
|
+
| `fqb -h` | `fiqhboard -h` | Help |
|
|
79
|
+
| | `fiqhboard-gui` | The window, without a console on Windows |
|
|
80
|
+
|
|
81
|
+
The command line never loads Qt, so it runs over SSH and in scripts. Every feature of the window will also be on the command line.
|
|
82
|
+
|
|
83
|
+
## 🗺️ Roadmap
|
|
84
|
+
|
|
85
|
+
- [x] **0.0.1** — the name, the package, a welcome window
|
|
86
|
+
- [ ] The application skeleton: settings, themes, interface languages (English, Turkish, Arabic first), portable applications
|
|
87
|
+
- [ ] The data format and its validator; the data repository
|
|
88
|
+
- [ ] The first topic end to end: the obligatory acts of wudu, every cell sourced
|
|
89
|
+
- [ ] The comparison matrix and the evidence drawer
|
|
90
|
+
- [ ] The glossary, with a definition under every term
|
|
91
|
+
- [ ] Decision diagrams, one per school (the prostration of forgetfulness first)
|
|
92
|
+
- [ ] Export to PDF, PNG and Markdown
|
|
93
|
+
- [ ] Purity (*taharah*) and prayer (*salat*) in full
|
|
94
|
+
|
|
95
|
+
## 📄 License
|
|
96
|
+
|
|
97
|
+
The application is released under the [MIT License](LICENSE). Quoted works keep their own licences; modern works under copyright are cited, never reproduced.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "fiqhboard"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Comparative fiqh of the four Sunni schools: side-by-side matrices, every ruling with its source and evidence, a glossary and decision diagrams"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
authors = [{ name = "Bayram Kotan" }]
|
|
13
|
+
requires-python = ">=3.10"
|
|
14
|
+
dependencies = ["PySide6>=6.6"]
|
|
15
|
+
|
|
16
|
+
keywords = ["fiqh", "islamic law", "madhhab", "hanafi", "maliki", "shafii", "hanbali", "islamic studies"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 1 - Planning",
|
|
19
|
+
"Environment :: X11 Applications :: Qt",
|
|
20
|
+
"Intended Audience :: Education",
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
"Natural Language :: English",
|
|
23
|
+
"Natural Language :: Arabic",
|
|
24
|
+
"Natural Language :: Turkish",
|
|
25
|
+
"Operating System :: OS Independent",
|
|
26
|
+
"Programming Language :: Python :: 3",
|
|
27
|
+
"Topic :: Education",
|
|
28
|
+
"Topic :: Religion",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/bayramkotan/fiqhboard"
|
|
33
|
+
Repository = "https://github.com/bayramkotan/fiqhboard"
|
|
34
|
+
Issues = "https://github.com/bayramkotan/fiqhboard/issues"
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
fiqhboard = "fiqhboard.main:main"
|
|
38
|
+
fqb = "fiqhboard.main:main"
|
|
39
|
+
|
|
40
|
+
[project.gui-scripts]
|
|
41
|
+
fiqhboard-gui = "fiqhboard.main:gui_main"
|
|
42
|
+
|
|
43
|
+
[tool.hatch.version]
|
|
44
|
+
path = "src/fiqhboard/__init__.py"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["src/fiqhboard"]
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.sdist]
|
|
50
|
+
exclude = ["FiqhBoard_Handoff.md", "FIQHBOARD_TODO.md", "js/"]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""The command line. It never imports Qt.
|
|
2
|
+
|
|
3
|
+
Every feature of the window will also be here (fiqhboard's rule: the window
|
|
4
|
+
and the command line give the same answer, both from fiqhboard.core).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
from fiqhboard import APP_NAME, __version__
|
|
12
|
+
|
|
13
|
+
VERSION_WORDS = {"-v", "-V", "--version", "--v", "--V", "version"}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _prog() -> str:
|
|
17
|
+
name = os.path.basename(sys.argv[0] or "") if sys.argv else ""
|
|
18
|
+
name = os.path.splitext(name)[0]
|
|
19
|
+
return name if name in ("fiqhboard", "fqb") else "fiqhboard"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
23
|
+
prog = _prog()
|
|
24
|
+
parser = argparse.ArgumentParser(
|
|
25
|
+
prog=prog,
|
|
26
|
+
description="fiqhboard: comparative fiqh of the four Sunni schools (Hanafi, Maliki, Shafi'i, Hanbali).",
|
|
27
|
+
epilog=(
|
|
28
|
+
"Without arguments the window opens.\n"
|
|
29
|
+
"\n"
|
|
30
|
+
"commands:\n"
|
|
31
|
+
f" {prog} version the version (also -v, -V, --version)\n"
|
|
32
|
+
"\n"
|
|
33
|
+
"This is the first release: it reserves the name. The comparison matrices,\n"
|
|
34
|
+
"the evidence drawer, the glossary and the diagrams follow."
|
|
35
|
+
),
|
|
36
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
37
|
+
)
|
|
38
|
+
parser.add_argument("command", nargs="?", choices=["version"], help=argparse.SUPPRESS)
|
|
39
|
+
return parser
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _utf8_output() -> None:
|
|
43
|
+
"""Windows writes redirected output in an old code page; Arabic would fail."""
|
|
44
|
+
for stream in (sys.stdout, sys.stderr):
|
|
45
|
+
try:
|
|
46
|
+
stream.reconfigure(encoding="utf-8", errors="replace")
|
|
47
|
+
except (AttributeError, ValueError):
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def main(argv=None) -> int:
|
|
52
|
+
_utf8_output()
|
|
53
|
+
argv = list(sys.argv[1:] if argv is None else argv)
|
|
54
|
+
if argv and argv[0] in VERSION_WORDS:
|
|
55
|
+
print(f"{APP_NAME} {__version__}")
|
|
56
|
+
return 0
|
|
57
|
+
parser = build_parser()
|
|
58
|
+
args = parser.parse_args(argv)
|
|
59
|
+
if args.command == "version":
|
|
60
|
+
print(f"{APP_NAME} {__version__}")
|
|
61
|
+
return 0
|
|
62
|
+
parser.print_help()
|
|
63
|
+
return 0
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == "__main__":
|
|
67
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""The PySide6 window. Only this package imports Qt."""
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""The main window.
|
|
2
|
+
|
|
3
|
+
The first release shows a single welcome page: only working pages are added to
|
|
4
|
+
the window (the matrix, the glossary and the diagrams arrive with their data).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from PySide6.QtCore import Qt
|
|
8
|
+
from PySide6.QtWidgets import (
|
|
9
|
+
QFrame,
|
|
10
|
+
QHBoxLayout,
|
|
11
|
+
QLabel,
|
|
12
|
+
QMainWindow,
|
|
13
|
+
QVBoxLayout,
|
|
14
|
+
QWidget,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from fiqhboard import APP_NAME, __version__
|
|
18
|
+
|
|
19
|
+
LAPIS = "#1D4777"
|
|
20
|
+
GOLD = "#A47E24"
|
|
21
|
+
|
|
22
|
+
SCHOOLS = [
|
|
23
|
+
("Hanafi", "الحنفي"),
|
|
24
|
+
("Maliki", "المالكي"),
|
|
25
|
+
("Shafi'i", "الشافعي"),
|
|
26
|
+
("Hanbali", "الحنبلي"),
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
NEXT = [
|
|
30
|
+
"Side-by-side matrices: one question per row, the four schools in the columns",
|
|
31
|
+
"Every position in each school's own terms, with the book, volume and page it comes from",
|
|
32
|
+
"The evidence drawer: the verse, the hadith (from isnady-data) and the principle behind each ruling",
|
|
33
|
+
"A glossary of fiqh terms in English, Turkish and Arabic",
|
|
34
|
+
"Decision diagrams, one per school, for learning — not as a fatwa",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class MainWindow(QMainWindow):
|
|
39
|
+
def __init__(self) -> None:
|
|
40
|
+
super().__init__()
|
|
41
|
+
self.setWindowTitle(f"{APP_NAME} {__version__}")
|
|
42
|
+
self.resize(960, 640)
|
|
43
|
+
|
|
44
|
+
page = QWidget()
|
|
45
|
+
outer = QVBoxLayout(page)
|
|
46
|
+
outer.setContentsMargins(48, 40, 48, 40)
|
|
47
|
+
outer.setSpacing(18)
|
|
48
|
+
|
|
49
|
+
title_row = QHBoxLayout()
|
|
50
|
+
title = QLabel(APP_NAME)
|
|
51
|
+
title.setStyleSheet(f"font-size: 34px; font-weight: 600; color: {LAPIS};")
|
|
52
|
+
arabic = QLabel("الفقه المقارن")
|
|
53
|
+
arabic.setStyleSheet(f"font-size: 28px; color: {GOLD};")
|
|
54
|
+
arabic.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignAbsolute | Qt.AlignmentFlag.AlignVCenter)
|
|
55
|
+
title_row.addWidget(title)
|
|
56
|
+
title_row.addStretch(1)
|
|
57
|
+
title_row.addWidget(arabic)
|
|
58
|
+
outer.addLayout(title_row)
|
|
59
|
+
|
|
60
|
+
line = QFrame()
|
|
61
|
+
line.setFixedHeight(2)
|
|
62
|
+
line.setStyleSheet(f"background: {GOLD};")
|
|
63
|
+
outer.addWidget(line)
|
|
64
|
+
|
|
65
|
+
lead = QLabel("Comparative fiqh of the four Sunni schools — each ruling in its school's own words, "
|
|
66
|
+
"with its source and its evidence.")
|
|
67
|
+
lead.setWordWrap(True)
|
|
68
|
+
lead.setStyleSheet("font-size: 17px;")
|
|
69
|
+
outer.addWidget(lead)
|
|
70
|
+
|
|
71
|
+
chips = QHBoxLayout()
|
|
72
|
+
chips.setSpacing(10)
|
|
73
|
+
for name, ar in SCHOOLS:
|
|
74
|
+
chip = QLabel(f"{name} · {ar}")
|
|
75
|
+
chip.setStyleSheet(
|
|
76
|
+
f"border: 1px solid {LAPIS}; border-radius: 12px; padding: 4px 12px; font-size: 14px;")
|
|
77
|
+
chips.addWidget(chip)
|
|
78
|
+
chips.addStretch(1)
|
|
79
|
+
outer.addLayout(chips)
|
|
80
|
+
|
|
81
|
+
heading = QLabel("Coming next")
|
|
82
|
+
heading.setStyleSheet(f"font-size: 15px; font-weight: 600; color: {GOLD}; margin-top: 12px;")
|
|
83
|
+
outer.addWidget(heading)
|
|
84
|
+
for item in NEXT:
|
|
85
|
+
row = QLabel(f"• {item}")
|
|
86
|
+
row.setWordWrap(True)
|
|
87
|
+
row.setStyleSheet("font-size: 14px;")
|
|
88
|
+
outer.addWidget(row)
|
|
89
|
+
|
|
90
|
+
outer.addStretch(1)
|
|
91
|
+
footer = QLabel(
|
|
92
|
+
f'Version {__version__} · first release, reserving the name · '
|
|
93
|
+
f'<a href="https://github.com/bayramkotan/fiqhboard">github.com/bayramkotan/fiqhboard</a>')
|
|
94
|
+
footer.setOpenExternalLinks(True)
|
|
95
|
+
footer.setStyleSheet("font-size: 12px;")
|
|
96
|
+
outer.addWidget(footer)
|
|
97
|
+
|
|
98
|
+
self.setCentralWidget(page)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Entry points.
|
|
2
|
+
|
|
3
|
+
The same program answers to several names:
|
|
4
|
+
fiqhboard, fqb no arguments: open the window; with arguments: the command line
|
|
5
|
+
fiqhboard-gui always the window, without a console on Windows
|
|
6
|
+
|
|
7
|
+
The command line never imports Qt, so it works on a server, over SSH and in
|
|
8
|
+
scripts, and starts quickly.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
from fiqhboard import APP_NAME, __version__
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def gui_main() -> int:
|
|
18
|
+
try:
|
|
19
|
+
from PySide6.QtCore import QLoggingCategory
|
|
20
|
+
from PySide6.QtWidgets import QApplication
|
|
21
|
+
except ImportError:
|
|
22
|
+
print("The fiqhboard window needs PySide6: pip install PySide6\n"
|
|
23
|
+
"The command line works without it; see: fqb -h", file=sys.stderr)
|
|
24
|
+
return 1
|
|
25
|
+
|
|
26
|
+
from fiqhboard.gui.main_window import MainWindow
|
|
27
|
+
|
|
28
|
+
if not os.environ.get("QT_LOGGING_RULES"):
|
|
29
|
+
# Qt reports, for every installed font, that it cannot shape a script none of them covers:
|
|
30
|
+
# hundreds of harmless lines. Only that category is silenced; a user's own QT_LOGGING_RULES wins.
|
|
31
|
+
QLoggingCategory.setFilterRules("qt.text.font.db=false")
|
|
32
|
+
if sys.platform == "win32":
|
|
33
|
+
# without its own id, Windows groups the window under python(w).exe and shows Python's icon
|
|
34
|
+
try:
|
|
35
|
+
import ctypes
|
|
36
|
+
|
|
37
|
+
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("bayramkotan.fiqhboard")
|
|
38
|
+
except (AttributeError, OSError):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
app = QApplication(sys.argv[:1])
|
|
42
|
+
app.setApplicationName(APP_NAME)
|
|
43
|
+
app.setApplicationVersion(__version__)
|
|
44
|
+
app.setDesktopFileName("fiqhboard")
|
|
45
|
+
window = MainWindow()
|
|
46
|
+
window.show()
|
|
47
|
+
return app.exec()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def main() -> int:
|
|
51
|
+
if len(sys.argv) > 1:
|
|
52
|
+
from fiqhboard.cli import main as cli_main
|
|
53
|
+
|
|
54
|
+
return cli_main(sys.argv[1:])
|
|
55
|
+
return gui_main()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if __name__ == "__main__":
|
|
59
|
+
raise SystemExit(main())
|