fakerforge 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,6 @@
1
+ """Domain providers registered through Faker's BaseProvider."""
2
+
3
+ from fakerforge.providers.base import ForgeProvider
4
+ from fakerforge.providers.finance import FinanceProvider
5
+
6
+ __all__ = ["FinanceProvider", "ForgeProvider"]
@@ -0,0 +1,16 @@
1
+ """Base class for FakerForge domain providers."""
2
+
3
+ from faker.providers import BaseProvider
4
+
5
+
6
+ class ForgeProvider(BaseProvider):
7
+ """Base class for custom domain providers.
8
+
9
+ Subclass this and add public methods. Register the subclass with
10
+ :meth:`fakerforge.FakerForge.add_provider`. Registered methods are then
11
+ available on the ``FakerForge`` instance through Faker's provider lookup.
12
+
13
+ This class does not copy or replace Faker providers. It is a subclass of
14
+ :class:`faker.providers.BaseProvider`, so provider helpers such as
15
+ ``random_element`` and ``numerify`` remain available.
16
+ """
@@ -0,0 +1,112 @@
1
+ """Finance provider built on Faker's BaseProvider."""
2
+
3
+ import math
4
+ from decimal import ROUND_HALF_UP, Decimal, InvalidOperation
5
+
6
+ from faker.providers import BaseProvider
7
+
8
+ _CENTS = Decimal("0.01")
9
+
10
+
11
+ class FinanceProvider(BaseProvider):
12
+ """Synthetic finance fields.
13
+
14
+ Methods draw from ``self.generator.random`` through Faker's provider
15
+ helpers, so they follow the ``FakerForge`` instance seed.
16
+ """
17
+
18
+ def credit_score(self, min_score: int = 300, max_score: int = 850) -> int:
19
+ """Return an integer credit score in the inclusive range.
20
+
21
+ Args:
22
+ min_score: Lowest accepted score.
23
+ max_score: Highest accepted score.
24
+
25
+ Returns:
26
+ A score between ``min_score`` and ``max_score``.
27
+
28
+ Raises:
29
+ TypeError: A bound is not an integer.
30
+ ValueError: ``min_score`` is greater than ``max_score``.
31
+ """
32
+ low = _require_int(min_score, "min_score")
33
+ high = _require_int(max_score, "max_score")
34
+ _require_ordered(low, high, "min_score", "max_score")
35
+ return self.random_int(min=low, max=high)
36
+
37
+ def transaction_amount(
38
+ self,
39
+ min_amount: int | float | Decimal = 1,
40
+ max_amount: int | float | Decimal = 10000,
41
+ ) -> Decimal:
42
+ """Return a transaction amount in dollars and cents.
43
+
44
+ Args:
45
+ min_amount: Lowest accepted amount.
46
+ max_amount: Highest accepted amount.
47
+
48
+ Returns:
49
+ A ``Decimal`` quantized to cents, inclusive of both bounds.
50
+
51
+ Raises:
52
+ TypeError: An amount is not an int, float, or Decimal.
53
+ ValueError: An amount is not finite, or ``min_amount`` is greater
54
+ than ``max_amount``.
55
+ """
56
+ low = _require_money(min_amount, "min_amount")
57
+ high = _require_money(max_amount, "max_amount")
58
+ _require_ordered(low, high, "min_amount", "max_amount")
59
+ cents = self.random_int(min=_to_cents(low), max=_to_cents(high))
60
+ return (Decimal(cents) / Decimal(100)).quantize(_CENTS)
61
+
62
+ def account_number(self, length: int = 12) -> str:
63
+ """Return a numeric account number of the requested length.
64
+
65
+ Args:
66
+ length: Number of digits. Leading zeros are allowed.
67
+
68
+ Returns:
69
+ A string of ``length`` digits.
70
+
71
+ Raises:
72
+ TypeError: ``length`` is not an integer.
73
+ ValueError: ``length`` is less than 1.
74
+ """
75
+ size = _require_int(length, "length")
76
+ if size < 1:
77
+ raise ValueError("length must be a positive integer")
78
+ return self.numerify("#" * size)
79
+
80
+
81
+ def _require_int(value: object, label: str) -> int:
82
+ if isinstance(value, bool) or not isinstance(value, int):
83
+ raise TypeError(f"{label} must be an int")
84
+ return value
85
+
86
+
87
+ def _require_money(value: object, label: str) -> Decimal:
88
+ if isinstance(value, bool) or not isinstance(value, (int, float, Decimal)):
89
+ raise TypeError(f"{label} must be an int, float, or Decimal")
90
+ if isinstance(value, float) and not math.isfinite(value):
91
+ raise ValueError(f"{label} must be finite")
92
+ try:
93
+ amount = value if isinstance(value, Decimal) else Decimal(str(value))
94
+ except InvalidOperation as exc:
95
+ raise ValueError(f"{label} must be a finite number") from exc
96
+ if not amount.is_finite():
97
+ raise ValueError(f"{label} must be finite")
98
+ return amount.quantize(_CENTS, rounding=ROUND_HALF_UP)
99
+
100
+
101
+ def _require_ordered(
102
+ low: int | Decimal,
103
+ high: int | Decimal,
104
+ low_label: str,
105
+ high_label: str,
106
+ ) -> None:
107
+ if low > high:
108
+ raise ValueError(f"{low_label} must be less than or equal to {high_label}")
109
+
110
+
111
+ def _to_cents(amount: Decimal) -> int:
112
+ return int((amount * 100).to_integral_value(rounding=ROUND_HALF_UP))
fakerforge/py.typed ADDED
File without changes
@@ -0,0 +1,25 @@
1
+ """Schema types for synthetic records."""
2
+
3
+ from fakerforge.schema.dataset import (
4
+ Column,
5
+ DatabaseSchema,
6
+ DatasetSchema,
7
+ GenerationError,
8
+ SchemaError,
9
+ TableSchema,
10
+ )
11
+ from fakerforge.schema.result import DatabaseResult, DatasetResult
12
+ from fakerforge.schema.schema import Field, Schema
13
+
14
+ __all__ = [
15
+ "Column",
16
+ "DatabaseResult",
17
+ "DatabaseSchema",
18
+ "DatasetResult",
19
+ "DatasetSchema",
20
+ "Field",
21
+ "GenerationError",
22
+ "Schema",
23
+ "SchemaError",
24
+ "TableSchema",
25
+ ]