18
18
from ipython_genutils .encoding import DEFAULT_ENCODING
19
19
from six import text_type , string_types , PY3
20
20
from traitlets .traitlets import (
21
- HasTraits , Container , List , Dict , Any ,
21
+ HasTraits , Container , List , Dict , Any , Undefined ,
22
22
)
23
23
24
24
#-----------------------------------------------------------------------------
@@ -853,14 +853,33 @@ def _kv_opt(traitname, opt_value):
853
853
return m .groups ()
854
854
855
855
856
+ class _FlagAction (argparse .Action ):
857
+ """ArgParse action to handle a flag"""
858
+ def __init__ (self , * args , ** kwargs ):
859
+ self .flag = kwargs .pop ('flag' )
860
+ self .alias = kwargs .pop ('alias' , None )
861
+ kwargs ['const' ] = Undefined
862
+ if not self .alias :
863
+ kwargs ['nargs' ] = 0
864
+ super (_FlagAction , self ).__init__ (* args , ** kwargs )
865
+
866
+ def __call__ (self , parser , namespace , values , option_string = None ):
867
+ key = option_string .lstrip ('-' )
868
+ print ('values %r' % values )
869
+ if self .nargs == 0 or values is Undefined :
870
+ namespace ._flags .append (self .flag )
871
+ else :
872
+ setattr (namespace , self .alias , values )
873
+
874
+
856
875
class KVArgParseConfigLoader (ArgParseConfigLoader ):
857
876
"""A config loader that loads aliases and flags with argparse,
858
877
but will use KVLoader for the rest. This allows better parsing
859
878
of common args, such as `ipython -c 'print 5'`, but still gets
860
879
arbitrary config with `ipython --InteractiveShell.autoindent=False`"""
861
880
862
881
def _add_arguments (self , aliases = None , flags = None , classes = None ):
863
- self . alias_flags = {}
882
+ alias_flags = {}
864
883
# print aliases, flags
865
884
if aliases is None :
866
885
aliases = self .aliases
@@ -869,6 +888,7 @@ def _add_arguments(self, aliases=None, flags=None, classes=None):
869
888
if classes is None :
870
889
classes = self .classes
871
890
paa = self .parser .add_argument
891
+ self .parser .set_defaults (_flags = [])
872
892
873
893
## An index of all container traits collected::
874
894
#
@@ -892,61 +912,54 @@ def _add_arguments(self, aliases=None, flags=None, classes=None):
892
912
argparse_traits [argname ] = (trait , argparse_kwds )
893
913
paa ('--' + argname , ** argparse_kwds )
894
914
895
- for keys , traitname in aliases .items ():
915
+ for keys , ( value , _ ) in flags .items ():
896
916
if not isinstance (keys , tuple ):
897
917
keys = (keys , )
898
918
for key in keys :
899
- argparse_kwds = {'type' : text_type , 'dest' : traitname }
900
- ## Is alias for a sequence-trait?
901
- #
902
- if traitname in argparse_traits :
903
- argparse_kwds .update (argparse_traits [traitname ][1 ])
904
- if 'action' in argparse_kwds :
905
- ## A flag+alias should have `nargs='?'` multiplicity,
906
- # but base config-property had 'append' multiplicity!
907
- #
908
- if key in flags :
909
- raise ArgumentError (
910
- "The alias `%s` for the 'append' sequence "
911
- "config-trait `%s` cannot be also a flag!'"
912
- % (key , traitname ))
913
- else :
914
- if key in flags :
915
- argparse_kwds ['nargs' ] = '?'
919
+ if key in self .aliases :
920
+ alias_flags [self .aliases [key ]] = value
921
+ continue
916
922
keys = ('-' + key , '--' + key ) if len (key ) is 1 else ('--' + key , )
917
- paa (* keys , ** argparse_kwds )
923
+ paa (* keys , action = _FlagAction , flag = value )
918
924
919
- for keys , ( value , _ ) in flags .items ():
925
+ for keys , traitname in aliases .items ():
920
926
if not isinstance (keys , tuple ):
921
927
keys = (keys , )
922
928
for key in keys :
923
- if key in self .aliases :
924
- self .alias_flags [self .aliases [key ]] = value
925
- continue
929
+ argparse_kwds = {'type' : text_type , 'dest' : traitname }
930
+ if traitname in argparse_traits :
931
+ argparse_kwds .update (argparse_traits [traitname ][1 ])
932
+ if 'action' in argparse_kwds and traitname in alias_flags :
933
+ # flag sets 'action', so can't have flag & alias with custom action
934
+ # on the same name
935
+ raise ArgumentError (
936
+ "The alias `%s` for the 'append' sequence "
937
+ "config-trait `%s` cannot be also a flag!'"
938
+ % (key , traitname ))
939
+ if traitname in alias_flags :
940
+ # alias and flag.
941
+ # when called with 0 args: flag
942
+ # when called with >= 1: alias
943
+ argparse_kwds .setdefault ('nargs' , '?' )
944
+ argparse_kwds ['action' ] = _FlagAction
945
+ argparse_kwds ['flag' ] = alias_flags [traitname ]
946
+ argparse_kwds ['alias' ] = traitname
926
947
keys = ('-' + key , '--' + key ) if len (key ) is 1 else ('--' + key , )
927
- paa (* keys , action = 'append_const' , dest = '_flags' , const = value )
948
+ paa (* keys , ** argparse_kwds )
928
949
929
950
def _convert_to_config (self ):
930
951
"""self.parsed_data->self.config, parse unrecognized extra args via KVLoader."""
931
- # remove subconfigs list from namespace before transforming the Namespace
932
- if '_flags' in self .parsed_data :
933
- subcs = self .parsed_data ._flags
934
- del self .parsed_data ._flags
935
- else :
936
- subcs = []
937
-
938
952
for k , v in vars (self .parsed_data ).items ():
939
- if v is None :
940
- # it was a flag that shares the name of an alias
941
- subcs .append (self .alias_flags [k ])
942
- else :
943
- trait = self .argparse_traits .get (k )
944
- if trait :
945
- trait = trait [0 ]
946
- # eval the KV assignment
947
- self ._exec_config_str (k , v , trait = trait )
953
+ if k == '_flags' :
954
+ # _flags will be handled later
955
+ continue
956
+ trait = self .argparse_traits .get (k )
957
+ if trait :
958
+ trait = trait [0 ]
959
+ # eval the KV assignment
960
+ self ._exec_config_str (k , v , trait = trait )
948
961
949
- for subc in subcs :
962
+ for subc in self . parsed_data . _flags :
950
963
self ._load_flag (subc )
951
964
952
965
if self .extra_args :
0 commit comments