ft3 0.0.1__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.
Files changed (111) hide show
  1. ft3/__init__.py +56 -0
  2. ft3/cli/__init__.py +31 -0
  3. ft3/cli/cfg.py +11 -0
  4. ft3/cli/lib.py +7 -0
  5. ft3/cli/obj.py +34 -0
  6. ft3/cli/utl.py +25 -0
  7. ft3/core/__init__.py +37 -0
  8. ft3/core/cfg.py +67 -0
  9. ft3/core/codecs/__init__.py +15 -0
  10. ft3/core/codecs/cfg.py +46 -0
  11. ft3/core/codecs/enm.py +65 -0
  12. ft3/core/codecs/lib.py +20 -0
  13. ft3/core/codecs/typ.py +14 -0
  14. ft3/core/codecs/utl.py +352 -0
  15. ft3/core/enm.py +23 -0
  16. ft3/core/exc.py +39 -0
  17. ft3/core/lib.py +57 -0
  18. ft3/core/strings/__init__.py +19 -0
  19. ft3/core/strings/cfg.py +55 -0
  20. ft3/core/strings/enm.py +20 -0
  21. ft3/core/strings/exc.py +29 -0
  22. ft3/core/strings/lib.py +7 -0
  23. ft3/core/strings/obj.py +448 -0
  24. ft3/core/strings/typ.py +7 -0
  25. ft3/core/strings/utl.py +410 -0
  26. ft3/core/typ/__init__.py +52 -0
  27. ft3/core/typ/cfg.py +11 -0
  28. ft3/core/typ/lib.py +16 -0
  29. ft3/core/typ/obj.py +560 -0
  30. ft3/core/typ/typ.py +123 -0
  31. ft3/core/typ/utl/__init__.py +9 -0
  32. ft3/core/typ/utl/check.py +550 -0
  33. ft3/core/typ/utl/hint.py +189 -0
  34. ft3/docs/__init__.py +33 -0
  35. ft3/docs/cfg.py +25 -0
  36. ft3/docs/enm.py +45 -0
  37. ft3/docs/lib.py +16 -0
  38. ft3/docs/obj.py +173 -0
  39. ft3/docs/static/__init__.py +12 -0
  40. ft3/docs/static/conf.tpl +106 -0
  41. ft3/docs/static/favicon.ico +0 -0
  42. ft3/docs/static/logo.png +0 -0
  43. ft3/docs/utl.py +437 -0
  44. ft3/loggers/__init__.py +55 -0
  45. ft3/loggers/cfg.py +26 -0
  46. ft3/loggers/exc.py +37 -0
  47. ft3/loggers/lib.py +18 -0
  48. ft3/loggers/obj.py +291 -0
  49. ft3/loggers/typ.py +59 -0
  50. ft3/loggers/utl.py +108 -0
  51. ft3/objects/__init__.py +48 -0
  52. ft3/objects/cfg.py +79 -0
  53. ft3/objects/enm.py +26 -0
  54. ft3/objects/exc.py +299 -0
  55. ft3/objects/fields/__init__.py +10 -0
  56. ft3/objects/fields/obj.py +781 -0
  57. ft3/objects/lib.py +20 -0
  58. ft3/objects/metas/__init__.py +12 -0
  59. ft3/objects/metas/obj.py +309 -0
  60. ft3/objects/metas/utl.py +181 -0
  61. ft3/objects/objs/__init__.py +10 -0
  62. ft3/objects/objs/obj.py +922 -0
  63. ft3/objects/queries/__init__.py +11 -0
  64. ft3/objects/queries/obj.py +213 -0
  65. ft3/objects/typ.py +54 -0
  66. ft3/objects/utl.py +130 -0
  67. ft3-0.0.1.dist-info/LICENSE +165 -0
  68. ft3-0.0.1.dist-info/METADATA +443 -0
  69. ft3-0.0.1.dist-info/RECORD +111 -0
  70. ft3-0.0.1.dist-info/WHEEL +5 -0
  71. ft3-0.0.1.dist-info/entry_points.txt +2 -0
  72. ft3-0.0.1.dist-info/top_level.txt +2 -0
  73. tests/__init__.py +7 -0
  74. tests/ci/__init__.py +7 -0
  75. tests/ci/cfg.py +9 -0
  76. tests/ci/commit_msg_test.py +105 -0
  77. tests/core/__init__.py +7 -0
  78. tests/core/cfg.py +11 -0
  79. tests/core/codecs/__init__.py +7 -0
  80. tests/core/codecs/cfg.py +11 -0
  81. tests/core/codecs/utl_test.py +463 -0
  82. tests/core/strings/__init__.py +7 -0
  83. tests/core/strings/cfg.py +15 -0
  84. tests/core/strings/exc_test.py +29 -0
  85. tests/core/strings/utl_test.py +190 -0
  86. tests/core/typings/__init__.py +7 -0
  87. tests/core/typings/cfg.py +13 -0
  88. tests/core/typings/utl_test.py +148 -0
  89. tests/loggers/__init__.py +7 -0
  90. tests/loggers/backup.py +397 -0
  91. tests/loggers/cfg.py +11 -0
  92. tests/loggers/exc_test.py +19 -0
  93. tests/loggers/obj_test.py +510 -0
  94. tests/mocking/__init__.py +103 -0
  95. tests/mocking/examples.py +13 -0
  96. tests/objects/__init__.py +7 -0
  97. tests/objects/cfg.py +11 -0
  98. tests/objects/exc_test.py +78 -0
  99. tests/objects/fields/__init__.py +7 -0
  100. tests/objects/fields/cfg.py +11 -0
  101. tests/objects/fields/fields_test.py +299 -0
  102. tests/objects/metas/__init__.py +7 -0
  103. tests/objects/metas/cfg.py +11 -0
  104. tests/objects/metas/metas_test.py +333 -0
  105. tests/objects/objs/__init__.py +7 -0
  106. tests/objects/objs/cfg.py +11 -0
  107. tests/objects/objs/objs_test.py +382 -0
  108. tests/objects/queries/__init__.py +7 -0
  109. tests/objects/queries/cfg.py +11 -0
  110. tests/objects/queries/queries_test.py +175 -0
  111. tests/readme_test.py +134 -0
