datatypes 0.12.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.
Files changed (44) hide show
  1. datatypes/__init__.py +153 -0
  2. datatypes/collections/__init__.py +22 -0
  3. datatypes/collections/container.py +150 -0
  4. datatypes/collections/mapping.py +614 -0
  5. datatypes/collections/sequence.py +469 -0
  6. datatypes/command.py +572 -0
  7. datatypes/compat.py +205 -0
  8. datatypes/config/__init__.py +9 -0
  9. datatypes/config/environ.py +302 -0
  10. datatypes/config/parser.py +255 -0
  11. datatypes/copy.py +151 -0
  12. datatypes/csv.py +322 -0
  13. datatypes/datetime.py +888 -0
  14. datatypes/decorators/__init__.py +23 -0
  15. datatypes/decorators/base.py +343 -0
  16. datatypes/decorators/descriptor.py +389 -0
  17. datatypes/decorators/misc.py +118 -0
  18. datatypes/email.py +351 -0
  19. datatypes/enum.py +191 -0
  20. datatypes/event.py +207 -0
  21. datatypes/filetypes/__init__.py +12 -0
  22. datatypes/filetypes/html.py +556 -0
  23. datatypes/filetypes/toml.py +260 -0
  24. datatypes/http.py +723 -0
  25. datatypes/logging.py +384 -0
  26. datatypes/number.py +187 -0
  27. datatypes/parse.py +246 -0
  28. datatypes/path.py +3637 -0
  29. datatypes/profile.py +232 -0
  30. datatypes/reflection.py +1498 -0
  31. datatypes/server.py +408 -0
  32. datatypes/service.py +212 -0
  33. datatypes/string.py +1328 -0
  34. datatypes/token/__init__.py +16 -0
  35. datatypes/token/abnf.py +1704 -0
  36. datatypes/token/base.py +475 -0
  37. datatypes/token/word.py +259 -0
  38. datatypes/url.py +841 -0
  39. datatypes/utils.py +142 -0
  40. datatypes-0.12.0.dist-info/LICENSE.txt +21 -0
  41. datatypes-0.12.0.dist-info/METADATA +52 -0
  42. datatypes-0.12.0.dist-info/RECORD +44 -0
  43. datatypes-0.12.0.dist-info/WHEEL +5 -0
  44. datatypes-0.12.0.dist-info/top_level.txt +1 -0
