Islamic Inheritance Distribution Calculator (Faraid)
Project description
Farady - Islamic Inheritance Distribution Calculator
A Python library and CLI tool for calculating Islamic inheritance distribution according to Faraid (Islamic inheritance law).
Table of Contents
Branching Model
| Branch | Purpose |
|---|---|
main |
Development work |
release-pypi |
Test PyPI publishing |
prod-pypi |
PyPI production (tag v* to release) |
release-sa |
SunnaAssets releases |
PyPI Release Flow
- Work on
main - Merge to
release-pypito test publishing - Merge to
prod-pypiwhen ready - Tag on
prod-pypi:git tag v1.0.0 && git push origin v1.0.0
SA Release Flow
Push to release-sa when SA might want new features.
Installation
pip install farady
Development mode:
pip install -e .
Quick Start
from farady import calculate_from_dict
# Simple case: 1 son, 1 daughter, wife
case = calculate_from_dict({"ibn": 1, "bint": 1, "zawja": True})
# Access results
print(case.distribution) # {'zawja': 0.125, 'ibn': 0.5833, 'bint': 0.2917}
print(case.ending) # 'taseeb'
print(case.total) # 1.0
print(case.status) # 'Complete'
print(case.asib) # 'ibn-bint'
API Reference
Core Classes
Case
Data class representing a family configuration for inheritance calculation.
from farady import Case
case = Case.from_dict({
"ibn": 2, # 2 sons
"bint": 1, # 1 daughter
"zawja": True, # Wife present
"umm": 1, # Mother present
"ab": 1, # Father present
})
Properties:
| Property | Type | Description |
|---|---|---|
distribution |
dict |
Heir -> share mapping |
ending |
str |
Distribution method used |
asib |
str |
Residual heir (if any) |
total |
float |
Total of all shares |
status |
str |
Calculation status |
raas |
int |
Total shares (denominator) |
total_shares |
int |
Sum of all allocated shares |
Class Methods:
| Method | Description |
|---|---|
Case.from_dict(data) |
Create from dictionary (handles string conversion) |
case.to_dict() |
Convert to dictionary (excludes zero/false values) |
Main Functions
calculate(case)
Main function to calculate inheritance distribution.
from farady import Case, calculate
case = Case.from_dict({"ibn": 2, "bint": 1, "zawja": True})
result = calculate(case)
Parameters:
| Parameter | Type | Description |
|---|---|---|
case |
Case |
Case object with family member counts |
Returns: Case with populated results
calculate_from_dict(data)
Calculate inheritance from a dictionary. Useful for loading from JSON, CSV, or form data.
from farady import calculate_from_dict
# From a dictionary
data = {"ibn": "2", "bint": "1", "zawja": "True"} # Strings are converted
case = calculate_from_dict(data)
# From form data with mixed types
data = {"ibn": 1, "bint": 2, "zawja": True, "umm": "1"}
case = calculate_from_dict(data)
String Conversion Rules:
| Field Type | String Value | Converted To |
|---|---|---|
Spouse (zawj, zawja) |
"True", "1", "yes" |
True |
Spouse (zawj, zawja) |
"False", "0", "no", "" |
False |
| Count fields | "1", "2", etc. |
int |
| Count fields | "True", "yes" |
1 |
| Count fields | "False", "no", "" |
(excluded) |
Returns: Case with populated results
calculate_inheritance(**kwargs)
Calculate inheritance directly from keyword arguments.
from farady import calculate_inheritance
case = calculate_inheritance(ibn=2, bint=1, zawja=True)
Parameters:
| Parameter | Type | Description |
|---|---|---|
ibn |
int |
Number of sons |
bint |
int |
Number of daughters |
iibn |
int |
Number of grandsons |
bibn |
int |
Number of granddaughters |
iiibn |
int |
Number of great-grandsons |
biibn |
int |
Number of great-granddaughters |
umm |
int |
Mother (0 or 1) |
jadda |
int |
Grandmother(s) (0 or 1) |
ab |
int |
Father (0 or 1) |
jadd |
int |
Grandfather (0 or 1) |
lium |
int |
Maternal half-sibling count |
shaqiqa |
int |
Full sister count |
shaqiq |
int |
Full brother count |
uliab |
int |
Paternal half-sister count |
aliab |
int |
Paternal half-brother count |
ibnamm_sh |
int |
Full nephew count |
ibnamm_liab |
int |
Half nephew count |
amm |
int |
Uncle count |
zawj |
bool |
Husband present |
zawja |
bool |
Wife present |
Returns: Case with populated results
CSV/Batch Processing
load_csv_cases(csv_path)
Load inheritance cases from a CSV file.
from farady import load_csv_cases
cases = load_csv_cases("tests/test_cases.csv")
# Returns: List[Case]
for case in cases:
print(case.to_dict())
CSV Format:
ibn,bint,zawja,expected_total,notes
1,1,True,1.0,Son + daughter + wife
2,0,True,1.0,Two sons + wife
0,2,True,1.125,Two daughters + wife (awl)
- Column headers must match valid field names (Arabic:
ibn,bint,zawja, etc.) - Extra columns (like
notes,expected_total) are ignored - String values are converted using same rules as
from_dict()
Returns: List[Case]
process_csv_results(csv_path)
Load CSV and calculate results for each row. Returns full context for testing/debugging.
from farady import process_csv_results
results = process_csv_results("tests/test_cases.csv")
for item in results:
row = item["row_data"] # Original CSV row (dict)
case = item["case"] # Case object (before calculation)
result = item["result"] # Case object (after calculation)
print(f"Case: {row.get('notes')}")
print(f" Distribution: {result.distribution}")
print(f" Ending: {result.ending}")
print(f" Total: {result.total}")
print(f" Status: {result.status}")
Returns: List[Dict] with keys:
| Key | Type | Description |
|---|---|---|
row_data |
dict |
Original CSV row data |
case |
Case |
Parsed case object |
result |
Case |
Calculated result case |
Case Fields
Family Member Fields (Arabic Names)
| Field | Type | Description | Fixed Share |
|---|---|---|---|
ibn |
int |
Sons | Variable (asib) |
bint |
int |
Daughters | 1/2 (single), 2/3 (multiple), or variable |
iibn |
int |
Grandsons (son's sons) | Variable |
bibn |
int |
Granddaughters (son's daughters) | Variable |
iiibn |
int |
Great-grandsons | Variable |
biibn |
int |
Great-granddaughters | Variable |
umm |
int |
Mother | 1/6 (with children) or 1/3 |
jadda |
int |
Grandmother(s) | 1/6 (if mother absent) |
ab |
int |
Father | 1/6 (with children) or variable |
jadd |
int |
Grandfather | Variable |
lium |
int |
Maternal half-siblings | 1/3 (collectively) |
shaqiqa |
int |
Full sisters | Variable |
shaqiq |
int |
Full brothers | Variable (asib) |
uliab |
int |
Paternal half-sisters | Variable |
aliab |
int |
Paternal half-brothers | Variable |
ibnamm_sh |
int |
Full nephews | Variable |
ibnamm_liab |
int |
Half nephews | Variable |
amm |
int |
Uncles | Variable |
zawj |
bool |
Husband | 1/2 (no kids) or 1/4 |
zawja |
bool |
Wife | 1/4 (no kids) or 1/8 |
Pretty Names Reference
from farady import PRETTY_NAMES
PRETTY_NAMES = {
'ibn': 'Son(s)',
'bint': 'Daughter(s)',
'iibn': 'Grandson(s)',
'bibn': 'Granddaughter(s)',
'iiibn': 'Great-grandson(s)',
'biibn': 'Great-granddaughter(s)',
'umm': 'Mother',
'jadda': 'Grandmother(s)',
'ab': 'Father',
'jadd': 'Grandfather (nearest in relation)',
'lium': 'Maternal Half-sibling(s)',
'shaqiqa': 'Full Sister(s)',
'shaqiq': 'Full Brother(s)',
'uliab': 'Paternal Half-sister(s)',
'aliab': 'Paternal Half-brother(s)',
'ibnamm_sh': 'Full Nephew',
'ibnamm_liab': 'Half Nephew',
'amm': 'Uncle',
'zawj': 'Husband',
'zawja': 'Wife',
}
CLI Usage
# Basic usage
farady --ibn 2 --bint 1 --zawja
# Verbose output (shows ending, asib, status)
farady --ibn 2 --bint 1 --zawja --verbose
# All flags
farady --ibn 1 --bint 2 --iibn 0 --bibn 0 --umm 1 --ab 1 --zawja
Examples
Example 1: Basic Case
from farady import calculate_from_dict
case = calculate_from_dict({"ibn": 1, "bint": 1, "zawja": True})
print(f"Distribution: {case.distribution}")
# Distribution: {'zawja': 0.125, 'ibn': 0.5833, 'bint': 0.2917}
print(f"Ending: {case.ending}")
# Ending: taseeb
print(f"Raas: {case.raas}")
# Raas: 24
# For document generation:
# "Divide into 24 shares: 3 to Wife, 14 to Son(s), 7 to Daughter(s)"
Example 2: Awl Case (Shares Exceed 1)
case = calculate_from_dict({"bint": 2, "zawja": True})
print(f"Total: {case.total}") # 1.125 (exceeds 1)
print(f"Ending: {case.ending}") # awl
Example 3: Radd Case (Leftover After Fixed Shares)
case = calculate_from_dict({"bint": 2})
print(f"Distribution: {case.distribution}") # {'bint': 1.0}
print(f"Total: {case.total}") # 1.0
print(f"Ending: {case.ending}") # radd
# Two daughters: 2/3 fixed, remaining 1/3 returned via radd
Example 4: CSV Batch Processing
from farady import process_csv_results
results = process_csv_results("test_cases.csv")
for item in results:
row = item["row_data"]
result = item["result"]
# Debug output
print(f"Case: {row.get('case_name', 'unnamed')}")
print(f" Ending method: {result.ending}")
print(f" Total: {result.total}")
print(f" Status: {result.status}")
if result.asib:
print(f" Residual heir: {result.asib}")
print()
Example 5: Form Data Integration
from farady import calculate_from_dict
# From web form (strings)
form_data = {
"ibn": "2",
"bint": "1",
"zawja": "yes", # Will be converted to True
"umm": "1",
}
case = calculate_from_dict(form_data)
# Use raas for will document
if case.raas:
shares_text = []
for heir, share in case.distribution.items():
num_shares = round(share * case.raas)
shares_text.append(f"{num_shares} shares to {heir}")
print(f"Divide into {case.raas} shares:")
print("\n".join(shares_text))
License
GNU Affero General Public License v3.0 (AGPLv3)
This software is licensed under AGPLv3. See the LICENSE file for the full text.
Key Points of AGPLv3
- Commercial Use Allowed: You may use this software for commercial purposes
- Source Required: If you modify this software and run it as a network service, you must make your modifications available to users
- Share Alike: If you distribute modified versions, they must be licensed under AGPLv3
- Attribution: You must give appropriate credit to Adam Ahmed
Enterprise & Commercial Use
AGPLv3 is a strong copyleft license. If you:
- Use it as-is: No restrictions
- Host it as a service: You must provide source code to users
- Modify it: Must distribute your modifications under AGPLv3
For traditional commercial licensing (to avoid copyleft obligations), please contact the author.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file farady-1.0.0.tar.gz.
File metadata
- Download URL: farady-1.0.0.tar.gz
- Upload date:
- Size: 39.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be267a3e3ea549746ee0715fa6f0e9b6bfb55ecf0c1bebd7c2ddcfd72a9bf12f
|
|
| MD5 |
8819dbb979c96ad103450004077da13d
|
|
| BLAKE2b-256 |
7abb52f59e01065e0f28a1c1c30432b92cca303dda2f966a1a34fd251d05d94e
|
Provenance
The following attestation bundles were made for farady-1.0.0.tar.gz:
Publisher:
release-pypi.yml on adamquant/farady
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
farady-1.0.0.tar.gz -
Subject digest:
be267a3e3ea549746ee0715fa6f0e9b6bfb55ecf0c1bebd7c2ddcfd72a9bf12f - Sigstore transparency entry: 1165091845
- Sigstore integration time:
-
Permalink:
adamquant/farady@8be47468d955984515a1e82b70e3a5e8d90fafd0 -
Branch / Tag:
refs/heads/prod-pypi - Owner: https://github.com/adamquant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@8be47468d955984515a1e82b70e3a5e8d90fafd0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file farady-1.0.0-py3-none-any.whl.
File metadata
- Download URL: farady-1.0.0-py3-none-any.whl
- Upload date:
- Size: 43.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0ea5c6541103ab1d2d930981678dba4b23d9edb0471308476b5021b00e134be
|
|
| MD5 |
b49b12909dbf45456bee50507db1371f
|
|
| BLAKE2b-256 |
d60bf11a31eec9808dea59bcdb06b24d9539e2ffede5ec18b1d12b1ff3aa2480
|
Provenance
The following attestation bundles were made for farady-1.0.0-py3-none-any.whl:
Publisher:
release-pypi.yml on adamquant/farady
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
farady-1.0.0-py3-none-any.whl -
Subject digest:
b0ea5c6541103ab1d2d930981678dba4b23d9edb0471308476b5021b00e134be - Sigstore transparency entry: 1165091945
- Sigstore integration time:
-
Permalink:
adamquant/farady@8be47468d955984515a1e82b70e3a5e8d90fafd0 -
Branch / Tag:
refs/heads/prod-pypi - Owner: https://github.com/adamquant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@8be47468d955984515a1e82b70e3a5e8d90fafd0 -
Trigger Event:
push
-
Statement type: