autotype-input 0.1.0__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.
- autotype_input-0.1.0/PKG-INFO +13 -0
- autotype_input-0.1.0/README.md +5 -0
- autotype_input-0.1.0/pyproject.toml +15 -0
- autotype_input-0.1.0/setup.cfg +4 -0
- autotype_input-0.1.0/src/autotype/__init__.py +9 -0
- autotype_input-0.1.0/src/autotype/converter.py +11 -0
- autotype_input-0.1.0/src/autotype/core.py +70 -0
- autotype_input-0.1.0/src/autotype/registry.py +27 -0
- autotype_input-0.1.0/src/autotype_input.egg-info/PKG-INFO +13 -0
- autotype_input-0.1.0/src/autotype_input.egg-info/SOURCES.txt +11 -0
- autotype_input-0.1.0/src/autotype_input.egg-info/dependency_links.txt +1 -0
- autotype_input-0.1.0/src/autotype_input.egg-info/top_level.txt +1 -0
- autotype_input-0.1.0/tests/test_core.py +119 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: autotype-input
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Automatic datatype detection and conversion for python input
|
|
5
|
+
Author: DEBAYAN DEY
|
|
6
|
+
Requires-Python: >=3.8
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
#Autotype Input
|
|
10
|
+
Automatically detects common Python datatypes from user input
|
|
11
|
+
|
|
12
|
+
##Installation
|
|
13
|
+
pip install autotype-input
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "autotype-input"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Automatic datatype detection and conversion for python input"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [{name="DEBAYAN DEY"}]
|
|
13
|
+
|
|
14
|
+
[tool.setuptools.packages.find]
|
|
15
|
+
where = ["src"]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from collections import __all__
|
|
2
|
+
from .core import auto_input,auto_convert
|
|
3
|
+
from .registry import (register_converter, unregister_converter)
|
|
4
|
+
from .converter import Converter
|
|
5
|
+
_all__ = ["auto_input",
|
|
6
|
+
"auto_convert",
|
|
7
|
+
"register_converter",
|
|
8
|
+
"unregister_converter",
|
|
9
|
+
"Converter"]
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
from datetime import date, datetime, time
|
|
3
|
+
from .registry import get_converter, NO_MATCH
|
|
4
|
+
from .converter import Converter
|
|
5
|
+
def auto_convert(value):
|
|
6
|
+
"""Automatically coverts a string to a suitable python datatype"""
|
|
7
|
+
|
|
8
|
+
if not isinstance(value,str):
|
|
9
|
+
return value
|
|
10
|
+
|
|
11
|
+
value = value.strip()
|
|
12
|
+
|
|
13
|
+
for converter in get_converter():
|
|
14
|
+
if isinstance(converter,Converter):
|
|
15
|
+
if converter.can_convert(value):
|
|
16
|
+
return converter.convert(value)
|
|
17
|
+
else:
|
|
18
|
+
result = converter(value)
|
|
19
|
+
if result is not NO_MATCH:
|
|
20
|
+
return result
|
|
21
|
+
|
|
22
|
+
#Boolean
|
|
23
|
+
if value.lower()=="true":
|
|
24
|
+
return True
|
|
25
|
+
|
|
26
|
+
if value.lower()=="false":
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
#None
|
|
30
|
+
if value.lower() == "none":
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
#Bytes
|
|
34
|
+
if value.startswith(("b'", 'b"')) and value.endswith(("'", '"')):
|
|
35
|
+
try:
|
|
36
|
+
result = ast.literal_eval(value)
|
|
37
|
+
if isinstance(result,bytes):
|
|
38
|
+
return result
|
|
39
|
+
except (ValueError, SyntaxError):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
#DAte
|
|
43
|
+
try:
|
|
44
|
+
return date.fromisoformat(value)
|
|
45
|
+
except ValueError:
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
#Datetime
|
|
49
|
+
try:
|
|
50
|
+
return datetime.fromisoformat(value)
|
|
51
|
+
except ValueError:
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
#Time
|
|
55
|
+
try:
|
|
56
|
+
return time.fromisoformat(value)
|
|
57
|
+
except ValueError:
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
#Other libraries
|
|
61
|
+
try:
|
|
62
|
+
return ast.literal_eval(value)
|
|
63
|
+
except(ValueError, SyntaxError):
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
return value
|
|
67
|
+
|
|
68
|
+
def auto_input(prompt=""):
|
|
69
|
+
"""takes user input and automatcally determine its datatype"""
|
|
70
|
+
return auto_convert(input(prompt))
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
_converters = []
|
|
2
|
+
class _NoMatch:
|
|
3
|
+
pass
|
|
4
|
+
|
|
5
|
+
NO_MATCH = _NoMatch()
|
|
6
|
+
|
|
7
|
+
def register_converter(converter, priority=None):
|
|
8
|
+
"""register a converter"""
|
|
9
|
+
if priority is None:
|
|
10
|
+
priority = getattr(converter, "priority", 0)
|
|
11
|
+
|
|
12
|
+
_converters.append((priority,converter))
|
|
13
|
+
_converters.sort(key=lambda item:item[0], reverse=True)
|
|
14
|
+
|
|
15
|
+
def registy_converter(converter, priority=0):
|
|
16
|
+
entry = (priority, converter)
|
|
17
|
+
_converters.append(entry)
|
|
18
|
+
_converters.sort(key=lambda item: item[0], reverse=True)
|
|
19
|
+
|
|
20
|
+
def unregister_converter(converter):
|
|
21
|
+
"Unregister a converter"
|
|
22
|
+
global _converters
|
|
23
|
+
_converters = [(priority, registered_converter)for priority,registered_converter in _converters if registered_converter is not converter]
|
|
24
|
+
|
|
25
|
+
def get_converter():
|
|
26
|
+
"""Return registered converters in priority order"""
|
|
27
|
+
return [converter for priority, converter in _converters]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: autotype-input
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Automatic datatype detection and conversion for python input
|
|
5
|
+
Author: DEBAYAN DEY
|
|
6
|
+
Requires-Python: >=3.8
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
#Autotype Input
|
|
10
|
+
Automatically detects common Python datatypes from user input
|
|
11
|
+
|
|
12
|
+
##Installation
|
|
13
|
+
pip install autotype-input
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/autotype/__init__.py
|
|
4
|
+
src/autotype/converter.py
|
|
5
|
+
src/autotype/core.py
|
|
6
|
+
src/autotype/registry.py
|
|
7
|
+
src/autotype_input.egg-info/PKG-INFO
|
|
8
|
+
src/autotype_input.egg-info/SOURCES.txt
|
|
9
|
+
src/autotype_input.egg-info/dependency_links.txt
|
|
10
|
+
src/autotype_input.egg-info/top_level.txt
|
|
11
|
+
tests/test_core.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
autotype
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from autotype import (auto_convert, register_converter, unregister_converter)
|
|
2
|
+
from autotype import Converter
|
|
3
|
+
from autotype.registry import NO_MATCH
|
|
4
|
+
from datetime import date,time
|
|
5
|
+
|
|
6
|
+
def test_integer():
|
|
7
|
+
assert auto_convert("42")==42
|
|
8
|
+
assert type(auto_convert("42"))is int
|
|
9
|
+
|
|
10
|
+
def test_float():
|
|
11
|
+
assert auto_convert("3.14")==3.14
|
|
12
|
+
assert type(auto_convert("3.14"))is float
|
|
13
|
+
|
|
14
|
+
def test_boolean():
|
|
15
|
+
assert auto_convert("True")is True
|
|
16
|
+
assert auto_convert("False")is False
|
|
17
|
+
|
|
18
|
+
def test_none():
|
|
19
|
+
assert auto_convert("None")is None
|
|
20
|
+
|
|
21
|
+
def test_string():
|
|
22
|
+
assert auto_convert("hello")=="hello"
|
|
23
|
+
assert type(auto_convert("hello"))is str
|
|
24
|
+
|
|
25
|
+
def test_list():
|
|
26
|
+
assert auto_convert("[1, 2, 3]")==[1, 2, 3]
|
|
27
|
+
|
|
28
|
+
def test_tuple():
|
|
29
|
+
assert auto_convert("(1, 2, 3)")==(1, 2, 3)
|
|
30
|
+
|
|
31
|
+
def test_dictionary():
|
|
32
|
+
assert auto_convert('{"name": "John", "age": 20}')=={"name": "John", "age":20}
|
|
33
|
+
|
|
34
|
+
def test_set():
|
|
35
|
+
assert auto_convert("(1, 2, 3)") == (1, 2, 3)
|
|
36
|
+
|
|
37
|
+
def test_complex():
|
|
38
|
+
result = auto_convert("3+4j")
|
|
39
|
+
assert result == 3+4j
|
|
40
|
+
assert type(result) is complex
|
|
41
|
+
|
|
42
|
+
def test_date():
|
|
43
|
+
result = auto_convert("2026-08-23")
|
|
44
|
+
assert result == date(2026, 8, 23)
|
|
45
|
+
assert type(result) is date
|
|
46
|
+
|
|
47
|
+
def test_time():
|
|
48
|
+
result = auto_convert("12:30:00")
|
|
49
|
+
assert result == time(12,30,0)
|
|
50
|
+
assert type(result) is time
|
|
51
|
+
|
|
52
|
+
class UserID:
|
|
53
|
+
def __init__(self, value):
|
|
54
|
+
self.value = value
|
|
55
|
+
|
|
56
|
+
def user_id_converter(value):
|
|
57
|
+
if value.startswith("USER-"):
|
|
58
|
+
return UserID(value)
|
|
59
|
+
return NO_MATCH
|
|
60
|
+
|
|
61
|
+
def test_custom_converter():
|
|
62
|
+
register_converter(user_id_converter)
|
|
63
|
+
result = auto_convert("USER-123")
|
|
64
|
+
assert isinstance(result, UserID)
|
|
65
|
+
assert result.value == "USER-123"
|
|
66
|
+
|
|
67
|
+
def test_converter_priority():
|
|
68
|
+
def low_priority(value):
|
|
69
|
+
if value == "123":
|
|
70
|
+
return "low"
|
|
71
|
+
|
|
72
|
+
return NO_MATCH
|
|
73
|
+
|
|
74
|
+
def high_priority(value):
|
|
75
|
+
if value == "123":
|
|
76
|
+
return "high"
|
|
77
|
+
|
|
78
|
+
return NO_MATCH
|
|
79
|
+
|
|
80
|
+
register_converter(low_priority, priority=10)
|
|
81
|
+
register_converter(high_priority, priority=100)
|
|
82
|
+
|
|
83
|
+
result = auto_convert("123")
|
|
84
|
+
assert result == "high"
|
|
85
|
+
|
|
86
|
+
def test_converter_can_return_none():
|
|
87
|
+
from autotype.registry import NO_MATCH
|
|
88
|
+
def converter(value):
|
|
89
|
+
if value == "empty":
|
|
90
|
+
return None
|
|
91
|
+
return NO_MATCH
|
|
92
|
+
|
|
93
|
+
register_converter(converter, priority=1000)
|
|
94
|
+
result = auto_convert("empty")
|
|
95
|
+
assert result is None
|
|
96
|
+
unregister_converter(converter)
|
|
97
|
+
|
|
98
|
+
class User_ID:
|
|
99
|
+
def __init__(self, value):
|
|
100
|
+
self.value = value
|
|
101
|
+
|
|
102
|
+
class UserIDConverter(Converter):
|
|
103
|
+
priority = 100
|
|
104
|
+
|
|
105
|
+
def can_convert(self, value):
|
|
106
|
+
return value.startswith("USER-")
|
|
107
|
+
|
|
108
|
+
def convert(self, value):
|
|
109
|
+
return User_ID(value)
|
|
110
|
+
|
|
111
|
+
def test_converter_class():
|
|
112
|
+
converter = UserIDConverter()
|
|
113
|
+
|
|
114
|
+
register_converter(converter)
|
|
115
|
+
result = auto_convert("USER-123")
|
|
116
|
+
|
|
117
|
+
assert isinstance(result, User_ID)
|
|
118
|
+
assert result.value == "USER-123"
|
|
119
|
+
unregister_converter(converter)
|