datatypes/compat.py ADDED
@@ -0,0 +1,205 @@
1
+ # -*- coding: utf-8 -*-
2
+ from __future__ import unicode_literals, division, print_function, absolute_import
3
+ import sys
4
+
5
+ try:
6
+ import cPickle as pickle
7
+ except ImportError:
8
+ import pickle
9
+
10
+ # shamelessly ripped from https://github.com/kennethreitz/requests/blob/master/requests/compat.py
11
+ # Syntax sugar.
12
+ _ver = sys.version_info
13
+ is_py2 = _ver[0] == 2
14
+ is_py3 = _ver[0] == 3
15
+
16
+ if is_py2:
17
+ basestring = basestring
18
+ unicode = unicode
19
+ range = xrange # range is now always an iterator
20
+ input = raw_input
21
+ cmp = cmp
22
+
23
+ import Queue as queue
24
+
25
+ # using _* makes __all__ not export this automatically, so you have to
26
+ # explicitly import this (from datatypes.compat import _thread), the reason
27
+ # is because the thread module is lowkey deprecated in favor of the
28
+ # threading module
29
+ #
30
+ # https://stackoverflow.com/questions/1141047/why-was-the-thread-module-renamed-to-thread-in-python-3-x
31
+ #
32
+ # I've chosen to keep the _thread syntax to prod me into finding a better
33
+ # way to do something, but I still have access to it explicitely if I need it
34
+ import thread as _thread
35
+
36
+ try:
37
+ from cStringIO import StringIO
38
+ except ImportError:
39
+ from StringIO import StringIO
40
+
41
+ from SimpleHTTPServer import SimpleHTTPRequestHandler
42
+ from BaseHTTPServer import (
43
+ BaseHTTPRequestHandler,
44
+ HTTPServer,
45
+ )
46
+ import SocketServer as socketserver
47
+ import Cookie as cookies
48
+ import __builtin__ as builtins
49
+
50
+ from urllib import urlencode
51
+ from urllib2 import (
52
+ Request,
53
+ urlopen,
54
+ URLError,
55
+ HTTPError,
56
+ )
57
+ import urlparse as parse
58
+
59
+ import itertools
60
+ zip = itertools.izip
61
+ zip_longest = itertools.izip_longest
62
+
63
+ from collections import (
64
+ Iterable,
65
+ Mapping,
66
+ Callable,
67
+ MutableSequence,
68
+ Sequence,
69
+ Collection,
70
+ )
71
+
72
+
73
+ from HTMLParser import HTMLParser
74
+ #unescape = HTMLParser().unescape
75
+
76
+ import cgi
77
+ class html(object):
78
+ @classmethod
79
+ def escape(cls, *args, **kwargs):
80
+ return cgi.escape(*args, **kwargs)
81
+
82
+ @classmethod
83
+ def unescape(cls, *args, **kwargs):
84
+ return HTMLParser().unescape(*args, **kwargs)
85
+
86
+ # NOTE -- getargspace isn't a full mapping of getfullargspec
87
+ from inspect import getargspec as getfullargspec
88
+
89
+
90
+ exec("""def reraise(exception_class, e, traceback=None):
91
+ try:
92
+ raise exception_class, e, traceback
93
+ finally:
94
+ traceback = None
95
+ """)
96
+
97
+
98
+ else:
99
+ basestring = (str, bytes)
100
+ unicode = str
101
+ long = int
102
+ input = input
103
+
104
+ import queue
105
+ import _thread
106
+ from io import StringIO
107
+ from http.server import (
108
+ HTTPServer,
109
+ SimpleHTTPRequestHandler,
110
+ BaseHTTPRequestHandler,
111
+ )
112
+ import socketserver
113
+ from http import cookies
114
+ import builtins
115
+
116
+ from functools import reduce # removed from common functions
117
+ from html.parser import HTMLParser
118
+ from urllib import parse
119
+ from urllib.parse import urlencode
120
+ from urllib.request import Request, urlopen
121
+ from urllib.error import URLError, HTTPError
122
+ try:
123
+ import html
124
+ #from html import unescape
125
+ except ImportError:
126
+ import cgi
127
+ class html(object):
128
+ @classmethod
129
+ def escape(cls, *args, **kwargs):
130
+ return cgi.escape(*args, **kwargs)
131
+
132
+ @classmethod
133
+ def unescape(cls, *args, **kwargs):
134
+ return HTMLParser().unescape(*args, **kwargs)
135
+ #unescape = HTMLParser.unescape
136
+
137
+ from inspect import getfullargspec
138
+ from itertools import zip_longest
139
+
140
+ from collections.abc import (
141
+ Iterable,
142
+ Mapping,
143
+ Callable,
144
+ MutableSequence,
145
+ Sequence,
146
+ Collection,
147
+ )
148
+
149
+
150
+ # ripped from six https://github.com/benjaminp/six
151
+ def reraise(exception_class, e, traceback=None):
152
+ """the 3 params correspond to the return value of sys.exc_info()
153
+
154
+ https://docs.python.org/3/library/sys.html#sys.exc_info
155
+
156
+ :param exception_class: BaseException, the class of the exception to reraise
157
+ :param e: BaseException instance, the actual exception instance
158
+ :param traceback: traceback, the stack trace
159
+ """
160
+ try:
161
+ e = exception_class("" if e is None else e)
162
+ if e.__traceback__ is not traceback:
163
+ raise e.with_traceback(traceback)
164
+ raise e
165
+ finally:
166
+ e = None
167
+ traceback = None
168
+
169
+
170
+ # py3 has no cmp function for some strange reason
171
+ # https://codegolf.stackexchange.com/a/49779
172
+ def cmp(a, b):
173
+ return (a > b) - (a < b)
174
+
175
+
176
+ Str = unicode if is_py2 else str
177
+ Bytes = str if is_py2 else bytes
178
+
179
+
180
+ # TODO using reraise
181
+
182
+ # if py_2:
183
+ # #raise error_info[0].__class__, error_info[0], error_info[1][2]
184
+ # reraise(*error_info)
185
+ # #raise error_info[0].__class__, error_info[1], error_info[2]
186
+ #
187
+ # elif py_3:
188
+ # #e, exc_info = error_info
189
+ # #et, ei, tb = exc_info
190
+ #
191
+ # reraise(*error_info)
192
+ # #et, ei, tb = error_info
193
+ # #raise ei.with_traceback(tb)
194
+
195
+
196
+ # if not error_info:
197
+ # exc_info = sys.exc_info()
198
+ # #raise e.__class__, e, exc_info[2]
199
+ # #self.error_info = (e, exc_info)
200
+ # self.error_info = exc_info
201
+ #
202
+ # if error_info:
203
+ #
204
+ # reraise(*error_info)
205
+
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .environ import (
4
+ Environ,
5
+ )
6
+ from .parser import (
7
+ Config,
8
+ )
9
+
@@ -0,0 +1,302 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ import tempfile
4
+
5
+ from ..compat import *
6
+
7
+
8
+ class Environ(Mapping):
9
+ """Create an Environ namespace instance
10
+
11
+ you would usually create this like this:
12
+
13
+ environ = Environ("PREFIX_")
14
+
15
+ Then you can access any environment variables with that prefix from the
16
+ `environ` instance.
17
+
18
+ :Example:
19
+ # in your environment
20
+ export PREFIX_FOOBAR=1
21
+ export PREFIX_CHE="this is the che value"
22
+
23
+ # in your python code
24
+ environ = Environ("PREFIX_")
25
+
26
+ print(environ.FOOBAR) # "1"
27
+ print(environ.CHE) # this is the che value
28
+
29
+ # by default, all environ values are string, but you can set defaults
30
+ # and set the type
31
+ environ.setdefault("BAZ", 1000, type=int)
32
+
33
+ print(environ.BAZ, type(environ.BAZ)) # 1000 <class 'int'>
34
+ """
35
+ @classmethod
36
+ def find_namespace(cls, prefix):
37
+ namespace = ""
38
+ if prefix:
39
+ namespace = prefix.split(".", maxsplit=1)[0].upper()
40
+ if not namespace.endswith("_"):
41
+ namespace += "_"
42
+ return namespace
43
+
44
+ def __init__(self, namespace="", environ=None):
45
+ """
46
+ :param namespace: str, usually __name__ from the calling module but can
47
+ also be "PREFIX_" or something like that
48
+ :param environ: str, the environment you want this instance to wrap, it
49
+ defualts to os.environ
50
+ """
51
+ self.__dict__["namespace"] = self.find_namespace(namespace)
52
+ self.__dict__["defaults"] = {}
53
+ self.__dict__["environ"] = environ or os.environ
54
+
55
+ def setdefault(self, key, value, type=None):
56
+ self.defaults[self.ekey(key)] = {
57
+ "value": value,
58
+ "type": type,
59
+ }
60
+
61
+ def set(self, key, value):
62
+ self.__setattr__(key, value)
63
+ #os.environ[self.key(key)] = value
64
+
65
+ def __setattr__(self, key, value):
66
+ #os.environ[self.key(key)] = value
67
+ self.environ[self.key(key)] = value
68
+
69
+ def __setitem__(self, key, value):
70
+ self.__setattr__(key, value)
71
+
72
+ def nset(self, key, values):
73
+ """Given a list of values, this will set key_* where * is 1 -> len(values)
74
+
75
+ :param key: string, the key that will be added to the environment as key_*
76
+ :param values: list, a list of values
77
+ """
78
+ self.ndelete(key)
79
+
80
+ for i, v in enumerate(values, 1):
81
+ k = "{}_{}".format(key, i)
82
+ self.set(k, v)
83
+
84
+ def delete(self, key):
85
+ """remove key from the environment"""
86
+ self.__delattr__(key)
87
+ #os.environ.pop(self.key(key), None)
88
+
89
+ def __delitem__(self, key):
90
+ #os.environ.pop(self.key(key), None)
91
+ self.environ.pop(self.key(key), None)
92
+
93
+ def ndelete(self, key):
94
+ """remove all key_* from the environment"""
95
+ for k in self.nkeys(key):
96
+ #os.environ.pop(k)
97
+ self.environ.pop(k, None)
98
+
99
+ def get(self, key, default=None):
100
+ """get a value for key from the environment
101
+
102
+ :param key: string, this will be normalized using the key() method
103
+ :returns: mixed, the value in the environment of key, or default if key
104
+ is not in the environment
105
+ """
106
+ try:
107
+ return self[key]
108
+
109
+ except KeyError:
110
+ return default
111
+ #return os.environ.get(self.key(key), default)
112
+
113
+ def pop(self, key, *defaults):
114
+ try:
115
+ return self.__getitem__(key)
116
+
117
+ except KeyError:
118
+ if defaults:
119
+ return defaults[0]
120
+
121
+ else:
122
+ raise
123
+
124
+ def __getitem__(self, key):
125
+ ek = self.ekey(key)
126
+ k = self.key(key)
127
+ try:
128
+ #return os.environ[k]
129
+ v = self.environ[k]
130
+
131
+ except KeyError:
132
+ v = self.defaults[ek]["value"]
133
+
134
+ if ek in self.defaults:
135
+ if self.defaults[ek]["type"]:
136
+ v = self.defaults[ek]["type"](v)
137
+
138
+ return v
139
+
140
+ def __getattr__(self, key):
141
+ try:
142
+ return self.__getitem__(key)
143
+
144
+ except KeyError as e:
145
+ raise AttributeError(key) from e
146
+
147
+ def nget(self, key):
148
+ """this will look for key, and key_N (where
149
+ N is 1 to infinity) in the environment
150
+
151
+ The number checks (eg *_1, *_2) go in order, so you can't do *_1, *_3,
152
+ because it will fail on missing *_2 and move on, so make sure your number
153
+ suffixes are in order (eg, 1, 2, 3, ...)
154
+
155
+ :param key: string, the name of the environment variables
156
+ :returns: generator, the found values for key and key_* variants
157
+ """
158
+ for nkey in self.nkeys(key):
159
+ #yield os.environ[nkey]
160
+ yield self.environ[nkey]
161
+
162
+ def keys(self):
163
+ """yields all the keys of the given namespace currently in the environment"""
164
+ for k, _ in self.items():
165
+ yield k
166
+
167
+ def values(self):
168
+ """yields all the keys of the given namespace currently in the environment"""
169
+ for _, v in self.items():
170
+ yield v
171
+
172
+ def items(self):
173
+ #for k, v in os.environ.items():
174
+ seen = set()
175
+ for k, v in self.environ.items():
176
+ if k.startswith(self.namespace):
177
+ ek = self.ekey(k)
178
+ seen.add(ek)
179
+ yield ek, v
180
+
181
+ for ek, d in self.defaults.items():
182
+ if ek not in seen:
183
+ yield ek, d["value"]
184
+
185
+ def __iter__(self):
186
+ return self.keys()
187
+
188
+ def key(self, key):
189
+ """normalizes key to have the namespace
190
+
191
+ :Example:
192
+ environ = Environ("FOO_")
193
+ k = environ.key("BAR")
194
+ print(k) # FOO_BAR
195
+ """
196
+ if self.namespace and not key.startswith(self.namespace):
197
+ key = self.namespace + key
198
+ return key
199
+
200
+ def ekey(self, key):
201
+ """Given a full namespaced key return the key name without the namespace
202
+
203
+ :Example:
204
+ environ = Environ("FOO_")
205
+ k = environ.ekey("FOO_BAR")
206
+ print(k) # BAR
207
+ """
208
+ return key.replace(self.namespace, "")
209
+
210
+ def nkey(self, key, n):
211
+ """internal method. Helper method for nkeys"""
212
+ k = self.key(key)
213
+ for fmt in ["{key}_{n}", "{key}{n}"]:
214
+ nkey = fmt.format(key=k, n=n)
215
+ if nkey in self.environ:
216
+ #if nkey in os.environ:
217
+ return nkey
218
+
219
+ raise KeyError("Environ {} has no {} key".format(key, n))
220
+
221
+ def nkeys(self, key):
222
+ """This returns the actual environment variable names from * -> *_N
223
+
224
+ :param key: string, the name of the environment variables
225
+ :returns: generator, the found environment names
226
+ """
227
+ k = self.key(key)
228
+ #if k in os.environ:
229
+ if k in self.environ:
230
+ yield k
231
+
232
+ # now try importing _1 -> _N prefixes
233
+ n = 0
234
+ while True:
235
+ try:
236
+ yield self.nkey(key, n)
237
+
238
+ except KeyError:
239
+ # 0 is a special case, so if it fails we keep going
240
+ if n:
241
+ # we are done because we missed an n value
242
+ break
243
+
244
+ finally:
245
+ n += 1
246
+
247
+ def paths(self, key):
248
+ """splits the value at key by the path separator and yields each individual
249
+ path part
250
+
251
+ splits each value using the path separator
252
+
253
+ :param key: str, the key
254
+ :returns: generator, each part of the value found at key
255
+ """
256
+ sep = os.pathsep
257
+ for paths in self.nget(key):
258
+ for p in paths.split(sep):
259
+ yield p
260
+
261
+ def has(self, key):
262
+ """Return True if key is in the environment
263
+
264
+ :param k: str
265
+ :returns: bool
266
+ """
267
+ #return self.key(key) in os.environ
268
+ return self.key(key) in self.environ
269
+
270
+ def __contains__(self, key):
271
+ return self.has(key)
272
+
273
+ def __len__(self):
274
+ return len(list(self.keys()))
275
+
276
+
277
+ ###############################################################################
278
+ # Actual environment configuration that is used throughout the package
279
+ ###############################################################################
280
+ environ = Environ("DATATYPES_")
281
+
282
+ environ.setdefault("ENCODING", "UTF-8")
283
+ """For things that need encoding, this will be the default encoding if nothing
284
+ else is passed in"""
285
+
286
+
287
+ environ.setdefault("ENCODING_ERRORS", "replace")
288
+ """For things that need encoding, this will handle any errors"""
289
+
290
+
291
+ # 2021-1-15 - we place our cache by default into another directory because I
292
+ # have problems running some commands like touch on the base temp directory on
293
+ # MacOS on Python3, no idea why but I couldn't get around it
294
+ environ.setdefault(
295
+ "CACHE_DIR",
296
+ os.path.join(tempfile.gettempdir(), environ.namespace.lower().rstrip("_"))
297
+ )
298
+ """the default caching directory for things that need a cache folder"""
299
+
300
+
301
+ environ.setdefault("USER_AGENT", "")
302
+