ft3/__init__.py ADDED
@@ -0,0 +1,56 @@
1
+ """
2
+ Overview
3
+ ========
4
+
5
+ **Author:** dan@1howardcapital.com
6
+
7
+ **Summary:** Zero-dependency python framework for object oriented development.
8
+ Implement _once_, document _once_, in _one_ place.
9
+
10
+ ---
11
+
12
+ With ft3, you will quickly learn established best practice... \
13
+ or face the consequences of runtime errors that will break your code \
14
+ if you deviate from it.
15
+
16
+ Experienced python engineers will find a framework \
17
+ that expects and rewards intuitive magic method implementations, \
18
+ consistent type annotations, and robust docstrings.
19
+
20
+ Implement _pythonically_ with ft3 and you will only ever need to: \
21
+ implement _once_, document _once_, in _one_ place.
22
+
23
+ ---
24
+
25
+ Getting Started
26
+ ---------------
27
+
28
+ ### Installation
29
+
30
+ Install from command line, with pip:
31
+
32
+ `$ pip install ft3`
33
+
34
+ """
35
+
36
+ __all__ = (
37
+ 'cli',
38
+ 'core',
39
+ 'docs',
40
+ 'log',
41
+ 'loggers',
42
+ 'objects',
43
+ 'Field',
44
+ 'Object'
45
+ )
46
+
47
+ __version__ = '0.0.1'
48
+
49
+ from . import cli
50
+ from . import core
51
+ from . import docs
52
+ from . import loggers
53
+ from . import objects
54
+
55
+ from . loggers import log
56
+ from . objects import Field, Object
ft3/cli/__init__.py ADDED
@@ -0,0 +1,31 @@
1
+ """
2
+ Overview
3
+ ========
4
+
5
+ **Summary:** Primary command-line interface (CLI) to ft3.
6
+
7
+ ---
8
+
9
+ Usage
10
+ -----
11
+
12
+ ```sh
13
+ $ ft3 --help
14
+ ```
15
+
16
+ """
17
+
18
+ __all__ = (
19
+ 'cfg',
20
+ 'lib',
21
+ 'obj',
22
+ 'main',
23
+ 'utl',
24
+ )
25
+
26
+ from . import cfg
27
+ from . import lib
28
+ from . import obj
29
+ from . import utl
30
+
31
+ from . utl import main
ft3/cli/cfg.py ADDED
@@ -0,0 +1,11 @@
1
+ """CLI constants."""
2
+
3
+ __all__ = (
4
+ 'Constants',
5
+ )
6
+
7
+ from .. import core
8
+
9
+
10
+ class Constants(core.cfg.Constants):
11
+ """Constant values specific to CLI modules."""
ft3/cli/lib.py ADDED
@@ -0,0 +1,7 @@
1
+ """CLI imports."""
2
+
3
+ from .. import core
4
+
5
+ __all__ = core.lib.__all__
6
+
7
+ from .. core . lib import *
ft3/cli/obj.py ADDED
@@ -0,0 +1,34 @@
1
+ """CLI objects."""
2
+
3
+ __all__ = (
4
+ 'parsers',
5
+ 'root_parser',
6
+ )
7
+
8
+ from .. import __version__
9
+
10
+ from . import cfg
11
+ from . import lib
12
+
13
+
14
+ class Constants(cfg.Constants):
15
+ """Constant values specific to CLI objs."""
16
+
17
+
18
+ root_parser = lib.argparse.ArgumentParser(
19
+ description='root_parser',
20
+ formatter_class=lib.argparse.ArgumentDefaultsHelpFormatter,
21
+ prog='ft3',
22
+ )
23
+ root_parser.add_argument(
24
+ '--version',
25
+ '-v',
26
+ action='version',
27
+ version=__version__,
28
+ )
29
+
30
+ parsers = root_parser.add_subparsers(
31
+ title='module',
32
+ required=True,
33
+ help='specify a module to access its commands'
34
+ )
ft3/cli/utl.py ADDED
@@ -0,0 +1,25 @@
1
+ """CLI utility functions."""
2
+
3
+ __all__ = (
4
+ 'main',
5
+ )
6
+
7
+ from . import obj
8
+
9
+
10
+ def main() -> None: # pragma: no cover
11
+ """
12
+ Main CLI entrypoint.
13
+
14
+ Commands follow the structure:
15
+
16
+ `$ ft3 {fgr_module_name} ...`
17
+
18
+ """
19
+
20
+ args = obj.root_parser.parse_args()
21
+ kwargs = args._get_kwargs()
22
+ as_args = [v for k, v in kwargs if k != 'func']
23
+ args.func(*as_args) # type: ignore[attr-defined]
24
+
25
+ return None
ft3/core/__init__.py ADDED
@@ -0,0 +1,37 @@
1
+ """
2
+ Overview
3
+ ========
4
+
5
+ **Author:** dan@1howardcapital.com
6
+
7
+ **Summary:** Zero-dependency python framework for object oriented development.
8
+
9
+ ---
10
+
11
+ Usage
12
+ -----
13
+
14
+ ```py
15
+ import ft3
16
+
17
+ ```
18
+
19
+ """
20
+
21
+ __all__ = (
22
+ 'cfg',
23
+ 'codecs',
24
+ 'enm',
25
+ 'exc',
26
+ 'lib',
27
+ 'strings',
28
+ 'typ',
29
+ )
30
+
31
+ from . import cfg
32
+ from . import codecs
33
+ from . import enm
34
+ from . import exc
35
+ from . import lib
36
+ from . import strings
37
+ from . import typ
ft3/core/cfg.py ADDED
@@ -0,0 +1,67 @@
1
+ """Core constants."""
2
+
3
+ __all__ = (
4
+ 'Constants',
5
+ )
6
+
7
+ from . import lib
8
+
9
+ if lib.t.TYPE_CHECKING: # pragma: no cover
10
+ from . import typ
11
+
12
+
13
+ class Constants:
14
+ """Constant values shared across all of ft3."""
15
+
16
+ PACAKGE = 'ft3'
17
+ """Reference to package name."""
18
+
19
+ CLASS_AS_DICT: 'typ.string[typ.snake_case]' = 'class_as_dict'
20
+ """Common string reference."""
21
+
22
+ DELIM = '-'
23
+ """Common delimiter used throughout package."""
24
+
25
+ INDENT = int(lib.os.getenv('INDENT', 2))
26
+ """
27
+ Default, package-wide indentation.
28
+
29
+ ---
30
+
31
+ Used for `__repr__`, log messages, etc.
32
+
33
+ """
34
+
35
+ UNDEFINED = f'[[{PACAKGE.upper()}_DEFAULT_PLACEHOLDER]]'
36
+ """Placeholder for undefined values that should not be `None`."""
37
+
38
+ ENV = lib.os.getenv('ENV', 'local').lower()
39
+ """The lowered name of our runtime environment."""
40
+
41
+ DEPLOY_ENVS = (
42
+ 'dev',
43
+ 'develop',
44
+ 'qa',
45
+ 'test',
46
+ 'testing',
47
+ 'stg',
48
+ 'stage',
49
+ 'staging',
50
+ 'uat',
51
+ 'prod',
52
+ 'production',
53
+ )
54
+ """Valid, non-local runtime environment names."""
55
+
56
+ DELIM_REBASE = '_X_'
57
+
58
+ __ANNOTATIONS__: 'typ.string[typ.snake_case]' = '__annotations__'
59
+ __DATACLASS_FIELDS__: 'typ.string[typ.snake_case]' = '__dataclass_fields__'
60
+ __DICT__: 'typ.string[typ.snake_case]' = '__dict__'
61
+ __HERITAGE__: 'typ.string[typ.snake_case]' = '__heritage__'
62
+ __SLOTS__: 'typ.string[typ.snake_case]' = '__slots__'
63
+ __MODULE__: 'typ.string[typ.snake_case]' = '__module__'
64
+
65
+ FIELDS: 'typ.string[typ.snake_case]' = 'fields'
66
+ ENUMERATIONS: 'typ.string[typ.snake_case]' = 'enumerations'
67
+ HASH_FIELDS: 'typ.string[typ.snake_case]' = 'hash_fields'
@@ -0,0 +1,15 @@
1
+ """Core codec modules."""
2
+
3
+ __all__ = (
4
+ 'cfg',
5
+ 'enm',
6
+ 'lib',
7
+ 'typ',
8
+ 'utl',
9
+ )
10
+
11
+ from . import cfg
12
+ from . import enm
13
+ from . import lib
14
+ from . import typ
15
+ from . import utl
ft3/core/codecs/cfg.py ADDED
@@ -0,0 +1,46 @@
1
+ """Codec constants."""
2
+
3
+ __all__ = (
4
+ 'Constants',
5
+ )
6
+
7
+ from .. import cfg
8
+
9
+ from . import lib
10
+ from . import typ
11
+
12
+
13
+ def _isoformat_encoder(
14
+ o: lib.datetime.datetime | lib.datetime.date | lib.datetime.time
15
+ ) -> str:
16
+ return o.isoformat()
17
+
18
+
19
+ class Constants(cfg.Constants):
20
+ """Constant values shared across core codecs modules."""
21
+
22
+ ENCODERS: dict[
23
+ type[lib.t.Any],
24
+ lib.t.Callable[[lib.t.Any], typ.Serial]
25
+ ] = {
26
+ bytes: lambda o: getattr(o, 'decode')(),
27
+ lib.datetime.date: _isoformat_encoder,
28
+ lib.datetime.datetime: _isoformat_encoder,
29
+ lib.datetime.time: _isoformat_encoder,
30
+ lib.datetime.timedelta: lambda td: getattr(td, 'total_seconds')(),
31
+ lib.decimal.Decimal: float,
32
+ lib.enum.Enum: lambda o: getattr(o, 'value'),
33
+ frozenset: list,
34
+ lib.collections.deque: list,
35
+ lib.types.GeneratorType: list,
36
+ lib.ipaddress.IPv4Address: str,
37
+ lib.ipaddress.IPv4Interface: str,
38
+ lib.ipaddress.IPv4Network: str,
39
+ lib.ipaddress.IPv6Address: str,
40
+ lib.ipaddress.IPv6Interface: str,
41
+ lib.ipaddress.IPv6Network: str,
42
+ lib.pathlib.Path: str,
43
+ lib.re.Pattern: lambda o: getattr(o, 'pattern'),
44
+ set: list,
45
+ lib.uuid.UUID: str,
46
+ }
ft3/core/codecs/enm.py ADDED
@@ -0,0 +1,65 @@
1
+ """Codecs enumerations."""
2
+
3
+ from .. import enm
4
+
5
+ __all__ = (
6
+ 'ParseErrorRef',
7
+ *enm.__all__
8
+ )
9
+
10
+ from .. enm import *
11
+
12
+ from . import lib
13
+ from . import typ
14
+
15
+
16
+ class ParseErrorRef(lib.enum.Enum):
17
+ """
18
+ Valid ErrorRef Enumeration.
19
+
20
+ """
21
+
22
+ bool_decode = typ.ErrorRef(
23
+ 'Could not decode valid JSON string to python `bool`.'
24
+ )
25
+ invalid_arr_decode = typ.ErrorRef(
26
+ 'Could not decode valid JSON array to python: `invalid item type(s)`.'
27
+ )
28
+ invalid_arr_len = typ.ErrorRef(
29
+ 'Could not decode valid JSON array to python: `invalid array length`.'
30
+ )
31
+ invalid_json = typ.ErrorRef(
32
+ 'Could not deserialize string as valid JSON.'
33
+ )
34
+ invalid_keys_decode = typ.ErrorRef(
35
+ 'Could not decode valid JSON object to python: `invalid keys`.'
36
+ )
37
+ invalid_map_decode = typ.ErrorRef(
38
+ ' '.join(
39
+ (
40
+ 'Could not decode valid JSON object to python:',
41
+ '`invalid item type(s)`.'
42
+ )
43
+ )
44
+ )
45
+ invalid_values_decode = typ.ErrorRef(
46
+ 'Could not decode valid JSON object to python: `invalid values`.'
47
+ )
48
+ number_decode = typ.ErrorRef(
49
+ ' '.join(
50
+ (
51
+ 'Could not decode valid JSON string to python',
52
+ '`numbers.Number`.'
53
+ )
54
+ )
55
+ )
56
+ null_decode = typ.ErrorRef(
57
+ 'Could not decode valid JSON string to python `None`.'
58
+ )
59
+ datetime_decode = typ.ErrorRef(
60
+ 'Could not decode value to valid `datetime`.'
61
+ )
62
+ literal_decode = typ.ErrorRef(
63
+ 'Could not decode value to valid `Literal`.'
64
+ )
65
+ value_decode = typ.ErrorRef('Could not decode invalid value.')
ft3/core/codecs/lib.py ADDED
@@ -0,0 +1,20 @@
1
+ """Codecs imports."""
2
+
3
+ from .. import lib
4
+
5
+ __all__ = (
6
+ 'collections',
7
+ 'ipaddress',
8
+ 'numbers',
9
+ 'pathlib',
10
+ 'uuid',
11
+ *lib.__all__
12
+ )
13
+
14
+ import collections.abc
15
+ import ipaddress
16
+ import numbers
17
+ import pathlib
18
+ import uuid
19
+
20
+ from .. lib import *
ft3/core/codecs/typ.py ADDED
@@ -0,0 +1,14 @@
1
+ """Codecs types."""
2
+
3
+ from .. import typ
4
+
5
+ __all__ = (
6
+ 'ErrorRef',
7
+ *typ.__all__
8
+ )
9
+
10
+ from .. typ import *
11
+
12
+ from . import lib
13
+
14
+ ErrorRef = lib.t.NewType('ErrorRef', str)