32
32
from pymongo .monitoring import _validate_event_listeners
33
33
from pymongo .read_concern import ReadConcern
34
34
from pymongo .read_preferences import _MONGOS_MODES , _ServerMode
35
- from pymongo .ssl_support import validate_cert_reqs
35
+ from pymongo .ssl_support import (validate_cert_reqs ,
36
+ validate_allow_invalid_certs )
36
37
from pymongo .write_concern import DEFAULT_WRITE_CONCERN , WriteConcern
37
38
38
39
try :
@@ -524,56 +525,79 @@ def validate_tzinfo(dummy, value):
524
525
return value
525
526
526
527
527
- # journal is an alias for j,
528
- # wtimeoutms is an alias for wtimeout,
529
- URI_VALIDATORS = {
530
- 'replicaset' : validate_string_or_none ,
531
- 'w' : validate_non_negative_int_or_basestring ,
532
- 'wtimeout' : validate_non_negative_integer ,
533
- 'wtimeoutms' : validate_non_negative_integer ,
534
- 'fsync' : validate_boolean_or_string ,
535
- 'j' : validate_boolean_or_string ,
528
+ # Dictionary where keys are the names of public URI options, and values
529
+ # are lists of aliases for that option. Aliases of option names are assumed
530
+ # to have been deprecated.
531
+ URI_OPTIONS_ALIAS_MAP = {
532
+ 'journal' : ['j' ],
533
+ 'wtimeoutms' : ['wtimeout' ],
534
+ 'tls' : ['ssl' ],
535
+ 'tlsallowinvalidcertificates' : ['ssl_cert_reqs' ],
536
+ 'tlsallowinvalidhostnames' : ['ssl_match_hostname' ],
537
+ 'tlscrlfile' : ['ssl_crlfile' ],
538
+ 'tlscafile' : ['ssl_ca_certs' ],
539
+ 'tlscertificatekeyfile' : ['ssl_certfile' ],
540
+ 'tlscertificatekeyfilepassword' : ['ssl_pem_passphrase' ],
541
+ }
542
+
543
+ # Dictionary where keys are the names of URI options, and values
544
+ # are functions that validate user-input values for that option. If an option
545
+ # alias uses a different validator than its public counterpart, it should be
546
+ # included here as a key, value pair.
547
+ URI_OPTIONS_VALIDATOR_MAP = {
548
+ 'appname' : validate_appname_or_none ,
549
+ 'authmechanism' : validate_auth_mechanism ,
550
+ 'authmechanismproperties' : validate_auth_mechanism_properties ,
551
+ 'authsource' : validate_string ,
552
+ 'compressors' : validate_compressors ,
553
+ 'connecttimeoutms' : validate_timeout_or_none ,
554
+ 'heartbeatfrequencyms' : validate_timeout_or_none ,
536
555
'journal' : validate_boolean_or_string ,
556
+ 'localthresholdms' : validate_positive_float_or_zero ,
557
+ 'maxidletimems' : validate_timeout_or_none ,
537
558
'maxpoolsize' : validate_positive_integer_or_none ,
538
- 'socketkeepalive' : validate_boolean_or_string ,
539
- 'waitqueuemultiple' : validate_non_negative_integer_or_none ,
540
- 'ssl' : validate_boolean_or_string ,
541
- 'ssl_keyfile' : validate_readable ,
542
- 'ssl_certfile' : validate_readable ,
543
- 'ssl_pem_passphrase' : validate_string_or_none ,
544
- 'ssl_cert_reqs' : validate_cert_reqs ,
545
- 'ssl_ca_certs' : validate_readable ,
546
- 'ssl_match_hostname' : validate_boolean_or_string ,
547
- 'ssl_crlfile' : validate_readable ,
559
+ 'maxstalenessseconds' : validate_max_staleness ,
548
560
'readconcernlevel' : validate_string_or_none ,
549
561
'readpreference' : validate_read_preference_mode ,
550
562
'readpreferencetags' : validate_read_preference_tags ,
551
- 'localthresholdms' : validate_positive_float_or_zero ,
552
- 'authmechanism' : validate_auth_mechanism ,
553
- 'authsource' : validate_string ,
554
- 'authmechanismproperties' : validate_auth_mechanism_properties ,
555
- 'tz_aware' : validate_boolean_or_string ,
556
- 'uuidrepresentation' : validate_uuid_representation ,
557
- 'connect' : validate_boolean_or_string ,
558
- 'minpoolsize' : validate_non_negative_integer ,
559
- 'appname' : validate_appname_or_none ,
560
- 'driver' : validate_driver_or_none ,
561
- 'unicode_decode_error_handler' : validate_unicode_decode_error_handler ,
563
+ 'replicaset' : validate_string_or_none ,
562
564
'retrywrites' : validate_boolean_or_string ,
563
- 'compressors' : validate_compressors ,
565
+ 'serverselectiontimeoutms' : validate_timeout_or_zero ,
566
+ 'sockettimeoutms' : validate_timeout_or_none ,
567
+ 'ssl_keyfile' : validate_readable ,
568
+ 'tls' : validate_boolean_or_string ,
569
+ 'tlsallowinvalidcertificates' : validate_allow_invalid_certs ,
570
+ 'ssl_cert_reqs' : validate_cert_reqs ,
571
+ 'tlsallowinvalidhostnames' : lambda * x : not validate_boolean_or_string (* x ),
572
+ 'ssl_match_hostname' : validate_boolean_or_string ,
573
+ 'tlscafile' : validate_readable ,
574
+ 'tlscertificatekeyfile' : validate_readable ,
575
+ 'tlscertificatekeyfilepassword' : validate_string_or_none ,
576
+ 'tlsinsecure' : validate_boolean_or_string ,
577
+ 'w' : validate_non_negative_int_or_basestring ,
578
+ 'wtimeoutms' : validate_non_negative_integer ,
564
579
'zlibcompressionlevel' : validate_zlib_compression_level ,
565
580
}
566
581
567
- TIMEOUT_VALIDATORS = {
568
- 'connecttimeoutms' : validate_timeout_or_none ,
569
- 'sockettimeoutms' : validate_timeout_or_none ,
582
+ # Dictionary where keys are the names of URI options specific to pymongo,
583
+ # and values are functions that validate user-input values for those options.
584
+ NONSPEC_OPTIONS_VALIDATOR_MAP = {
585
+ 'connect' : validate_boolean_or_string ,
586
+ 'driver' : validate_driver_or_none ,
587
+ 'fsync' : validate_boolean_or_string ,
588
+ 'minpoolsize' : validate_non_negative_integer ,
589
+ 'socketkeepalive' : validate_boolean_or_string ,
590
+ 'tlscrlfile' : validate_readable ,
591
+ 'tz_aware' : validate_boolean_or_string ,
592
+ 'unicode_decode_error_handler' : validate_unicode_decode_error_handler ,
593
+ 'uuidrepresentation' : validate_uuid_representation ,
594
+ 'waitqueuemultiple' : validate_non_negative_integer_or_none ,
570
595
'waitqueuetimeoutms' : validate_timeout_or_none ,
571
- 'serverselectiontimeoutms' : validate_timeout_or_zero ,
572
- 'heartbeatfrequencyms' : validate_timeout_or_none ,
573
- 'maxidletimems' : validate_timeout_or_none ,
574
- 'maxstalenessseconds' : validate_max_staleness ,
575
596
}
576
597
598
+ # Dictionary where keys are the names of keyword-only options for the
599
+ # MongoClient constructor, and values are functions that validate user-input
600
+ # values for those options.
577
601
KW_VALIDATORS = {
578
602
'document_class' : validate_document_class ,
579
603
'read_preference' : validate_read_preference ,
@@ -584,10 +608,57 @@ def validate_tzinfo(dummy, value):
584
608
'server_selector' : validate_is_callable_or_none ,
585
609
}
586
610
587
- URI_VALIDATORS .update (TIMEOUT_VALIDATORS )
588
- VALIDATORS = URI_VALIDATORS .copy ()
611
+ # Dictionary where keys are any URI option name, and values are the
612
+ # internally-used names of that URI option. Options with only one name
613
+ # variant need not be included here. Options whose public and internal
614
+ # names are the same need not be included here.
615
+ INTERNAL_URI_OPTION_NAME_MAP = {
616
+ 'j' : 'journal' ,
617
+ 'wtimeout' : 'wtimeoutms' ,
618
+ 'tls' : 'ssl' ,
619
+ 'tlsallowinvalidcertificates' : 'ssl_cert_reqs' ,
620
+ 'tlsallowinvalidhostnames' : 'ssl_match_hostname' ,
621
+ 'tlscrlfile' : 'ssl_crlfile' ,
622
+ 'tlscafile' : 'ssl_ca_certs' ,
623
+ 'tlscertificatekeyfile' : 'ssl_certfile' ,
624
+ 'tlscertificatekeyfilepassword' : 'ssl_pem_passphrase' ,
625
+ }
626
+
627
+ # Map from deprecated URI option names to the updated option names.
628
+ # Case is preserved for updated option names as they are part of user warnings.
629
+ URI_OPTIONS_DEPRECATION_MAP = {
630
+ 'j' : 'journal' ,
631
+ 'wtimeout' : 'wTimeoutMS' ,
632
+ 'ssl_cert_reqs' : 'tlsAllowInvalidCertificates' ,
633
+ 'ssl_match_hostname' : 'tlsAllowInvalidHostnames' ,
634
+ 'ssl_crlfile' : 'tlsCRLFile' ,
635
+ 'ssl_ca_certs' : 'tlsCAFile' ,
636
+ 'ssl_pem_passphrase' : 'tlsCertificateKeyFilePassword' ,
637
+ }
638
+
639
+ # Augment the option validator map with pymongo-specific option information.
640
+ URI_OPTIONS_VALIDATOR_MAP .update (NONSPEC_OPTIONS_VALIDATOR_MAP )
641
+ for optname , aliases in iteritems (URI_OPTIONS_ALIAS_MAP ):
642
+ for alias in aliases :
643
+ if alias not in URI_OPTIONS_VALIDATOR_MAP :
644
+ URI_OPTIONS_VALIDATOR_MAP [alias ] = (
645
+ URI_OPTIONS_VALIDATOR_MAP [optname ])
646
+
647
+ # Map containing all URI option and keyword argument validators.
648
+ VALIDATORS = URI_OPTIONS_VALIDATOR_MAP .copy ()
589
649
VALIDATORS .update (KW_VALIDATORS )
590
650
651
+ # List of timeout-related options.
652
+ TIMEOUT_OPTIONS = [
653
+ 'connecttimeoutms' ,
654
+ 'heartbeatfrequencyms' ,
655
+ 'maxidletimems' ,
656
+ 'maxstalenessseconds' ,
657
+ 'serverselectiontimeoutms' ,
658
+ 'sockettimeoutms' ,
659
+ 'waitqueuetimeoutms' ,
660
+ ]
661
+
591
662
592
663
_AUTH_OPTIONS = frozenset (['authmechanismproperties' ])
593
664
@@ -613,15 +684,22 @@ def validate(option, value):
613
684
614
685
def get_validated_options (options , warn = True ):
615
686
"""Validate each entry in options and raise a warning if it is not valid.
616
- Returns a copy of options with invalid entries removed
687
+ Returns a copy of options with invalid entries removed.
688
+
689
+ :Parameters:
690
+ - `opts`: A dict of MongoDB URI options.
691
+ - `warn` (optional): If ``True`` then warnings will be logged and
692
+ invalid options will be ignored. Otherwise, invalid options will
693
+ cause errors.
617
694
"""
618
695
validated_options = {}
619
696
for opt , value in iteritems (options ):
620
697
lower = opt .lower ()
621
698
try :
622
- validator = URI_VALIDATORS .get (lower , raise_config_error )
699
+ validator = URI_OPTIONS_VALIDATOR_MAP .get (
700
+ lower , raise_config_error )
623
701
value = validator (opt , value )
624
- except (ValueError , ConfigurationError ) as exc :
702
+ except (ValueError , TypeError , ConfigurationError ) as exc :
625
703
if warn :
626
704
warnings .warn (str (exc ))
627
705
else :
@@ -631,6 +709,7 @@ def get_validated_options(options, warn=True):
631
709
return validated_options
632
710
633
711
712
+ # List of write-concern-related options.
634
713
WRITE_CONCERN_OPTIONS = frozenset ([
635
714
'w' ,
636
715
'wtimeout' ,
0 commit comments