@@ -30,7 +30,7 @@ class SchemaNotFoundError(FileNotFoundError):
3030
3131
3232class Connection (object ):
33- def __init__ (self , autoconnect = True , ** kwargs ):
33+ def __init__ (self , autoconnect = True , verbose = False , ** kwargs ):
3434 """
3535 Set up the connection to the WRDS database.
3636 By default, also establish the connection to the database.
@@ -40,13 +40,16 @@ def __init__(self, autoconnect=True, **kwargs):
4040 *wrds_port*: database connection port number
4141 *wrds_dbname*: WRDS database name
4242 *wrds_username*: WRDS username
43+ *autoconnect*: If false will not immediately establish the connection
4344
44- The constructor will use the .pgpass file if it exists.
45+ The constructor will use the .pgpass file if it exists and may make use of
46+ PostgreSQL environment variables such as PGHOST, PGUSER, etc., if cooresponding
47+ parameters are not set.
4548 If not, it will ask the user for a username and password.
4649 It will also direct the user to information on setting up .pgpass.
4750
4851 Additionally, creating the instance will load a list of schemas
49- the user has permission to access.
52+ the user has permission to access.
5053
5154 :return: None
5255
@@ -55,91 +58,89 @@ def __init__(self, autoconnect=True, **kwargs):
5558 Loading library list...
5659 Done
5760 """
61+ self ._verbose = verbose
5862 self ._password = ""
5963 # If user passed in any of these parameters, override defaults.
60- self ._username = kwargs .get ("wrds_username" , None )
61- self ._hostname = kwargs .get ("wrds_hostname" , WRDS_POSTGRES_HOST )
64+ self ._username = kwargs .get ("wrds_username" , "" )
65+ # PGHOST if set will override default for first attempt
66+ self ._hostname = kwargs .get (
67+ "wrds_hostname" , os .environ .get ('PGHOST' , WRDS_POSTGRES_HOST )
68+ )
6269 self ._port = kwargs .get ("wrds_port" , WRDS_POSTGRES_PORT )
6370 self ._dbname = kwargs .get ("wrds_dbname" , WRDS_POSTGRES_DB )
6471 self ._connect_args = kwargs .get ("wrds_connect_args" , WRDS_CONNECT_ARGS )
6572
66- # If username was passed in, the URI is different.
67- if self ._username :
68- pguri = "postgresql://{usr}@{host}:{port}/{dbname}"
69- self .engine = sa .create_engine (
70- pguri .format (
71- usr = self ._username ,
72- host = self ._hostname ,
73- port = self ._port ,
74- dbname = self ._dbname ,
75- ),
76- isolation_level = "AUTOCOMMIT" ,
77- connect_args = self ._connect_args ,
78- )
79- # No username passed in, but other parameters might have been.
80- else :
81- pguri = "postgresql://{host}:{port}/{dbname}"
82- self .engine = sa .create_engine (
83- pguri .format (host = self ._hostname , port = self ._port , dbname = self ._dbname ),
84- isolation_level = "AUTOCOMMIT" ,
85- connect_args = self ._connect_args ,
86- )
8773 if autoconnect :
8874 self .connect ()
8975 self .load_library_list ()
9076
91- def connect (self ):
92- """Make a connection to the WRDS database."""
77+ def __make_sa_engine_conn (self , raise_err = False ):
78+ username = self ._username
79+ hostname = self ._hostname
80+ password = urllib .parse .quote_plus (self ._password )
81+ port = self ._port
82+ dbname = self ._dbname
83+ pguri = f"postgresql://{ username } :{ password } @{ hostname } :{ port } /{ dbname } "
84+ if self ._verbose :
85+ print (f"postgresql://{ username } :@{ hostname } :{ port } /{ dbname } " )
9386 try :
94- self .connection = self .engine .connect ()
95- except Exception :
96- # These things should probably not be exported all over creation
97- self ._username , self ._password = self .__get_user_credentials ()
98- pghost = "postgresql://{usr}:{pwd}@{host}:{port}/{dbname}"
9987 self .engine = sa .create_engine (
100- pghost .format (
101- usr = self ._username ,
102- pwd = urllib .parse .quote_plus (self ._password ),
103- host = self ._hostname ,
104- port = self ._port ,
105- dbname = self ._dbname ,
106- ),
88+ pguri ,
10789 isolation_level = "AUTOCOMMIT" ,
10890 connect_args = self ._connect_args ,
10991 )
110- try :
111- self .connection = self .engine .connect ()
112- except Exception as e :
113- print ("There was an error with your password." )
114- self ._username = None
115- self ._password = None
116- raise e
117-
118- # Connection successful. Offer to create a .pgpass for the user.
119- print ("WRDS recommends setting up a .pgpass file." )
120- do_create_pgpass = ""
121- while do_create_pgpass != "y" and do_create_pgpass != "n" :
122- do_create_pgpass = input ("Create .pgpass file now [y/n]?: " )
123-
124- if do_create_pgpass == "y" :
125- try :
126- self .create_pgpass_file ()
127- print ("Created .pgpass file successfully." )
128- except :
129- print (
130- "Failed to create .pgpass file. Please try manually with the "
131- "create_pgpass_file() function."
132- )
92+ self .connection = self .engine .connect ()
93+ except Exception as err :
94+ if self ._verbose :
95+ print (f"{ err = } " )
96+ self .engine = None
97+ if raise_err :
98+ raise err
99+
100+ def connect (self ):
101+ """Make a connection to the WRDS database."""
102+ # first try connection using system defaults and params set in constructor
103+ self .__make_sa_engine_conn ()
104+
105+ if (self .engine is None and self ._hostname != WRDS_POSTGRES_HOST ):
106+ # try explicit w/ default hostname
107+ print (f"Trying '{ WRDS_POSTGRES_HOST } '..." )
108+ self ._hostname = WRDS_POSTGRES_HOST
109+ self .__make_sa_engine_conn ()
110+
111+ if (self .engine is None ):
112+ # Use explicit username and password
113+ self ._username , self ._password = self .__get_user_credentials ()
114+ # Last attempt, raise error if Exception encountered
115+ self .__make_sa_engine_conn (raise_err = True )
116+
117+ if (self .engine is None ):
118+ print (f"Failed to connect { self ._username } @{ self ._hostname } " )
133119 else :
134- print ("You can create this file yourself at any time" )
135- print ("with the create_pgpass_file() function." )
120+ # Connection successful. Offer to create a .pgpass for the user.
121+ print ("WRDS recommends setting up a .pgpass file." )
122+ do_create_pgpass = ""
123+ while do_create_pgpass != "y" and do_create_pgpass != "n" :
124+ do_create_pgpass = input ("Create .pgpass file now [y/n]?: " )
125+
126+ if do_create_pgpass == "y" :
127+ try :
128+ self .create_pgpass_file ()
129+ print ("Created .pgpass file successfully." )
130+ except Exception :
131+ print ("Failed to create .pgpass file." )
132+ print (
133+ "You can create this file yourself at any time "
134+ "with the create_pgpass_file() function."
135+ )
136136
137137 def close (self ):
138138 """
139139 Close the connection to the database.
140140 """
141141 self .connection .close ()
142142 self .engine .dispose ()
143+ self .engine = None
143144
144145 def __enter__ (self ):
145146 self .connect ()
@@ -215,7 +216,7 @@ def __get_user_credentials(self):
215216
216217 def create_pgpass_file (self ):
217218 """
218- Create a .pgpass file to store WRDS connection credentials..
219+ Create a .pgpass file to store WRDS connection credentials.
219220
220221 Use the existing username and password if already connected to WRDS,
221222 or prompt for that information if not.
0 commit comments