cdxcore 0.1.6__py3-none-any.whl → 0.1.9__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.

Potentially problematic release.


This version of cdxcore might be problematic. Click here for more details.

cdxcore/logger.py DELETED
@@ -1,319 +0,0 @@
1
- """
2
- Basic log file logic
3
- """
4
-
5
- from .util import _fmt, prnt, write
6
- import sys as sys
7
- import logging as logging
8
- import traceback as traceback
9
- import datetime as datetime
10
-
11
- _prnt = prnt
12
- _write = write
13
-
14
- class Logger(object):
15
- """
16
- Simple utility object to decorate loggers, plus:
17
- - infor, warning, () also accept named argument formatting ie "The error is %(message)self" instead of positional %
18
- - added Exceptn function which logs an error before returning an exception.
19
- It also make sure an exception is only tracked once.
20
- The point of this class is to be able to write
21
- import base.logger as logger
22
- _log = logger.getLogger(__file__)
23
- ...
24
- _log.verify( some_condition_we_want_met, "Error: cannot find %s", message)
25
- and it will keep a log of that exception.
26
-
27
- Exceptions independent of logging level
28
-
29
- verify( cond, text, *args, **kwargs )
30
- If cond is not met, raise an exception with util.fmt( text, *args, **kwargs )
31
-
32
- throw_if(cond, text, *args, **kwargs )
33
- If cond is met, raise an exception with util.fmt( text, *args, **kwargs )
34
-
35
- throw( text, *args, **kwargs )
36
- Raise an exception with fmt( text, *args, **kwargs )
37
-
38
- Unconditional logging
39
-
40
- debug( text, *args, **kwargs )
41
- info( text, *args, **kwargs )
42
- warning( text, *args, **kwargs )
43
- error( text, *args, **kwargs )
44
- debug( text, *args, **kwargs )
45
-
46
- Conditional logging functions, verify version
47
-
48
- verify_debug( cond, text, *args, **kwargs )
49
- verify_info( cond, text, *args, **kwargs )
50
- verify_warning( cond, text, *args, **kwargs )
51
-
52
- verify( cond, text, *args, **kwargs )
53
-
54
- Conditional logging functions, if version
55
-
56
- debug_if( text, *args, **kwargs )
57
- info_if( text, *args, **kwargs )
58
- warning_if( text, *args, **kwargs )
59
-
60
- throw_if( text, *args, **kwargs )
61
-
62
- prnt_if( text, *args, **kwargs ) # with EOL
63
- write_if( text, *args, **kwargs ) # without EOL
64
- """
65
-
66
- CRITICAL = logging.CRITICAL
67
- ERROR = logging.ERROR
68
- WARNING = logging.WARNING
69
- INFO = logging.INFO
70
- DEBUG = logging.DEBUG
71
- NOTSET = logging.NOTSET
72
-
73
- def __init__(self,topic : str):
74
- assert topic !="", "Logger cannot be empty"
75
- setupAppLogging() # ensure system is ready
76
- i = topic.rfind('/')
77
- if i == -1:
78
- i = topic.rfind('\\')
79
- if i != -1 and i<len(topic)-1:
80
- topic = topic[i+1:]
81
- self.logger = logging.getLogger(topic)
82
-
83
- # Exception support
84
- # -----------------
85
-
86
- class LogException(Exception):
87
- """ Placeholder exception class we use to identify our own exceptions """
88
-
89
- def __init__(self,text : str):
90
- Exception.__init__(self,text)
91
-
92
- def Exceptn(self, text : str, *args, **kwargs ):
93
- """
94
- Returns an exception object with 'text' % kwargs and stores an 'error' message
95
- If an exception is present, it will be printed, too.
96
- If the base logger logs 'debug' information, the call stack will be printed as well
97
-
98
- Usage:
99
- raise _log.Exceptn("Something happened")
100
- """
101
- text = _fmt(text,args,kwargs)
102
- (typ, val, trc) = sys.exc_info()
103
-
104
- # are we already throwing our own exception?
105
- if typ is Logger.LogException:
106
- return val # --> already logged --> keep raising the exception but don't do anything
107
-
108
- # new exception?
109
- if typ is None:
110
- assert val is None and trc is None, "*** Internal error"
111
- self.error( text )
112
- return Logger.LogException("*** LogException: " + text)
113
-
114
- # another exception is being thrown.
115
- # we re-cast this as one of our own.
116
- if text[-1] == ".":
117
- text = text + " " + str(val)
118
- else:
119
- text = text + ". " + str(val)
120
-
121
- # in debug, add trace information
122
- if self.logger.getEffectiveLevel() <= logging.WARNING:
123
- text = text.rstrip()
124
- txt = traceback.format_exception(typ,val,trc,limit = 100)
125
- for t in txt:
126
- text += "\n " + t[:-1]
127
- self.error( text )
128
-
129
- # return an exception with the corresponding text
130
- return Logger.LogException("*** LogException: " + text)
131
-
132
- # logging() replacemets
133
- # ---------------------
134
-
135
- def debug(self, text, *args, **kwargs ):
136
- """ Reports debug information with new style formatting """
137
- if self.logger.getEffectiveLevel() <= logging.DEBUG and len(text) > 0:
138
- self.logger.debug(_fmt(text,args,kwargs))
139
-
140
- def info(self, text, *args, **kwargs ):
141
- """ Reports information with new style formatting """
142
- if self.logger.getEffectiveLevel() <= logging.INFO and len(text) > 0:
143
- self.logger.info(_fmt(text,args,kwargs))
144
-
145
- def warning(self, text, *args, **kwargs ):
146
- """ Reports a warning with new style formatting """
147
- if self.logger.getEffectiveLevel() <= logging.WARNING and len(text) > 0:
148
- self.logger.warning(_fmt(text,args,kwargs))
149
- warn = warning
150
-
151
- def error(self, text, *args, **kwargs ):
152
- """ Reports an error with new style formatting """
153
- if self.logger.getEffectiveLevel() <= logging.ERROR and len(text) > 0:
154
- self.logger.error(_fmt(text,args,kwargs))
155
-
156
- def critical(self, text, *args, **kwargs ):
157
- """ Reports a critial occcurance with new style formatting """
158
- if self.logger.getEffectiveLevel() <= logging.CRITICAL and len(text) > 0:
159
- self.logger.critical(_fmt(text,args,kwargs))
160
-
161
- def throw( self, text, *args, **kwargs ):
162
- """ Raise an exception """
163
- raise self.Exceptn(text,*args,**kwargs)
164
-
165
- @staticmethod
166
- def prnt( text, *args, **kwargs ):
167
- """ Simple print, with EOL """
168
- _prnt(_fmt(text,args,kwargs))
169
-
170
- @staticmethod
171
- def write(text, *args, **kwargs ):
172
- """ Simple print, without EOL """
173
- _write(_fmt(text,args,kwargs))
174
-
175
- # run time utilities with validity check
176
- # --------------------------------------
177
-
178
- def verify(self, cond, text, *args, **kwargs ):
179
- """
180
- Verifies 'cond'. Raises an exception if 'cond' is not met with the specified text.
181
- Usage:
182
- _log.verify( i>0, "i must be positive, found %d", i)
183
- """
184
- if not cond:
185
- self.throw(text,*args,**kwargs)
186
-
187
- def verify_warning(self, cond, text, *args, **kwargs ):
188
- """
189
- Verifies 'cond'. If true, writes a warning and then continues
190
- Usage
191
- _log.verify_warning( i>0, "i must be positive, found %d", i)
192
- """
193
- if not cond:
194
- self.warning(text, *args, **kwargs )
195
-
196
- verify_warn = verify_warning
197
-
198
- def verify_info(self, cond, text, *args, **kwargs ):
199
- """ Verifies 'cond'. If true, writes log information and then continues """
200
- if not cond:
201
- self.info(text, *args, **kwargs )
202
-
203
- def verify_debug(self, cond, text, *args, **kwargs ):
204
- """ Verifies 'cond'. If true, writes log debug and then continues """
205
- if not cond:
206
- self.debug(text, *args, **kwargs )
207
-
208
- # if-action
209
- # ---------
210
-
211
- def throw_if(self, cond, text, *args, **kwargs ):
212
- """ Raises an exception if 'cond' is true. This is the reverse of verify() """
213
- if cond:
214
- raise self.Exceptn(text,*args,**kwargs)
215
- raise_if = throw_if
216
-
217
- def warning_if(self, cond, text, *args, **kwargs ):
218
- """ If 'cond' is true, writes a warning. Opposite condition than verify_warning """
219
- if cond:
220
- self.warning(text,*args,**kwargs)
221
- warn_if = warning_if
222
-
223
- def info_if(self, cond, text, *args, **kwargs ):
224
- """ If 'cond' is true, writes information 'info'. Opposite condition than verify_info """
225
- if cond:
226
- self.info(text,*args,**kwargs)
227
-
228
- def debug_if(self, cond, text, *args, **kwargs ):
229
- """ If 'cond' is true, writes debug 'info'. Opposite condition than verify_debug """
230
- if cond:
231
- self.debug(text,*args,**kwargs)
232
-
233
- @staticmethod
234
- def prnt_if(cond, text, *args, **kwargs ):
235
- """ If 'cond' is True, prnt() text. Python 2.7 """
236
- if cond:
237
- Logger.prnt(text,*args,**kwargs)
238
-
239
- @staticmethod
240
- def write_if(cond, text, *args, **kwargs ):
241
- """ If 'cond' is True, prnt() text """
242
- if cond:
243
- Logger.write(text,*args,**kwargs)
244
-
245
- # interface into logging
246
- # ----------------------
247
-
248
- def setLevel(self, level):
249
- """ logging.setLevel """
250
- self.logger.setLevel(level)
251
-
252
- def getEffectiveLevel(self):
253
- """ logging.getEffectiveLevel """
254
- return self.logger.getEffectiveLevel()
255
-
256
- # ====================================================================================================
257
- # setupAppLogging
258
- # ---------------
259
- # Defines logging at stderr and file level.
260
- # ====================================================================================================
261
-
262
- GLOBAL_LOG_DATA = "cdxbasics.logger"
263
-
264
- class RootLog(object):
265
- def __init__(self, root):
266
- self.handler = root
267
- self.fileName = None
268
-
269
- rootLog = RootLog( logging.getLogger() ) # root level logger
270
-
271
- def setupAppLogging( levelPrint : int = logging.ERROR,
272
- levelFile : int = None
273
- ):
274
- """
275
- Application wide logging control - basically sets a log file path
276
- This function will only called once.
277
- Put this function into your root import
278
-
279
- Parameters
280
- ----------
281
- levelPrint : printing level https://docs.python.org/3/library/logging.html
282
- levelFile : file level. Set to None to not write to file.
283
- """
284
-
285
- data = globals().get(GLOBAL_LOG_DATA,None)
286
- if data is None:
287
- # logging for std derror
288
- logging.basicConfig(level=min(levelPrint,levelFile) if not levelFile is None else levelPrint)
289
- fmtt = logging.Formatter(fmt="%(asctime)self %(levelname)-10s: %(message)self" )
290
- stdErr = logging.StreamHandler(sys.stdout)
291
- stdErr.setLevel(levelPrint )
292
- rootLog.handler.addHandler( stdErr )
293
- data = {'strm':stdErr }
294
-
295
- if not levelFile is None:
296
- # file system
297
- import os
298
- import os.path
299
- import tempfile
300
- stamp = datetime.datetime.now().strftime("%Y-%m-%d_%S%M%H")
301
- pid = os.getpid() # note: process name is 'python.exe'
302
- tmpDir = tempfile.gettempdir()
303
- logFile = os.path.join(tmpDir,"py_logger_" + stamp + "_" + str(pid) + ".log")
304
-
305
- fileE = None
306
- try:
307
- fileE = logging.FileHandler(logFile)
308
- fileE.setFormatter(fmtt)
309
- fileE.setLevel( levelFile )
310
- rootLog.handler.addHandler( fileE )
311
- data = {'strm':stdErr, 'file':fileE, 'logFileName':logFile }
312
- except:
313
- pass
314
-
315
- globals()[GLOBAL_LOG_DATA] = data
316
-
317
- rootLog.fileName = data.get('logFileName', None)
318
- return data
319
-
cdxcore/prettydict.py DELETED
@@ -1,388 +0,0 @@
1
- """
2
- prettyict
3
- Dictionaries with member synthax access
4
- Hans Buehler 2022
5
- """
6
-
7
- from collections import OrderedDict
8
- from sortedcontainers import SortedDict
9
- import dataclasses as dataclasses
10
- from dataclasses import Field
11
- import types as types
12
- from collections.abc import Mapping
13
-
14
- class PrettyDict(dict):
15
- """
16
- Dictionary which allows accessing its members with member notation, e.g.
17
- pdct = PrettyDict()
18
- pdct.x = 1
19
- x = pdct.x
20
-
21
- Functions will be made members, i.e the following works as expected
22
- def mult_x(self, a):
23
- return self.x * a
24
- pdct.mult_x = mult_x
25
- pdct.mult_x(2) --> 2
26
-
27
- To assign a static member use []:
28
- def mult(a,b):
29
- return a*b
30
- pdct['mult'] = mult
31
- pdct.mult(1,3) --> 3
32
-
33
- IMPORTANT
34
- Attributes starting with '__' are handled as standard attributes.
35
- In other words,
36
- pdct = PrettyDict()
37
- pdct.__x = 1
38
- _ = pdct['__x'] <- throws an exception
39
- This allows re-use of general operator handling.
40
- """
41
-
42
- def __getattr__(self, key : str):
43
- """ Equyivalent to self[key] """
44
- if key[:2] == "__": raise AttributeError(key) # you cannot treat private members as dictionary members
45
- return self[key]
46
- def __delattr__(self, key : str):
47
- """ Equyivalent to del self[key] """
48
- if key[:2] == "__": raise AttributeError(key) # you cannot treat private members as dictionary members
49
- del self[key]
50
- def __setattr__(self, key : str, value):
51
- """ Equivalent to self[key] = value """
52
- if key[:2] == "__":
53
- return dict.__setattr__(self, key, value)
54
- if isinstance(value,types.FunctionType):
55
- # bind function to this object
56
- value = types.MethodType(value,self)
57
- elif isinstance(value,types.MethodType):
58
- # re-point the method to the current instance
59
- value = types.MethodType(value.__func__,self)
60
- self[key] = value
61
- def __call__(self, key : str, *default):
62
- """ Equivalent of self.get(key,default) """
63
- if len(default) > 1:
64
- raise NotImplementedError("Cannot pass more than one default parameter.")
65
- return self.get(key,default[0]) if len(default) == 1 else self.get(key)
66
-
67
- def as_field(self) -> Field:
68
- """
69
- Returns a PrettyDictField wrapper around self for use in dataclasses
70
- See PrettyDictField documentation for an example
71
- """
72
- return PrettyDictField(self)
73
-
74
- class PrettyOrderedDict(OrderedDict):
75
- """
76
- Ordered dictionary which allows accessing its members with member notation, e.g.
77
- pdct = PrettyDict()
78
- pdct.x = 1
79
- x = pdct.x
80
-
81
- Functions will be made members, i.e the following works as expected
82
- def mult_x(self, a):
83
- return self.x * a
84
- pdct.mult_x = mult_x
85
- pdct.mult_x(2) --> 2
86
-
87
- To assign a static member use []:
88
- def mult(a,b):
89
- return a*b
90
- pdct['mult'] = mult
91
- pdct.mult(1,3) --> 3
92
-
93
- IMPORTANT
94
- Attributes starting with '__' are handled as standard attributes.
95
- In other words,
96
- pdct = PrettyOrderedDict()
97
- pdct.__x = 1
98
- _ = pdct['__x'] <- throws an exception
99
- This allows re-use of general operator handling.
100
- """
101
-
102
- def __getattr__(self, key : str):
103
- """ Equyivalent to self[key] """
104
- if key[:2] == "__": raise AttributeError(key) # you cannot treat private members as dictionary members
105
- return self[key]
106
- def __delattr__(self, key : str):
107
- """ Equyivalent to del self[key] """
108
- if key[:2] == "__": raise AttributeError(key) # you cannot treat private members as dictionary members
109
- del self[key]
110
- def __setattr__(self, key : str, value):
111
- """ Equivalent to self[key] = value """
112
- if key[:2] == "__":
113
- return OrderedDict.__setattr__(self, key, value)
114
- if isinstance(value,types.FunctionType):
115
- # bind function to this object
116
- value = types.MethodType(value,self)
117
- elif isinstance(value,types.MethodType):
118
- # re-point the method to the current instance
119
- value = types.MethodType(value.__func__,self)
120
- self[key] = value
121
- def __call__(self, key : str, *default):
122
- """ Equivalent of self.get(key,default) """
123
- if len(default) > 1:
124
- raise NotImplementedError("Cannot pass more than one default parameter.")
125
- return self.get(key,default[0]) if len(default) == 1 else self.get(key)
126
-
127
- # pickling
128
- def __getstate__(self):
129
- """ Return state to pickle """
130
- return self.__dict__
131
- def __setstate__(self, state):
132
- """ Restore pickle """
133
- self.__dict__.update(state)
134
-
135
- def as_field(self) -> Field:
136
- """
137
- Returns a PrettyDictField wrapper around 'self' for use in dataclasses
138
- See PrettyDictField documentation for an example
139
- """
140
- return PrettyDictField(self)
141
-
142
- @property
143
- def at_pos(self):
144
- """
145
- Element access
146
-
147
- at_pos[position] returns an element or elements at an ordinal position.
148
- It returns a single element if 'position' refers to only one field.
149
- If 'position' is a slice then the respecitve list of fields is returned
150
-
151
- at_pos[position] = item assigns an item or an ordinal position
152
- If 'position' refers to a single element, 'item' must be that item
153
- If 'position' is a slice then 'item' must resolve to a list of the required size.
154
-
155
- Key access
156
-
157
- at_pos.keys[position] returns the key or keys at 'position'
158
-
159
- at_pos.items[position] returns the tuple (key, element) or a list thereof for `position`
160
- """
161
- class Access:
162
- """
163
- Wrapper object to allow index access for at_pos
164
- """
165
- def __init__(self):
166
- self.__keys = None
167
-
168
- def __getitem__(_, position):
169
- key = _.keys[position]
170
- return self[key] if not isinstance(key,list) else [ self[k] for k in key ]
171
- def __setitem__(_, position, item ):
172
- key = _.keys[position]
173
- if not isinstance(key,list):
174
- self[key] = item
175
- else:
176
- for k, i in zip(key, item):
177
- self[k] = i
178
- @property
179
- def keys(_) -> list:
180
- """ Returns the list of keys of the original dictionary """
181
- if _.__keys is None:
182
- _.__keys = list(self.keys())
183
- return _.__keys
184
- @property
185
- def items(_) -> list:
186
- """ Returns the list of keys of the original dictionary """
187
- class ItemAccess(object):
188
- def __getitem__(_x, position):
189
- key = _.keys[position]
190
- return (key, self[key]) if not isinstance(key,list) else [ (k,self[k]) for k in key ]
191
- return ItemAccess()
192
-
193
- return Access()
194
-
195
- @property
196
- def key_at_pos(self) -> list:
197
- """
198
- key_at_pos returns the list of keys, hence key_at_pos[i] returns the ith key
199
- """
200
- return list(self)
201
-
202
- @property
203
- def item_at_pos(self) -> list:
204
- """
205
- key_at_pos returns the list of keys, hence key_at_pos[i] returns the ith key
206
- """
207
- return list(self)
208
-
209
- pdct = PrettyOrderedDict
210
-
211
- class BETA_PrettySortedDict(SortedDict):
212
- """
213
- *NOT WORKING WELL*
214
- Sorted dictionary which allows accessing its members with member notation, e.g.
215
- pdct = PrettyDict()
216
- pdct.x = 1
217
- x = pdct.x
218
-
219
- Functions will be made members, i.e the following works as expected
220
- def mult_x(self, a):
221
- return self.x * a
222
- pdct.mult_x = mult_x
223
- pdct.mult_x(2) --> 2
224
-
225
- To assign a static member use []:
226
- def mult(a,b):
227
- return a*b
228
- pdct['mult'] = mult
229
- pdct.mult(1,3) --> 3
230
-
231
- IMPORTANT
232
- Attributes starting with '_' (one underscore) are handled as standard attributes.
233
- In other words,
234
- pdct = PrettyOrderedDict()
235
- pdct._x = 1
236
- _ = pdct['_x'] <- throws an exception
237
- This allows re-use of general operator handling.
238
- The reason the sorted class disallow '_' (as opposed to the other two classes who merely disallow '__')
239
- is that SortedDict() uses protected members.
240
- """
241
-
242
- def __getattr__(self, key : str):
243
- """ Equyivalent to self[key] """
244
- if key[:1] == "_": raise AttributeError(key) # you cannot treat protected or private members as dictionary members
245
- return self[key]
246
- def __delattr__(self, key : str):
247
- """ Equyivalent to del self[key] """
248
- if key[:2] == "__": raise AttributeError(key) # you cannot treat private members as dictionary members
249
- del self[key]
250
- def __setattr__(self, key : str, value):
251
- """ Equivalent to self[key] = value """
252
- if key[:1] == "_":
253
- return SortedDict.__setattr__(self, key, value)
254
- if isinstance(value,types.FunctionType):
255
- # bind function to this object
256
- value = types.MethodType(value,self)
257
- elif isinstance(value,types.MethodType):
258
- # re-point the method to the current instance
259
- value = types.MethodType(value.__func__,self)
260
- self[key] = value
261
- def __call__(self, key : str, *default):
262
- """ Equivalent of self.get(key,default) """
263
- if len(default) > 1:
264
- raise NotImplementedError("Cannot pass more than one default parameter.")
265
- return self.get(key,default[0]) if len(default) == 1 else self.get(key)
266
-
267
- class PrettyDictField(object):
268
- """
269
- Simplististc 'read only' wrapper for PrettyOrderedDict objects.
270
- Useful for Flax
271
-
272
- import dataclasses as dataclasses
273
- import jax.numpy as jnp
274
- import jax as jax
275
- from options.cdxbasics.config import Config, ConfigField
276
- import types as types
277
-
278
- class A( nn.Module ):
279
- pdct : PrettyOrderedDictField = PrettyOrderedDictField.Field()
280
-
281
- def setup(self):
282
- self.dense = nn.Dense(1)
283
-
284
- def __call__(self, x):
285
- a = self.pdct.a
286
- return self.dense(x)*a
287
-
288
- r = PrettyOrderedDict(a=1.)
289
- a = A( r.as_field() )
290
-
291
- key1, key2 = jax.random.split(jax.random.key(0))
292
- x = jnp.zeros((10,10))
293
- param = a.init( key1, x )
294
- y = a.apply( param, x )
295
-
296
- The class will traverse pretty dictionaries of pretty dictionaries correctly.
297
- However, it has some limitations as it does not handle custom lists of pretty dicts.
298
- """
299
- def __init__(self, pdct : PrettyOrderedDict = None, **kwargs):
300
- """ Initialize with an input dictionary and potential overwrites """
301
- if not pdct is None:
302
- if type(pdct).__name__ == type(self).__name__ and len(kwargs) == 0:
303
- # copy
304
- self.__pdct = PrettyOrderedDict( pdct.__pdct )
305
- return
306
- if not isinstance(pdct, Mapping): raise ValueError("'pdct' must be a Mapping")
307
- self.__pdct = PrettyOrderedDict(pdct)
308
- self.__pdct.update(kwargs)
309
- else:
310
- self.__pdct = PrettyOrderedDict(**kwargs)
311
- def rec(x):
312
- for k, v in x.items():
313
- if isinstance(v, (PrettyDict, PrettyOrderedDict)):
314
- x[k] = PrettyDictField(v)
315
- elif isinstance(v, Mapping):
316
- rec(v)
317
- rec(self.__pdct)
318
-
319
- def as_dict(self) -> PrettyOrderedDict:
320
- """ Return copy of underlying dictionary """
321
- return PrettyOrderedDict( self.__pdct )
322
-
323
- def as_field(self) -> Field:
324
- """
325
- Returns a PrettyDictField wrapper around self for use in dataclasse
326
- This function makes a (shallow enough) copy of the current field.
327
- It is present so iterative applications of as_field() are convenient.
328
- """
329
- return PrettyDictField(self)
330
-
331
- @staticmethod
332
- def default():
333
- return PrettyDictField()
334
-
335
- @staticmethod
336
- def Field( default : PrettyOrderedDict = None, **kwargs):
337
- """
338
- Returns a dataclasses.field for PrettyDictField
339
- """
340
- if default is None and len(kwargs) == 0:
341
- return dataclasses.field( default_factory=PrettyDictField )
342
-
343
- if not default is None:
344
- default.upate(kwargs)
345
- else:
346
- default = kwargs
347
- def factory():
348
- return PrettyDictField(default)
349
- return dataclasses.field( default_factory=factory )
350
-
351
- # mimic the underlying dictionary
352
- # -------------------------------
353
-
354
- def __getattr__(self, key):
355
- if key[:2] == "__":
356
- return object.__getattr__(self,key)
357
- return self.__pdct.__getattr__(key)
358
- def __getitem__(self, key):
359
- return self.__pdct[key]
360
- def __call__(self, *kargs, **kwargs):
361
- return self.__pdct(*kargs, **kwargs)
362
- def __eq__(self, other):
363
- if type(other).__name__ == "PrettyOrderedDict":
364
- return self.__pdct == other
365
- else:
366
- return self.__pdct == other.pdct
367
- def keys(self):
368
- return self.__pdct.keys()
369
- def items(self):
370
- return self.__pdct.items()
371
- def values(self):
372
- return self.__pdct.values()
373
- def __hash__(self):
374
- h = 0
375
- for k, v in self.items():
376
- h ^= hash(k) ^ hash(v)
377
- return h
378
- def __iter__(self):
379
- return self.__pdct.__iter__()
380
- def __contains__(self, key):
381
- return self.__pdct.__contains__(key)
382
- def __len__(self):
383
- return self.__pdct.__len__()
384
- def __str__(self):
385
- return self.__pdct.__str__()
386
- def __repr__(self):
387
- return self.__pdct.__repr__()
388
-