1313import sys
1414import typing as ty
1515import warnings
16- from collections import OrderedDict
1716from functools import reduce
1817from operator import mul
1918from os .path import exists , splitext
@@ -84,7 +83,14 @@ class Recoder:
8483 2
8584 """
8685
87- def __init__ (self , codes , fields = ('code' ,), map_maker = OrderedDict ):
86+ fields : tuple [str , ...]
87+
88+ def __init__ (
89+ self ,
90+ codes : ty .Sequence [ty .Sequence [ty .Hashable ]],
91+ fields : ty .Sequence [str ] = ('code' ,),
92+ map_maker : type [ty .Mapping [ty .Hashable , ty .Hashable ]] = dict ,
93+ ):
8894 """Create recoder object
8995
9096 ``codes`` give a sequence of code, alias sequences
@@ -122,14 +128,14 @@ def __init__(self, codes, fields=('code',), map_maker=OrderedDict):
122128 self .field1 = self .__dict__ [fields [0 ]]
123129 self .add_codes (codes )
124130
125- def __getattr__ (self , key : str ) -> ty .Mapping :
131+ def __getattr__ (self , key : str ) -> ty .Mapping [ ty . Hashable , ty . Hashable ] :
126132 # By setting this, we let static analyzers know that dynamic attributes will
127133 # be dict-like (Mapping).
128134 # However, __getattr__ is called if looking up the field in __dict__ fails,
129135 # so we only get here if the attribute is really missing.
130136 raise AttributeError (f'{ self .__class__ .__name__ !r} object has no attribute { key !r} ' )
131137
132- def add_codes (self , code_syn_seqs ) :
138+ def add_codes (self , code_syn_seqs : ty . Sequence [ ty . Sequence [ ty . Hashable ]]) -> None :
133139 """Add codes to object
134140
135141 Parameters
@@ -163,7 +169,7 @@ def add_codes(self, code_syn_seqs):
163169 for field_ind , field_name in enumerate (self .fields ):
164170 self .__dict__ [field_name ][alias ] = code_syns [field_ind ]
165171
166- def __getitem__ (self , key ) :
172+ def __getitem__ (self , key : ty . Hashable ) -> ty . Hashable :
167173 """Return value from field1 dictionary (first column of values)
168174
169175 Returns same value as ``obj.field1[key]`` and, with the
@@ -176,13 +182,9 @@ def __getitem__(self, key):
176182 """
177183 return self .field1 [key ]
178184
179- def __contains__ (self , key ) :
185+ def __contains__ (self , key : ty . Hashable ) -> bool :
180186 """True if field1 in recoder contains `key`"""
181- try :
182- self .field1 [key ]
183- except KeyError :
184- return False
185- return True
187+ return key in self .field1
186188
187189 def keys (self ):
188190 """Return all available code and alias values
@@ -198,7 +200,7 @@ def keys(self):
198200 """
199201 return self .field1 .keys ()
200202
201- def value_set (self , name = None ):
203+ def value_set (self , name : str | None = None ) -> OrderedSet :
202204 """Return OrderedSet of possible returned values for column
203205
204206 By default, the column is the first column.
@@ -232,7 +234,7 @@ def value_set(self, name=None):
232234endian_codes = Recoder (_endian_codes )
233235
234236
235- class DtypeMapper :
237+ class DtypeMapper ( dict [ ty . Hashable , ty . Hashable ]) :
236238 """Specialized mapper for numpy dtypes
237239
238240 We pass this mapper into the Recoder class to deal with numpy dtype
@@ -250,40 +252,34 @@ class DtypeMapper:
250252 and return any matching values for the matching key.
251253 """
252254
253- def __init__ (self ):
254- self ._dict = {}
255- self ._dtype_keys = []
256-
257- def keys (self ):
258- return self ._dict .keys ()
259-
260- def values (self ):
261- return self ._dict .values ()
255+ def __init__ (self ) -> None :
256+ super ().__init__ ()
257+ self ._dtype_keys : list [np .dtype ] = []
262258
263- def __setitem__ (self , key , value ) :
259+ def __setitem__ (self , key : ty . Hashable , value : ty . Hashable ) -> None :
264260 """Set item into mapping, checking for dtype keys
265261
266262 Cache dtype keys for comparison test in __getitem__
267263 """
268- self . _dict [ key ] = value
269- if hasattr (key , 'subdtype' ):
264+ super (). __setitem__ ( key , value )
265+ if isinstance (key , np . dtype ):
270266 self ._dtype_keys .append (key )
271267
272- def __getitem__ (self , key ) :
268+ def __getitem__ (self , key : ty . Hashable ) -> ty . Hashable :
273269 """Get item from mapping, checking for dtype keys
274270
275271 First do simple hash lookup, then check for a dtype key that has failed
276272 the hash lookup. Look then for any known dtype keys that compare equal
277273 to `key`.
278274 """
279275 try :
280- return self . _dict [ key ]
276+ return super (). __getitem__ ( key )
281277 except KeyError :
282278 pass
283- if hasattr (key , 'subdtype' ):
279+ if isinstance (key , np . dtype ):
284280 for dt in self ._dtype_keys :
285281 if key == dt :
286- return self . _dict [ dt ]
282+ return super (). __getitem__ ( dt )
287283 raise KeyError (key )
288284
289285
@@ -347,7 +343,7 @@ def pretty_mapping(mapping, getterfunc=None):
347343 return '\n ' .join (out )
348344
349345
350- def make_dt_codes (codes_seqs ) :
346+ def make_dt_codes (codes_seqs : ty . Sequence [ ty . Sequence ]) -> Recoder :
351347 """Create full dt codes Recoder instance from datatype codes
352348
353349 Include created numpy dtype (from numpy type) and opposite endian
0 commit comments