| Conditions | 16 |
| Total Lines | 169 |
| Code Lines | 113 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like tabpy.tabpy_server.app.app.TabPyApp._parse_config() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | from argparse import ArgumentParser |
||
| 136 | def _parse_config(self, config_file): |
||
| 137 | """Provide consistent mechanism for pulling in configuration. |
||
| 138 | |||
| 139 | Attempt to retain backward compatibility for |
||
| 140 | existing implementations by grabbing port |
||
| 141 | setting from CLI first. |
||
| 142 | |||
| 143 | Take settings in the following order: |
||
| 144 | |||
| 145 | 1. CLI arguments if present |
||
| 146 | 2. config file |
||
| 147 | 3. OS environment variables (for ease of |
||
| 148 | setting defaults if not present) |
||
| 149 | 4. current defaults if a setting is not present in any location |
||
| 150 | |||
| 151 | Additionally provide similar configuration capabilities in between |
||
| 152 | config file and environment variables. |
||
| 153 | For consistency use the same variable name in the config file as |
||
| 154 | in the os environment. |
||
| 155 | For naming standards use all capitals and start with 'TABPY_' |
||
| 156 | """ |
||
| 157 | self.settings = {} |
||
| 158 | self.subdirectory = "" |
||
| 159 | self.tabpy_state = None |
||
| 160 | self.python_service = None |
||
| 161 | self.credentials = {} |
||
| 162 | |||
| 163 | parser = configparser.ConfigParser(os.environ) |
||
| 164 | |||
| 165 | if os.path.isfile(config_file): |
||
| 166 | with open(config_file) as f: |
||
| 167 | parser.read_string(f.read()) |
||
| 168 | else: |
||
| 169 | logger.warning( |
||
| 170 | f'Unable to find config file at {config_file}, ' |
||
| 171 | 'using default settings.') |
||
| 172 | |||
| 173 | def set_parameter(settings_key, |
||
| 174 | config_key, |
||
| 175 | default_val=None): |
||
| 176 | key_is_set = False |
||
| 177 | |||
| 178 | if config_key is not None and\ |
||
| 179 | parser.has_section('TabPy') and\ |
||
| 180 | parser.has_option('TabPy', config_key): |
||
| 181 | self.settings[settings_key] = parser.get('TabPy', config_key) |
||
| 182 | key_is_set = True |
||
| 183 | logger.debug( |
||
| 184 | f'Parameter {settings_key} set to ' |
||
| 185 | f'"{self.settings[settings_key]}" ' |
||
| 186 | 'from config file or environment variable') |
||
| 187 | |||
| 188 | if not key_is_set and default_val is not None: |
||
| 189 | self.settings[settings_key] = default_val |
||
| 190 | key_is_set = True |
||
| 191 | logger.debug( |
||
| 192 | f'Parameter {settings_key} set to ' |
||
| 193 | f'"{self.settings[settings_key]}" ' |
||
| 194 | 'from default value') |
||
| 195 | |||
| 196 | if not key_is_set: |
||
| 197 | logger.debug( |
||
| 198 | f'Parameter {settings_key} is not set') |
||
| 199 | |||
| 200 | set_parameter(SettingsParameters.Port, ConfigParameters.TABPY_PORT, |
||
| 201 | default_val=9004) |
||
| 202 | set_parameter(SettingsParameters.ServerVersion, None, |
||
| 203 | default_val=__version__) |
||
| 204 | |||
| 205 | set_parameter(SettingsParameters.EvaluateTimeout, |
||
| 206 | ConfigParameters.TABPY_EVALUATE_TIMEOUT, |
||
| 207 | default_val=30) |
||
| 208 | |||
| 209 | try: |
||
| 210 | self.settings[SettingsParameters.EvaluateTimeout] = float( |
||
| 211 | self.settings[SettingsParameters.EvaluateTimeout]) |
||
| 212 | except ValueError: |
||
| 213 | logger.warning( |
||
| 214 | 'Evaluate timeout must be a float type. Defaulting ' |
||
| 215 | 'to evaluate timeout of 30 seconds.') |
||
| 216 | self.settings[SettingsParameters.EvaluateTimeout] = 30 |
||
| 217 | |||
| 218 | pkg_path = os.path.dirname(tabpy.__file__) |
||
| 219 | set_parameter(SettingsParameters.UploadDir, |
||
| 220 | ConfigParameters.TABPY_QUERY_OBJECT_PATH, |
||
| 221 | default_val=os.path.join(pkg_path, |
||
| 222 | 'tmp', 'query_objects')) |
||
| 223 | if not os.path.exists(self.settings[SettingsParameters.UploadDir]): |
||
| 224 | os.makedirs(self.settings[SettingsParameters.UploadDir]) |
||
| 225 | |||
| 226 | # set and validate transfer protocol |
||
| 227 | set_parameter(SettingsParameters.TransferProtocol, |
||
| 228 | ConfigParameters.TABPY_TRANSFER_PROTOCOL, |
||
| 229 | default_val='http') |
||
| 230 | self.settings[SettingsParameters.TransferProtocol] =\ |
||
| 231 | self.settings[SettingsParameters.TransferProtocol].lower() |
||
| 232 | |||
| 233 | set_parameter(SettingsParameters.CertificateFile, |
||
| 234 | ConfigParameters.TABPY_CERTIFICATE_FILE) |
||
| 235 | set_parameter(SettingsParameters.KeyFile, |
||
| 236 | ConfigParameters.TABPY_KEY_FILE) |
||
| 237 | self._validate_transfer_protocol_settings() |
||
| 238 | |||
| 239 | # if state.ini does not exist try and create it - remove |
||
| 240 | # last dependence on batch/shell script |
||
| 241 | set_parameter(SettingsParameters.StateFilePath, |
||
| 242 | ConfigParameters.TABPY_STATE_PATH, |
||
| 243 | default_val=os.path.join(pkg_path, 'tabpy_server')) |
||
| 244 | self.settings[SettingsParameters.StateFilePath] = os.path.realpath( |
||
| 245 | os.path.normpath( |
||
| 246 | os.path.expanduser( |
||
| 247 | self.settings[SettingsParameters.StateFilePath]))) |
||
| 248 | state_file_dir = self.settings[SettingsParameters.StateFilePath] |
||
| 249 | state_file_path = os.path.join(state_file_dir, 'state.ini') |
||
| 250 | if not os.path.isfile(state_file_path): |
||
| 251 | state_file_template_path = os.path.join( |
||
| 252 | pkg_path, 'tabpy_server', 'state.ini.template') |
||
| 253 | logger.debug(f'File {state_file_path} not found, creating from ' |
||
| 254 | f'template {state_file_template_path}...') |
||
| 255 | shutil.copy(state_file_template_path, state_file_path) |
||
| 256 | |||
| 257 | logger.info(f'Loading state from state file {state_file_path}') |
||
| 258 | tabpy_state = _get_state_from_file(state_file_dir) |
||
| 259 | self.tabpy_state = TabPyState( |
||
| 260 | config=tabpy_state, settings=self.settings) |
||
| 261 | |||
| 262 | self.python_service = PythonServiceHandler(PythonService()) |
||
| 263 | self.settings['compress_response'] = True |
||
| 264 | set_parameter(SettingsParameters.StaticPath, |
||
| 265 | ConfigParameters.TABPY_STATIC_PATH, |
||
| 266 | default_val='./') |
||
| 267 | self.settings[SettingsParameters.StaticPath] =\ |
||
| 268 | os.path.abspath(self.settings[SettingsParameters.StaticPath]) |
||
| 269 | logger.debug(f'Static pages folder set to ' |
||
| 270 | f'"{self.settings[SettingsParameters.StaticPath]}"') |
||
| 271 | |||
| 272 | # Set subdirectory from config if applicable |
||
| 273 | if tabpy_state.has_option("Service Info", "Subdirectory"): |
||
| 274 | self.subdirectory = "/" + \ |
||
| 275 | tabpy_state.get("Service Info", "Subdirectory") |
||
| 276 | |||
| 277 | # If passwords file specified load credentials |
||
| 278 | set_parameter(ConfigParameters.TABPY_PWD_FILE, |
||
| 279 | ConfigParameters.TABPY_PWD_FILE) |
||
| 280 | if ConfigParameters.TABPY_PWD_FILE in self.settings: |
||
| 281 | if not self._parse_pwd_file(): |
||
| 282 | msg = ('Failed to read passwords file ' |
||
| 283 | f'{self.settings[ConfigParameters.TABPY_PWD_FILE]}') |
||
| 284 | logger.critical(msg) |
||
| 285 | raise RuntimeError(msg) |
||
| 286 | else: |
||
| 287 | logger.info( |
||
| 288 | "Password file is not specified: " |
||
| 289 | "Authentication is not enabled") |
||
| 290 | |||
| 291 | features = self._get_features() |
||
| 292 | self.settings[SettingsParameters.ApiVersions] =\ |
||
| 293 | {'v1': {'features': features}} |
||
| 294 | |||
| 295 | set_parameter(SettingsParameters.LogRequestContext, |
||
| 296 | ConfigParameters.TABPY_LOG_DETAILS, |
||
| 297 | default_val='false') |
||
| 298 | self.settings[SettingsParameters.LogRequestContext] = ( |
||
| 299 | self.settings[SettingsParameters.LogRequestContext].lower() != |
||
| 300 | 'false') |
||
| 301 | call_context_state =\ |
||
| 302 | 'enabled' if self.settings[SettingsParameters.LogRequestContext]\ |
||
| 303 | else 'disabled' |
||
| 304 | logger.info(f'Call context logging is {call_context_state}') |
||
| 305 | |||
| 374 |