3232from pymongo .monitoring import _validate_event_listeners
3333from pymongo .read_concern import ReadConcern
3434from 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 )
3637from pymongo .write_concern import DEFAULT_WRITE_CONCERN , WriteConcern
3738
3839try :
@@ -524,56 +525,79 @@ def validate_tzinfo(dummy, value):
524525 return value
525526
526527
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 ,
536555 'journal' : validate_boolean_or_string ,
556+ 'localthresholdms' : validate_positive_float_or_zero ,
557+ 'maxidletimems' : validate_timeout_or_none ,
537558 '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 ,
548560 'readconcernlevel' : validate_string_or_none ,
549561 'readpreference' : validate_read_preference_mode ,
550562 '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 ,
562564 '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 ,
564579 'zlibcompressionlevel' : validate_zlib_compression_level ,
565580}
566581
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 ,
570595 '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 ,
575596}
576597
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.
577601KW_VALIDATORS = {
578602 'document_class' : validate_document_class ,
579603 'read_preference' : validate_read_preference ,
@@ -584,10 +608,57 @@ def validate_tzinfo(dummy, value):
584608 'server_selector' : validate_is_callable_or_none ,
585609}
586610
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 ()
589649VALIDATORS .update (KW_VALIDATORS )
590650
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+
591662
592663_AUTH_OPTIONS = frozenset (['authmechanismproperties' ])
593664
@@ -613,15 +684,22 @@ def validate(option, value):
613684
614685def get_validated_options (options , warn = True ):
615686 """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.
617694 """
618695 validated_options = {}
619696 for opt , value in iteritems (options ):
620697 lower = opt .lower ()
621698 try :
622- validator = URI_VALIDATORS .get (lower , raise_config_error )
699+ validator = URI_OPTIONS_VALIDATOR_MAP .get (
700+ lower , raise_config_error )
623701 value = validator (opt , value )
624- except (ValueError , ConfigurationError ) as exc :
702+ except (ValueError , TypeError , ConfigurationError ) as exc :
625703 if warn :
626704 warnings .warn (str (exc ))
627705 else :
@@ -631,6 +709,7 @@ def get_validated_options(options, warn=True):
631709 return validated_options
632710
633711
712+ # List of write-concern-related options.
634713WRITE_CONCERN_OPTIONS = frozenset ([
635714 'w' ,
636715 'wtimeout' ,
0 commit comments