2023-08-22 15:34:45 +02:00
# Copyright Contributors to the osc project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
2006-10-10 16:04:34 +02:00
2013-04-09 12:51:28 +02:00
2023-08-22 15:34:45 +02:00
"""
This module handles configuration of osc .
Configuring osc from oscrc
- - - - - - - - - - - - - - - - - - - - - - - - - -
To configure osc from oscrc , do following : :
import osc . conf
# see ``get_config()`` documentation for available function arguments
# see ``oscrc(5)`` man page for oscrc configuration options
osc . conf . get_config ( )
2006-10-10 16:04:34 +02:00
2023-08-22 15:34:45 +02:00
Configuring osc from API
- - - - - - - - - - - - - - - - - - - - - - - -
2006-10-10 16:04:34 +02:00
2023-08-22 15:34:45 +02:00
To configure osc purely from the API ( without reading oscrc ) , do following : :
2006-10-10 16:04:34 +02:00
2023-08-22 15:34:45 +02:00
import osc . conf
2006-10-10 16:04:34 +02:00
2023-08-22 15:34:45 +02:00
# initialize the main config object
config = osc . conf . Options ( )
2006-10-10 16:04:34 +02:00
2023-08-22 15:34:45 +02:00
# configure host options for an apiurl
apiurl = osc . conf . sanitize_apiurl ( apiurl )
host_options = HostOptions ( apiurl = apiurl , username = . . . , _parent = config )
config . api_host_options [ apiurl ] = host_options
# set the default ``apiurl``
config . apiurl = . . .
# place the config object in `osc.conf`
osc . conf . config = config
# optional: enable http debugging according to the ``http_debug`` and ``http_full_debug`` options
from osc . connection import enable_http_debug
enable_http_debug ( osc . conf . config )
2006-10-10 16:04:34 +02:00
"""
2009-10-29 18:27:20 +01:00
2022-07-28 12:28:33 +02:00
2023-08-22 15:34:45 +02:00
import collections
2021-10-21 02:44:20 +02:00
import errno
2022-07-28 12:28:33 +02:00
import getpass
2023-08-22 15:34:45 +02:00
import http . client
2011-08-17 15:33:56 +02:00
import os
import re
2023-08-22 15:34:45 +02:00
import shutil
2011-08-17 15:33:56 +02:00
import sys
2023-08-22 15:34:45 +02:00
import textwrap
from io import BytesIO
2022-02-03 11:11:40 +01:00
from io import StringIO
from urllib . parse import urlsplit
2011-07-15 20:10:45 +02:00
2022-07-28 12:28:33 +02:00
from . import credentials
2013-04-09 11:35:53 +02:00
from . import OscConfigParser
2022-07-28 12:28:33 +02:00
from . import oscerr
2024-02-21 09:23:29 +01:00
from . output import tty
2023-08-22 15:34:45 +02:00
from . util import xdg
2022-07-28 12:28:33 +02:00
from . util . helper import raw_input
2023-08-22 15:34:45 +02:00
from . util . models import *
2022-07-28 12:28:33 +02:00
2006-10-10 16:04:34 +02:00
2009-09-04 19:48:53 +02:00
GENERIC_KEYRING = False
2009-05-11 09:46:01 +02:00
try :
2009-09-04 19:48:53 +02:00
import keyring
GENERIC_KEYRING = True
except :
2022-08-25 10:29:50 +02:00
pass
2006-10-10 16:04:34 +02:00
2011-08-17 15:33:56 +02:00
2023-08-22 15:34:45 +02:00
__all__ = [
" get_config " ,
" Options " ,
" HostOptions " ,
" Password " ,
" config " ,
]
2011-02-18 00:34:49 +01:00
2021-08-12 02:21:11 +02:00
2023-08-22 15:34:45 +02:00
class Password ( collections . UserString ) :
2022-08-22 13:36:52 +02:00
"""
2023-08-22 15:34:45 +02:00
Lazy password that wraps either a string or a function .
The result of the function gets returned any time the object is used as a string .
2022-08-22 13:36:52 +02:00
"""
2023-08-22 15:34:45 +02:00
def __init__ ( self , data ) :
self . _data = data
2022-08-22 13:36:52 +02:00
2023-08-22 15:34:45 +02:00
@property
def data ( self ) :
if callable ( self . _data ) :
# if ``data`` is a function, call it every time the string gets evaluated
# we use the password only from time to time to make a session cookie
# and there's no need to keep the password in program memory longer than necessary
result = self . _data ( )
2023-10-13 14:26:28 +02:00
# the function can also return a function, let's evaluate them recursively
while callable ( result ) :
result = result ( )
2023-08-22 15:34:45 +02:00
if result is None :
raise oscerr . OscIOError ( None , " Unable to retrieve password " )
return result
return self . _data
2022-08-22 13:36:52 +02:00
2023-08-22 15:34:45 +02:00
def __format__ ( self , format_spec ) :
if format_spec . endswith ( " s " ) :
return f " { self . __str__ ( ) : { format_spec } } "
return super ( ) . __format__ ( format_spec )
2022-08-22 13:36:52 +02:00
2024-01-22 16:28:28 +01:00
def encode ( self , * args , * * kwargs ) :
if sys . version_info < ( 3 , 8 ) :
# avoid returning the Password object on python < 3.8
return str ( self ) . encode ( * args , * * kwargs )
return super ( ) . encode ( * args , * * kwargs )
2006-10-10 16:04:34 +02:00
2023-08-22 15:34:45 +02:00
HttpHeader = NewType ( " HttpHeader " , Tuple [ str , str ] )
2021-02-11 10:58:40 +01:00
2010-03-28 21:13:04 +02:00
2023-08-22 15:34:45 +02:00
class OscOptions ( BaseModel ) :
2023-10-19 14:23:04 +02:00
def __init__ ( self , * args , * * kwargs ) :
super ( ) . __init__ ( * args , * * kwargs )
2024-01-03 21:21:38 +01:00
self . _allow_new_attributes = True
self . _extra_fields = { }
self . _allow_new_attributes = False
2023-10-19 14:23:04 +02:00
2023-08-22 15:34:45 +02:00
# compat function with the config dict
def _get_field_name ( self , name ) :
if name in self . __fields__ :
return name
2010-03-28 21:13:04 +02:00
2023-08-22 15:34:45 +02:00
for field_name , field in self . __fields__ . items ( ) :
ini_key = field . extra . get ( " ini_key " , None )
if ini_key == name :
return field_name
2014-11-20 17:09:53 +01:00
2023-08-22 15:34:45 +02:00
return None
2014-11-20 17:09:53 +01:00
2023-08-22 15:34:45 +02:00
# compat function with the config dict
def __getitem__ ( self , name ) :
field_name = self . _get_field_name ( name )
2023-10-19 14:23:04 +02:00
2023-10-23 22:14:32 +02:00
if field_name is None and not hasattr ( self , name ) :
2024-01-03 21:21:38 +01:00
return self . _extra_fields [ name ]
2023-10-19 14:23:04 +02:00
2023-10-23 22:14:32 +02:00
field_name = field_name or name
2023-08-22 15:34:45 +02:00
try :
return getattr ( self , field_name )
except AttributeError :
raise KeyError ( name )
# compat function with the config dict
def __setitem__ ( self , name , value ) :
field_name = self . _get_field_name ( name )
2023-10-19 14:23:04 +02:00
2023-10-23 22:14:32 +02:00
if field_name is None and not hasattr ( self , name ) :
2024-01-03 21:21:38 +01:00
self . _extra_fields [ name ] = value
2023-10-19 14:23:04 +02:00
return
2023-10-23 22:14:32 +02:00
field_name = field_name or name
2023-08-22 15:34:45 +02:00
setattr ( self , field_name , value )
# compat function with the config dict
def __contains__ ( self , name ) :
try :
self [ name ]
except KeyError :
return False
return True
# compat function with the config dict
def setdefault ( self , name , default = None ) :
field_name = self . _get_field_name ( name )
# we're ignoring ``default`` because the field always exists
return getattr ( self , field_name , None )
# compat function with the config dict
def get ( self , name , default = None ) :
try :
return self [ name ]
except KeyError :
return default
def set_value_from_string ( self , name , value ) :
field_name = self . _get_field_name ( name )
field = self . __fields__ [ field_name ]
if not isinstance ( value , str ) :
setattr ( self , field_name , value )
return
if not value . strip ( ) :
if field . is_optional :
2023-09-25 10:15:52 +02:00
setattr ( self , field_name , None )
2023-08-22 15:34:45 +02:00
return
if field . origin_type is Password :
value = Password ( value )
setattr ( self , field_name , value )
return
if field . type is List [ HttpHeader ] :
value = http . client . parse_headers ( BytesIO ( value . strip ( ) . encode ( " utf-8 " ) ) ) . items ( )
setattr ( self , field_name , value )
return
if field . origin_type is list :
# split list options into actual lists
value = re . split ( r " [, ]+ " , value )
setattr ( self , field_name , value )
return
if field . origin_type is bool :
if value . lower ( ) in [ " 1 " , " yes " , " true " , " on " ] :
value = True
setattr ( self , field_name , value )
return
if value . lower ( ) in [ " 0 " , " no " , " false " , " off " ] :
value = False
setattr ( self , field_name , value )
return
if field . origin_type is int :
value = int ( value )
setattr ( self , field_name , value )
return
setattr ( self , field_name , value )
class HostOptions ( OscOptions ) :
"""
Configuration options for individual apiurls .
"""
2009-08-20 21:28:05 +02:00
2023-08-22 15:34:45 +02:00
def __init__ ( self , _parent , * * kwargs ) :
super ( ) . __init__ ( _parent = _parent , * * kwargs )
apiurl : str = Field (
default = None ,
description = textwrap . dedent (
"""
URL to the API server .
"""
) ,
) # type: ignore[assignment]
aliases : List [ str ] = Field (
default = [ ] ,
description = textwrap . dedent (
"""
Aliases of the apiurl .
"""
) ,
) # type: ignore[assignment]
username : str = Field (
default = None ,
description = textwrap . dedent (
"""
Username for the apiurl .
"""
) ,
ini_key = " user " ,
) # type: ignore[assignment]
credentials_mgr_class : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
Fully qualified name of a class used to fetch a password .
"""
) ,
) # type: ignore[assignment]
password : Optional [ Password ] = Field (
default = None ,
description = textwrap . dedent (
"""
Password for the apiurl .
May be empty if the credentials manager fetches the password from a keyring or ` ` sshkey ` ` is used .
"""
) ,
ini_key = " pass " ,
) # type: ignore[assignment]
sshkey : Optional [ str ] = Field (
default = FromParent ( " sshkey " ) ,
description = textwrap . dedent (
"""
A pointer to public SSH key that corresponds with a private SSH used for authentication :
- path to the public SSH key
- public SSH key filename ( must be placed in ~ / . ssh )
NOTE : The private key may not be available on disk because it could be in a GPG keyring , on YubiKey or forwarded through SSH agent .
"""
) ,
) # type: ignore[assignment]
downloadurl : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
Redirect downloads of packages used during build to an alternative location .
This allows specifying a local mirror or a proxy , which can greatly improve download performance , latency and more .
"""
) ,
) # type: ignore[assignment]
cafile : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
The path to a file of concatenated CA certificates in PEM format .
If specified , the CA certificates from the path will be used to validate other peers ' certificates instead of the system-wide certificates.
"""
) ,
) # type: ignore[assignment]
capath : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
The path to a directory containing several CA certificates in PEM format .
If specified , the CA certificates from the path will be used to validate other peers ' certificates instead of the system-wide certificates.
"""
) ,
) # type: ignore[assignment]
sslcertck : bool = Field (
default = True ,
description = textwrap . dedent (
"""
Whether to validate SSL certificate of the server .
It is highly recommended to keep this option enabled .
"""
) ,
) # type: ignore[assignment]
allow_http : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Whether to allow plain HTTP connections .
Using HTTP is insecure because it sends passwords and session cookies in plain text .
It is highly recommended to keep this option disabled .
"""
) ,
) # type: ignore[assignment]
http_headers : List [ HttpHeader ] = Field (
default = [ ] ,
description = textwrap . dedent (
"""
Additional HTTP headers attached to each HTTP or HTTPS request .
The format is [ ( header - name , header - value ) ] .
"""
) ,
ini_description = textwrap . dedent (
"""
Additional HTTP headers attached to each request .
The format is HTTP headers separated with newlines .
Example : :
http_headers =
X - Header1 : Value1
X - Header2 : Value2
"""
) ,
ini_type = " newline-separated-list " ,
) # type: ignore[assignment]
trusted_prj : List [ str ] = Field (
default = [ ] ,
description = textwrap . dedent (
"""
List of names of the trusted projects .
The names can contain globs .
Please note that some repos may contain malicious packages that can compromise the build result or even your system !
"""
) ,
) # type: ignore[assignment]
disable_hdrmd5_check : bool = Field (
default = FromParent ( " disable_hdrmd5_check " ) ,
description = textwrap . dedent (
"""
Disable hdrmd5 checks of downloaded and cached packages in ` ` osc build ` ` .
It is recommended to keep the check enabled .
OBS builds the noarch packages once per binary arch .
Such noarch packages are supposed to be nearly identical across all build arches ,
any discrepancy in the payload and dependencies is considered a packaging bug .
But to guarantee that the local builds work identically to builds in OBS ,
using the arch - specific copy of the noarch package is required .
Unfortunatelly only one of the noarch packages gets distributed
and can be downloaded from a local mirror .
All other noarch packages are available through the OBS API only .
Since there is currently no information about hdrmd5 checksums of published noarch packages ,
we download them , verify hdrmd5 and re - download the package from OBS API on mismatch .
The same can also happen for architecture depend packages when someone is messing around
with the source history or the release number handling in a way that it is not increasing .
If you want to save some bandwidth and don ' t care about the exact rebuilds
you can turn this option on to disable hdrmd5 checks completely .
"""
) ,
) # type: ignore[assignment]
passx : Optional [ str ] = Field (
default = None ,
deprecated_text = textwrap . dedent (
"""
Option ' passx ' ( oscrc option [ $ apiurl ] / passx ) is deprecated .
You should be using the ' password ' option with ' credentials_mgr_class ' set to ' osc.credentials.ObfuscatedConfigFileCredentialsManager ' instead .
"""
) ,
) # type: ignore[assignment]
realname : Optional [ str ] = Field (
default = FromParent ( " realname " ) ,
description = textwrap . dedent (
"""
Name of the user passed to the ` ` vc ` ` tool via ` ` VC_REALNAME ` ` env variable .
"""
) ,
) # type: ignore[assignment]
email : Optional [ str ] = Field (
default = FromParent ( " email " ) ,
description = textwrap . dedent (
"""
Email of the user passed to the ` ` vc ` ` tool via ` ` VC_MAILADDR ` ` env variable .
"""
) ,
) # type: ignore[assignment]
class Options ( OscOptions ) :
"""
Main configuration options .
"""
2009-09-03 20:08:43 +02:00
2023-08-22 15:34:45 +02:00
# for internal use
conffile : Optional [ str ] = Field (
default = None ,
exclude = True ,
) # type: ignore[assignment]
api_host_options : Dict [ str , HostOptions ] = Field (
default = { } ,
description = textwrap . dedent (
"""
A dictionary that maps ` ` apiurl ` ` to ` ` HostOptions ` ` .
"""
) ,
ini_exclude = True ,
) # type: ignore[assignment]
@property
def apiurl_aliases ( self ) :
"""
Compute and return a dictionary that maps ` ` alias ` ` to ` ` apiurl ` ` .
"""
result = { }
for apiurl , opts in self . api_host_options . items ( ) :
result [ apiurl ] = apiurl
for alias in opts . aliases :
result [ alias ] = apiurl
return result
section_generic : str = Field (
default = " Generic options " ,
exclude = True ,
section = True ,
) # type: ignore[assignment]
apiurl : str = Field (
default = " https://api.opensuse.org " ,
description = textwrap . dedent (
"""
Default URL to the API server .
Credentials and other ` ` apiurl ` ` specific settings must be configured
in a ` ` [ $ apiurl ] ` ` config section or via API in an ` ` api_host_options ` ` entry .
"""
) ,
) # type: ignore[assignment]
section_auth : str = Field (
default = " Authentication options " ,
exclude = True ,
section = True ,
) # type: ignore[assignment]
username : Optional [ str ] = Field (
default = None ,
ini_key = " user " ,
deprecated_text = textwrap . dedent (
"""
Option ' username ' ( oscrc option [ global ] / user ) is deprecated .
You should be using username for each apiurl instead .
"""
) ,
) # type: ignore[assignment]
password : Optional [ Password ] = Field (
default = None ,
ini_key = " pass " ,
deprecated_text = textwrap . dedent (
"""
Option ' password ' ( oscrc option [ global ] / pass ) is deprecated .
You should be using password for each apiurl instead .
"""
) ,
) # type: ignore[assignment]
passx : Optional [ str ] = Field (
default = None ,
deprecated_text = textwrap . dedent (
"""
Option ' passx ' ( oscrc option [ global ] / passx ) is deprecated .
You should be using password for each apiurl instead .
"""
) ,
) # type: ignore[assignment]
sshkey : Optional [ str ] = Field (
default = None ,
description = HostOptions . __fields__ [ " sshkey " ] . description ,
) # type: ignore[assignment]
use_keyring : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Enable keyring as an option for storing passwords .
"""
) ,
) # type: ignore[assignment]
section_verbosity : str = Field (
default = " Verbosity options " ,
exclude = True ,
section = True ,
) # type: ignore[assignment]
2024-01-24 09:49:22 +01:00
quiet : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Reduce amount of printed information to bare minimum .
2024-01-24 09:49:24 +01:00
If enabled , automatically sets ` ` verbose ` ` to ` ` False ` ` .
2024-01-24 09:49:22 +01:00
"""
) ,
) # type: ignore[assignment]
2023-08-22 15:34:45 +02:00
verbose : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Increase amount of printed information to stdout .
2024-01-24 09:49:24 +01:00
Automatically set to ` ` False ` ` when ` ` quiet ` ` is enabled .
2023-08-22 15:34:45 +02:00
"""
) ,
2024-01-24 09:49:24 +01:00
get_callback = lambda conf , value : False if conf . quiet else value ,
2023-08-22 15:34:45 +02:00
) # type: ignore[assignment]
debug : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Print debug information to stderr .
"""
) ,
) # type: ignore[assignment]
http_debug : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Print HTTP traffic to stderr .
2024-01-24 09:49:24 +01:00
Automatically set to ` ` True ` ` when ` ` http_full_debug ` ` is enabled .
2023-08-22 15:34:45 +02:00
"""
) ,
2024-01-24 09:49:24 +01:00
get_callback = lambda conf , value : True if conf . http_full_debug else value ,
2023-08-22 15:34:45 +02:00
) # type: ignore[assignment]
http_full_debug : bool = Field (
default = False ,
description = textwrap . dedent (
"""
[ CAUTION ! ] Print HTTP traffic incl . authentication data to stderr .
2024-01-24 09:49:24 +01:00
If enabled , automatically sets ` ` http_debug ` ` to ` ` True ` ` .
2023-08-22 15:34:45 +02:00
"""
) ,
) # type: ignore[assignment]
post_mortem : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Jump into a debugger when an unandled exception occurs .
"""
) ,
) # type: ignore[assignment]
traceback : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Print full traceback to stderr when an unandled exception occurs .
"""
) ,
) # type: ignore[assignment]
show_download_progress : bool = Field (
default = True ,
description = textwrap . dedent (
"""
Show download progressbar .
"""
) ,
) # type: ignore[assignment]
section_connection : str = Field (
default = " Connection options " ,
exclude = True ,
section = True ,
) # type: ignore[assignment]
http_retries : int = Field (
default = 3 ,
description = textwrap . dedent (
"""
Number of retries on HTTP error .
"""
) ,
) # type: ignore[assignment]
cookiejar : str = Field (
default = os . path . join ( xdg . XDG_STATE_HOME , " osc " , " cookiejar " ) ,
description = textwrap . dedent (
"""
Path to a cookie jar that stores session cookies .
"""
) ,
) # type: ignore[assignment]
section_scm : str = Field (
default = " SCM options " ,
exclude = True ,
section = True ,
) # type: ignore[assignment]
realname : Optional [ str ] = Field (
default = None ,
description = HostOptions . __fields__ [ " realname " ] . description ,
) # type: ignore[assignment]
email : Optional [ str ] = Field (
default = None ,
description = HostOptions . __fields__ [ " email " ] . description ,
) # type: ignore[assignment]
local_service_run : bool = Field (
default = True ,
description = textwrap . dedent (
"""
Run local services during commit .
"""
) ,
) # type: ignore[assignment]
getpac_default_project : str = Field (
default = " openSUSE:Factory " ,
description = textwrap . dedent (
"""
The default project for ` ` osc getpac ` ` and ` ` osc bco ` ` .
The value is a space separated list of strings .
"""
) ,
) # type: ignore[assignment]
exclude_glob : List [ str ] = Field (
default = [ " .osc " , " CVS " , " .svn " , " .* " , " _linkerror " , " *~ " , " #*# " , " *.orig " , " *.bak " , " *.changes.vctmp.* " ] ,
description = textwrap . dedent (
"""
Space separated list of files ignored by SCM .
The files can contain globs .
"""
) ,
) # type: ignore[assignment]
exclude_files : List [ str ] = Field (
default = [ ] ,
description = textwrap . dedent (
"""
Files that match the listed glob patterns get skipped during checkout .
"""
) ,
) # type: ignore[assignment]
include_files : List [ str ] = Field (
default = [ ] ,
description = textwrap . dedent (
"""
Files that do not match the listed glob patterns get skipped during checkout .
The ` ` exclude_files ` ` option takes priority over ` ` include_files ` ` .
"""
) ,
) # type: ignore[assignment]
checkout_no_colon : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Use ' / ' as project separator instead the default ' : ' and create corresponding subdirs .
If enabled , it takes priority over the ` ` project_separator ` ` option .
"""
) ,
) # type: ignore[assignment]
project_separator : str = Field (
default = " : " ,
description = textwrap . dedent (
"""
Use the specified string to separate projects .
"""
) ,
) # type: ignore[assignment]
check_filelist : bool = Field (
default = True ,
description = textwrap . dedent (
"""
Check for untracked files and removed files before commit .
"""
) ,
) # type: ignore[assignment]
do_package_tracking : bool = Field (
default = True ,
description = textwrap . dedent (
"""
Track packages in parent project ' s .osc/_packages.
"""
) ,
) # type: ignore[assignment]
checkout_rooted : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Prevent checking out projects inside other projects or packages .
"""
) ,
) # type: ignore[assignment]
status_mtime_heuristic : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Consider a file with a modified mtime as modified .
"""
) ,
) # type: ignore[assignment]
linkcontrol : bool = Field (
default = False ,
description = textwrap . dedent (
# TODO: explain what linkcontrol does
"""
"""
) ,
) # type: ignore[assignment]
section_build : str = Field (
default = " Build options " ,
exclude = True ,
section = True ,
) # type: ignore[assignment]
build_repository : str = Field (
default = " openSUSE_Factory " ,
description = textwrap . dedent (
"""
The default repository used when the ` ` repository ` ` argument is omitted from ` ` osc build ` ` .
"""
) ,
) # type: ignore[assignment]
buildlog_strip_time : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Strip the build time from the build logs .
"""
) ,
) # type: ignore[assignment]
package_cache_dir : str = Field (
default = " /var/tmp/osbuild-packagecache " ,
description = textwrap . dedent (
"""
The directory where downloaded packages are stored . Must be writable by you .
"""
) ,
ini_key = " packagecachedir " ,
) # type: ignore[assignment]
no_verify : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Disable signature verification of packages used for build .
"""
) ,
) # type: ignore[assignment]
builtin_signature_check : bool = Field (
default = True ,
description = textwrap . dedent (
"""
Use the RPM ' s built-in package signature verification.
"""
) ,
) # type: ignore[assignment]
disable_hdrmd5_check : bool = Field (
default = False ,
description = HostOptions . __fields__ [ " disable_hdrmd5_check " ] . description ,
) # type: ignore[assignment]
section_request : str = Field (
default = " Request options " ,
exclude = True ,
section = True ,
) # type: ignore[assignment]
include_request_from_project : bool = Field (
default = True ,
description = textwrap . dedent (
"""
When querying requests , show also those that originate in the specified projects .
"""
) ,
) # type: ignore[assignment]
request_list_days : int = Field (
default = 0 ,
description = textwrap . dedent (
"""
Limit the age of requests shown with ` ` osc req list ` ` to the given number of days .
This is only the default that can be overridden with ` ` osc request list - D < VALUE > ` ` .
Use ` ` 0 ` ` for unlimited .
"""
) ,
) # type: ignore[assignment]
check_for_request_on_action : bool = Field (
default = True ,
description = textwrap . dedent (
"""
Check for pending requests after executing an action ( e . g . checkout , update , commit ) .
"""
) ,
) # type: ignore[assignment]
request_show_interactive : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Show requests in the interactive mode by default .
"""
) ,
) # type: ignore[assignment]
print_web_links : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Print links to Web UI that can be directly pasted to a web browser where possible .
"""
) ,
) # type: ignore[assignment]
request_show_source_buildstatus : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Print the buildstatus of the source package .
Works only with ` ` osc request show ` ` and the interactive review .
"""
) ,
) # type: ignore[assignment]
submitrequest_accepted_template : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
Template message for accepting a request .
Supported substitutions : ` ` % ( reqid ) s ` ` , ` ` % ( type ) s ` ` , ` ` % ( who ) s ` ` , ` ` % ( src_project ) s ` ` , ` ` % ( src_package ) s ` ` , ` ` % ( src_rev ) s ` ` , ` ` % ( tgt_project ) s ` ` , ` ` % ( tgt_package ) s ` `
Example : :
Hi % ( who ) s , your request % ( reqid ) s ( type : % ( type ) s ) for % ( tgt_project ) s / % ( tgt_package ) s has been accepted . Thank you for your contribution .
"""
) ,
) # type: ignore[assignment]
submitrequest_declined_template : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
Template message for declining a request .
Supported substitutions : ` ` % ( reqid ) s ` ` , ` ` % ( type ) s ` ` , ` ` % ( who ) s ` ` , ` ` % ( src_project ) s ` ` , ` ` % ( src_package ) s ` ` , ` ` % ( src_rev ) s ` ` , ` ` % ( tgt_project ) s ` ` , ` ` % ( tgt_package ) s ` `
Example : :
Hi % ( who ) s , your request % ( reqid ) s ( type : % ( type ) s ) for % ( tgt_project ) s / % ( tgt_package ) s has been declined because . . .
"""
) ,
) # type: ignore[assignment]
request_show_review : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Review requests interactively .
"""
) ,
) # type: ignore[assignment]
review_inherit_group : bool = Field (
default = False ,
description = textwrap . dedent (
"""
If a review was accepted in interactive mode and a group was specified ,
the review will be accepted for this group .
"""
) ,
) # type: ignore[assignment]
submitrequest_on_accept_action : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
What to do with the source package if the request has been accepted .
If nothing is specified the API default is used .
Choices : cleanup , update , noupdate
"""
) ,
) # type: ignore[assignment]
# XXX: let's hide attributes from documentation as it is not clear if anyone uses them and should them change from their defaults
# section_obs_attributes: str = Field(
# default="OBS attributes",
# exclude=True,
# section=True,
# ) # type: ignore[assignment]
maintained_attribute : str = Field (
default = " OBS:Maintained " ,
) # type: ignore[assignment]
maintenance_attribute : str = Field (
default = " OBS:MaintenanceProject " ,
) # type: ignore[assignment]
maintained_update_project_attribute : str = Field (
default = " OBS:UpdateProject " ,
) # type: ignore[assignment]
section_build_tool : str = Field (
default = " Build tool options " ,
exclude = True ,
section = True ,
) # type: ignore[assignment]
build_jobs : Optional [ int ] = Field (
default = os . cpu_count ,
description = textwrap . dedent (
"""
The number of parallel processes during the build .
Defaults to the number of available CPU threads .
Passed as ` ` - - jobs ` ` to the build tool .
"""
) ,
ini_key = " build-jobs " ,
) # type: ignore[assignment]
2023-09-26 13:37:30 +02:00
vm_type : Optional [ str ] = Field (
2023-08-22 15:34:45 +02:00
default = None ,
description = textwrap . dedent (
"""
Type of the build environment passed the build tool as the ` ` - - vm - type ` ` option :
2023-09-26 13:39:23 +02:00
- < empty > chroot build
- kvm KVM VM build ( rootless , needs build - device , build - swap , build - memory )
- xen XEN VM build ( needs build - device , build - swap , build - memory )
- qemu [ EXPERIMENTAL ] QEMU VM build
- lxc [ EXPERIMENTAL ] LXC build
- uml
- zvm
- openstack
- ec2
- docker
- podman ( rootless )
- pvm
- nspawn
See ` ` build - - help ` ` for more details about supported options .
2023-08-22 15:34:45 +02:00
"""
) ,
ini_key = " build-type " ,
) # type: ignore[assignment]
build_memory : Optional [ int ] = Field (
default = None ,
description = textwrap . dedent (
"""
The amount of RAM ( in MiB ) assigned to a build VM .
"""
) ,
ini_key = " build-memory " ,
) # type: ignore[assignment]
build_root : str = Field (
2023-09-25 14:56:50 +02:00
default = " /var/tmp/build-root %(dash_user)s / %(repo)s - %(arch)s " ,
2023-08-22 15:34:45 +02:00
description = textwrap . dedent (
"""
Path to the build root directory .
2023-09-25 14:56:50 +02:00
Supported substitutions : ` ` % ( repo ) s ` ` , ` ` % ( arch ) s ` ` , ` ` % ( project ) s ` ` , ` ` % ( package ) s ` ` , ` ` % ( apihost ) s ` ` , ` ` % ( user ) s ` ` , ` ` % ( dash_user ) s ` `
where : :
- ` ` apihost ` ` is the hostname extracted from the currently used ` ` apiurl ` ` .
- ` ` dash_user ` ` is the username prefixed with a dash . If ` ` user ` ` is empty , ` ` dash_user ` ` is also empty .
2023-08-22 15:34:45 +02:00
2023-09-25 14:24:57 +02:00
NOTE : The configuration holds the original unexpanded string . Call ` ` osc . build . get_build_root ( ) ` ` with proper arguments to retrieve an actual path .
2023-08-22 15:34:45 +02:00
Passed as ` ` - - root < VALUE > ` ` to the build tool .
"""
) ,
ini_key = " build-root " ,
) # type: ignore[assignment]
build_shell_after_fail : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Start a shell prompt in the build environment if a build fails .
Passed as ` ` - - shell - after - fail ` ` to the build tool .
"""
) ,
ini_key = " build-shell-after-fail " ,
) # type: ignore[assignment]
build_uid : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
Numeric uid : gid to use for the abuild user .
Neither of the values should be 0.
This is useful if you are hacking in the buildroot .
This must be set to the same value if the buildroot is re - used .
Passed as ` ` - - uid < VALUE > ` ` to the build tool .
"""
) ,
ini_key = " build-uid " ,
) # type: ignore[assignment]
build_vm_kernel : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
The kernel used in a VM build .
"""
) ,
ini_key = " build-kernel " ,
) # type: ignore[assignment]
build_vm_initrd : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
The initrd used in a VM build .
"""
) ,
ini_key = " build-initrd " ,
) # type: ignore[assignment]
build_vm_disk : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
The disk image used as rootfs in a VM build .
Passed as ` ` - - vm - disk < VALUE > ` ` to the build tool .
"""
) ,
ini_key = " build-device " ,
) # type: ignore[assignment]
build_vm_disk_filesystem : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
The file system type of the disk image used as rootfs in a VM build .
Supported values : ext3 ( default ) , ext4 , xfs , reiserfs , btrfs .
Passed as ` ` - - vm - disk - filesystem < VALUE > ` ` to the build tool .
"""
) ,
ini_key = " build-vmdisk-filesystem " ,
) # type: ignore[assignment]
build_vm_disk_size : Optional [ int ] = Field (
default = None ,
description = textwrap . dedent (
"""
The size of the disk image ( in MiB ) used as rootfs in a VM build .
Passed as ` ` - - vm - disk - size ` ` to the build tool .
"""
) ,
ini_key = " build-vmdisk-rootsize " ,
) # type: ignore[assignment]
build_vm_swap : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
Path to the disk image used as a swap for VM builds .
Passed as ` ` - - swap ` ` to the build tool .
"""
) ,
ini_key = " build-swap " ,
) # type: ignore[assignment]
build_vm_swap_size : Optional [ int ] = Field (
default = None ,
description = textwrap . dedent (
"""
The size of the disk image ( in MiB ) used as swap in a VM build .
Passed as ` ` - - vm - swap - size ` ` to the build tool .
"""
) ,
ini_key = " build-vmdisk-swapsize " ,
) # type: ignore[assignment]
build_vm_user : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
The username of a user used to run QEMU / KVM process .
"""
) ,
ini_key = " build-vm-user " ,
) # type: ignore[assignment]
icecream : int = Field (
default = 0 ,
description = textwrap . dedent (
"""
Use Icecream distributed compiler .
The value represents the number of parallel build jobs .
Passed as ` ` - - icecream < VALUE > ` ` to the build tool .
"""
) ,
) # type: ignore[assignment]
ccache : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Enable compiler cache ( ccache ) in build roots .
Passed as ` ` - - ccache ` ` to the build tool .
"""
) ,
) # type: ignore[assignment]
sccache : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Enable shared compilation cache ( sccache ) in build roots . Conflicts with ` ` ccache ` ` .
Passed as ` ` - - sccache ` ` to the build tool .
"""
) ,
) # type: ignore[assignment]
sccache_uri : Optional [ str ] = Field (
default = None ,
description = textwrap . dedent (
"""
Optional URI for sccache storage .
Supported URIs depend on the sccache configuration .
The URI allows the following substitutions :
- ` ` { pkgname } ` ` : name of the package to be build
Examples :
- file : / / / var / tmp / osbuild - sccache - { pkgname } . tar . lzop
- file : / / / var / tmp / osbuild - sccache - { pkgname } . tar
- redis : / / 127.0 .0 .1 : 6379
Passed as ` ` - - sccache - uri < VALUE > ` ` to the build tool .
"""
) ,
) # type: ignore[assignment]
no_preinstallimage : bool = Field (
default = False ,
description = textwrap . dedent (
"""
Do not use preinstall images to initialize build roots .
"""
) ,
) # type: ignore[assignment]
extra_pkgs : List [ str ] = Field (
default = [ ] ,
description = textwrap . dedent (
"""
Extra packages to install into the build root when building packages locally with ` ` osc build ` ` .
This corresponds to ` ` osc build - x pkg1 - x pkg2 . . . ` ` .
The configured values can be overriden from the command - line with ` ` - x ' ' ` ` .
This global setting may leads to dependency problems when the base distro is not providing the package .
Therefore using server - side ` ` cli_debug_packages ` ` option instead is recommended .
Passed as ` ` - - extra - packs < VALUE > ` ` to the build tool .
"""
) ,
ini_key = " extra-pkgs " ,
) # type: ignore[assignment]
section_programs : str = Field (
default = " Paths to programs " ,
exclude = True ,
section = True ,
) # type: ignore[assignment]
build_cmd : str = Field (
default =
shutil . which ( " build " , path = " /usr/bin:/usr/lib/build:/usr/lib/obs-build " )
or shutil . which ( " obs-build " , path = " /usr/bin:/usr/lib/build:/usr/lib/obs-build " )
or " /usr/bin/build " ,
description = textwrap . dedent (
"""
Path to the ' build ' tool .
"""
) ,
ini_key = " build-cmd " ,
) # type: ignore[assignment]
download_assets_cmd : str = Field (
default =
shutil . which ( " download_assets " , path = " /usr/lib/build:/usr/lib/obs-build " )
or " /usr/lib/build/download_assets " ,
description = textwrap . dedent (
"""
Path to the ' download_assets ' tool used for downloading assets in SCM / Git based builds .
"""
) ,
ini_key = " download-assets-cmd " ,
) # type: ignore[assignment]
vc_cmd : str = Field (
default = shutil . which ( " vc " , path = " /usr/lib/build:/usr/lib/obs-build " ) or " /usr/lib/build/vc " ,
description = textwrap . dedent (
"""
Path to the ' vc ' tool .
"""
) ,
ini_key = " vc-cmd " ,
) # type: ignore[assignment]
su_wrapper : str = Field (
default = " sudo " ,
description = textwrap . dedent (
"""
The wrapper to call build tool as root ( sudo , su - , . . . ) .
If empty , the build tool runs under the current user wich works only with KVM at this moment .
"""
) ,
ini_key = " su-wrapper " ,
) # type: ignore[assignment]
# Generate rst from a model. Use it to generate man page in sphinx.
# This IS NOT a public API.
def _model_to_rst ( cls , title = None , description = None , sections = None , output_file = None ) :
def header ( text , char = " - " ) :
result = f " { text } \n "
result + = f " { ' ' : { char } ^ { len ( text ) } } "
return result
def bold ( text ) :
text = text . replace ( r " * " , r " \ * " )
return f " ** { text } ** "
def italic ( text ) :
text = text . replace ( r " * " , r " \ * " )
return f " * { text } * "
def get_type ( name , field ) :
ini_type = field . extra . get ( " ini_type " , None )
if ini_type :
return ini_type
if field . origin_type . __name__ == " list " :
return " space-separated-list "
return field . origin_type . __name__
def get_default ( name , field ) :
if field . default is None :
return None
2023-12-01 16:20:55 +01:00
if field . default_is_lazy :
# lazy default may return different results under different circumstances -> return nothing
return None
2023-08-22 15:34:45 +02:00
ini_type = field . extra . get ( " ini_type " , None )
if ini_type :
return None
if isinstance ( field . default , FromParent ) :
return None
origin_type = field . origin_type
if origin_type == bool :
return str ( int ( field . default ) )
if origin_type == int :
return str ( field . default )
if origin_type == list :
if not field . default :
return None
default_str = " " . join ( field . default )
return f ' " { default_str } " '
if origin_type == str :
return f ' " { field . default } " '
# TODO:
raise Exception ( f " { name } { field } , { origin_type } " )
result = [ ]
if title :
result . append ( header ( title , char = " = " ) )
result . append ( " " )
if description :
result . append ( description )
result . append ( " " )
for name , field in cls . __fields__ . items ( ) :
extra = field . extra
is_section_header = extra . get ( " section " , False )
if is_section_header :
result . append ( header ( field . default ) )
result . append ( " " )
continue
exclude = extra . get ( " ini_exclude " , False ) or field . exclude
exclude | = field . description is None
if exclude :
continue
ini_key = extra . get ( " ini_key " , name )
2024-01-06 09:54:57 +01:00
x = f " { bold ( ini_key ) } : { get_type ( name , field ) } "
2023-08-22 15:34:45 +02:00
default = get_default ( name , field )
if default :
2024-01-06 09:54:57 +01:00
x + = f " = { italic ( default ) } "
2023-08-22 15:34:45 +02:00
result . append ( x )
result . append ( " " )
desc = extra . get ( " ini_description " , None ) or field . description or " "
for line in desc . splitlines ( ) :
result . append ( f " { line } " )
result . append ( " " )
sections = sections or { }
for section_name , section_class in sections . items ( ) :
result . append ( header ( section_name ) )
result . append ( _model_to_rst ( section_class ) )
2009-08-20 21:28:05 +02:00
2023-08-22 15:34:45 +02:00
if output_file :
with open ( output_file , " w " , encoding = " utf-8 " ) as f :
f . write ( " \n " . join ( result ) )
return " \n " . join ( result )
2022-04-08 17:38:51 +02:00
2010-12-27 23:03:17 +01:00
2023-08-22 15:34:45 +02:00
# being global to this module, this object can be accessed from outside
# it will hold the parsed configuration
config = Options ( )
2008-07-30 18:45:00 +02:00
2009-08-20 21:28:05 +02:00
2023-08-22 15:34:45 +02:00
general_opts = [ field . extra . get ( " ini_key " , field . name ) for field in Options . __fields__ . values ( ) if not field . exclude ]
api_host_options = [ field . extra . get ( " ini_key " , field . name ) for field in HostOptions . __fields__ . values ( ) if not field . exclude ]
2009-08-20 21:28:05 +02:00
2023-08-22 15:34:45 +02:00
# HACK: Proxy object that modifies field defaults in the Options class; needed for compatibility with the old DEFAULTS dict; prevents breaking osc-plugin-collab
# This IS NOT a public API.
class Defaults :
def _get_field ( self , name ) :
if hasattr ( Options , name ) :
return getattr ( Options , name )
2010-12-01 10:22:53 +01:00
2023-08-22 15:34:45 +02:00
for i in dir ( Options ) :
field = getattr ( Options , i )
if field . extra . get ( " ini_key " , None ) == name :
return field
2010-08-12 21:34:08 +02:00
2023-08-22 15:34:45 +02:00
return None
2009-08-20 21:28:05 +02:00
2023-08-22 15:34:45 +02:00
def __getitem__ ( self , name ) :
field = self . _get_field ( name )
result = field . default
if field . type is List [ str ] :
# return list as a string so we can append another string to it
return " , " . join ( result )
return result
2009-08-20 21:28:05 +02:00
2023-08-22 15:34:45 +02:00
def __setitem__ ( self , name , value ) :
obj = Options ( )
obj . set_value_from_string ( name , value )
field = self . _get_field ( name )
field . default = obj [ name ]
2009-09-18 03:10:41 +02:00
2023-08-22 15:34:45 +02:00
DEFAULTS = Defaults ( )
2009-12-19 14:44:51 +01:00
2010-11-14 18:32:02 +01:00
2023-08-22 15:34:45 +02:00
new_conf_template = """
# see oscrc(5) man page for the full list of available options
2010-11-14 18:32:02 +01:00
2023-08-22 15:34:45 +02:00
[ general ]
2010-02-11 01:47:47 +01:00
2023-08-22 15:34:45 +02:00
# Default URL to the API server.
# Credentials and other `apiurl` specific settings must be configured in a `[$apiurl]` config section.
apiurl = % ( apiurl ) s
2012-04-27 15:04:06 +02:00
2009-02-24 00:29:32 +01:00
[ % ( apiurl ) s ]
2023-08-22 15:34:45 +02:00
# aliases=
# user=
# pass=
# credentials_mgr_class=osc.credentials...
2006-10-10 16:04:34 +02:00
"""
2011-08-17 15:33:56 +02:00
account_not_configured_text = """
2006-10-10 16:04:34 +02:00
Your user account / password are not configured yet .
You will be asked for them below , and they will be stored in
% s for future use .
"""
config_incomplete_text = """
Your configuration file % s is not complete .
Make sure that it has a [ general ] section .
( You can copy & paste the below . Some commented defaults are shown . )
"""
2008-08-07 19:14:26 +02:00
config_missing_apiurl_text = """
2022-04-07 09:09:28 +02:00
The apiurl \' %s \' does not exist in the config file. Please enter
2008-08-07 19:14:26 +02:00
your credentials for this apiurl .
"""
2011-08-17 15:33:56 +02:00
2023-08-22 15:34:45 +02:00
def sanitize_apiurl ( apiurl ) :
"""
Sanitize apiurl :
- add https : / / schema if apiurl contains none
- strip trailing slashes
"""
return urljoin ( * parse_apisrv_url ( None , apiurl ) )
2007-04-25 12:24:51 +02:00
def parse_apisrv_url ( scheme , apisrv ) :
if apisrv . startswith ( ' http:// ' ) or apisrv . startswith ( ' https:// ' ) :
2015-08-20 14:45:02 +02:00
url = apisrv
2022-08-29 12:56:57 +02:00
elif scheme is not None :
2015-08-20 14:45:02 +02:00
url = scheme + apisrv
2009-02-24 02:29:17 +01:00
else :
2024-01-06 09:54:57 +01:00
url = f " https:// { apisrv } "
2015-08-20 14:45:02 +02:00
scheme , url , path = urlsplit ( url ) [ 0 : 3 ]
return scheme , url , path . rstrip ( ' / ' )
2011-08-17 15:33:56 +02:00
2007-04-25 12:24:51 +02:00
2013-10-26 01:15:18 +02:00
def urljoin ( scheme , apisrv , path = ' ' ) :
2024-01-06 09:54:57 +01:00
return f " { scheme } :// { apisrv } " + path
2009-02-24 00:29:32 +01:00
2011-08-17 15:33:56 +02:00
2010-09-01 15:53:37 +02:00
def is_known_apiurl ( url ) :
2022-01-24 08:57:53 +01:00
""" returns ``True`` if url is a known apiurl """
2023-08-22 15:34:45 +02:00
apiurl = sanitize_apiurl ( url )
2011-08-17 15:33:56 +02:00
return apiurl in config [ ' api_host_options ' ]
2010-09-01 15:53:37 +02:00
2013-10-26 01:15:18 +02:00
def extract_known_apiurl ( url ) :
"""
Return longest prefix of given url that is known apiurl ,
None if there is no known apiurl that is prefix of given url .
"""
scheme , host , path = parse_apisrv_url ( None , url )
p = path . split ( ' / ' )
while p :
apiurl = urljoin ( scheme , host , ' / ' . join ( p ) )
if apiurl in config [ ' api_host_options ' ] :
return apiurl
p . pop ( )
return None
2008-08-20 12:41:10 +02:00
def get_apiurl_api_host_options ( apiurl ) :
"""
2022-01-24 08:57:53 +01:00
Returns all apihost specific options for the given apiurl , ` ` None ` ` if
no such specific options exist .
2008-08-20 12:41:10 +02:00
"""
# FIXME: in A Better World (tm) there was a config object which
# knows this instead of having to extract it from a url where it
# had been mingled into before. But this works fine for now.
2009-02-24 00:29:32 +01:00
2023-08-22 15:34:45 +02:00
apiurl = sanitize_apiurl ( apiurl )
2010-09-01 15:53:37 +02:00
if is_known_apiurl ( apiurl ) :
2009-02-24 00:29:32 +01:00
return config [ ' api_host_options ' ] [ apiurl ]
2024-01-06 09:54:57 +01:00
raise oscerr . ConfigMissingApiurl ( f ' missing credentials for apiurl: \' { apiurl } \' ' ,
2010-09-01 15:53:37 +02:00
' ' , apiurl )
2008-08-20 12:41:10 +02:00
2011-08-17 15:33:56 +02:00
2008-03-15 23:51:37 +01:00
def get_apiurl_usr ( apiurl ) :
"""
returns the user for this host - if this host does not exist in the
2008-08-20 11:45:49 +02:00
internal api_host_options the default user is returned .
2008-03-15 23:51:37 +01:00
"""
2008-08-20 12:41:10 +02:00
# FIXME: maybe there should be defaults not just for the user but
# for all apihost specific options. The ConfigParser class
# actually even does this but for some reason we don't use it
# (yet?).
try :
return get_apiurl_api_host_options ( apiurl ) [ ' user ' ]
except KeyError :
2022-09-12 13:43:10 +02:00
print ( ' no specific section found in config file for host of [ \' %s \' ] - using default user: \' %s \' '
% ( apiurl , config [ ' user ' ] ) , file = sys . stderr )
2008-03-18 14:51:57 +01:00
return config [ ' user ' ]
2008-03-15 23:51:37 +01:00
2011-08-17 15:33:56 +02:00
2008-03-15 23:51:37 +01:00
def get_configParser ( conffile = None , force_read = False ) :
"""
Returns an ConfigParser ( ) object . After its first invocation the
ConfigParser object is stored in a method attribute and this attribute
is returned unless you pass force_read = True .
"""
2017-10-27 11:29:00 +02:00
if not conffile :
conffile = identify_conf ( )
2008-03-15 23:51:37 +01:00
conffile = os . path . expanduser ( conffile )
2011-08-17 15:33:56 +02:00
if ' conffile ' not in get_configParser . __dict__ :
2010-03-07 22:50:11 +01:00
get_configParser . conffile = conffile
2011-08-17 15:33:56 +02:00
if force_read or ' cp ' not in get_configParser . __dict__ or conffile != get_configParser . conffile :
2023-08-22 15:34:45 +02:00
get_configParser . cp = OscConfigParser . OscConfigParser ( )
2008-03-15 23:51:37 +01:00
get_configParser . cp . read ( conffile )
2010-03-07 22:50:11 +01:00
get_configParser . conffile = conffile
2008-03-15 23:51:37 +01:00
return get_configParser . cp
2011-08-17 15:33:56 +02:00
2011-11-18 22:27:38 +01:00
def write_config ( fname , cp ) :
""" write new configfile in a safe way """
2011-11-18 22:32:10 +01:00
if os . path . exists ( fname ) and not os . path . isfile ( fname ) :
# only write to a regular file
return
2021-12-06 14:23:51 +01:00
# config file is behind a symlink
# resolve the symlink and continue writing the config as usual
if os . path . islink ( fname ) :
fname = os . readlink ( fname )
# create directories to the config file (if they don't exist already)
2022-07-24 14:36:23 +02:00
fdir = os . path . dirname ( fname )
if fdir :
2021-12-06 14:23:51 +01:00
try :
2022-07-24 14:36:23 +02:00
os . makedirs ( fdir , mode = 0o700 )
2021-12-06 14:23:51 +01:00
except OSError as e :
if e . errno != errno . EEXIST :
raise
2024-01-06 09:54:57 +01:00
with open ( f " { fname } .new " , ' w ' ) as f :
2011-11-18 22:27:38 +01:00
cp . write ( f , comments = True )
try :
2024-01-06 09:54:57 +01:00
os . rename ( f " { fname } .new " , fname )
2013-04-09 12:45:16 +02:00
os . chmod ( fname , 0o600 )
2011-11-18 22:27:38 +01:00
except :
2024-01-06 09:54:57 +01:00
if os . path . exists ( f " { fname } .new " ) :
os . unlink ( f " { fname } .new " )
2011-11-18 22:27:38 +01:00
raise
2019-08-29 11:35:34 +02:00
def config_set_option ( section , opt , val = None , delete = False , update = True , creds_mgr_descr = None , * * kwargs ) :
2010-03-07 22:50:11 +01:00
"""
Sets a config option . If val is not specified the current / default value is
returned . If val is specified , opt is set to val and the new value is returned .
2022-01-24 08:57:53 +01:00
If an option was modified get_config is called with ` ` * * kwargs ` ` unless update is set
to ` ` False ` ` ( ` ` override_conffile ` ` defaults to ` ` config [ ' conffile ' ] ` ` ) .
If val is not specified and delete is ` ` True ` ` then the option is removed from the
2010-03-07 22:50:11 +01:00
config / reset to the default value .
"""
cp = get_configParser ( config [ ' conffile ' ] )
2023-08-22 15:34:45 +02:00
2010-06-23 14:20:56 +02:00
if section != ' general ' :
2023-10-23 22:14:32 +02:00
section = config . apiurl_aliases . get ( section , section )
2013-10-26 01:15:18 +02:00
scheme , host , path = \
2010-06-23 14:20:56 +02:00
parse_apisrv_url ( config . get ( ' scheme ' , ' https ' ) , section )
2013-10-26 01:15:18 +02:00
section = urljoin ( scheme , host , path )
2010-06-23 14:20:56 +02:00
sections = { }
for url in cp . sections ( ) :
if url == ' general ' :
sections [ url ] = url
else :
2013-10-26 01:15:18 +02:00
scheme , host , path = \
2010-06-23 14:20:56 +02:00
parse_apisrv_url ( config . get ( ' scheme ' , ' https ' ) , url )
2013-10-26 01:15:18 +02:00
apiurl = urljoin ( scheme , host , path )
2010-06-23 14:20:56 +02:00
sections [ apiurl ] = url
2010-03-08 14:09:15 +01:00
section = sections . get ( section . rstrip ( ' / ' ) , section )
2022-09-12 14:15:34 +02:00
if section not in cp . sections ( ) :
2024-01-06 09:54:57 +01:00
raise oscerr . ConfigError ( f ' unknown section \' { section } \' ' , config [ ' conffile ' ] )
2022-09-12 14:15:34 +02:00
if section == ' general ' and opt not in general_opts or \
section != ' general ' and opt not in api_host_options :
2024-01-06 09:54:57 +01:00
raise oscerr . ConfigError ( f ' unknown config option \' { opt } \' ' , config [ ' conffile ' ] )
2021-07-14 11:19:08 +02:00
if not val and not delete and opt == ' pass ' and creds_mgr_descr is not None :
# change password store
creds_mgr = _get_credentials_manager ( section , cp )
user = _extract_user_compat ( cp , section , creds_mgr )
2022-04-04 10:15:35 +02:00
val = creds_mgr . get_password ( section , user , defer = False )
2021-07-14 11:19:08 +02:00
2010-03-07 22:50:11 +01:00
run = False
if val :
2019-08-29 11:35:34 +02:00
if opt == ' pass ' :
creds_mgr = _get_credentials_manager ( section , cp )
2019-08-29 14:27:30 +02:00
user = _extract_user_compat ( cp , section , creds_mgr )
2019-08-29 11:35:34 +02:00
old_pw = creds_mgr . get_password ( section , user , defer = False )
try :
creds_mgr . delete_password ( section , user )
if creds_mgr_descr :
creds_mgr_new = creds_mgr_descr . create ( cp )
else :
creds_mgr_new = creds_mgr
creds_mgr_new . set_password ( section , user , val )
write_config ( config [ ' conffile ' ] , cp )
opt = credentials . AbstractCredentialsManager . config_entry
old_pw = None
finally :
if old_pw is not None :
creds_mgr . set_password ( section , user , old_pw )
# not nice, but needed if the Credentials Manager will change
# something in cp
write_config ( config [ ' conffile ' ] , cp )
else :
cp . set ( section , opt , val )
write_config ( config [ ' conffile ' ] , cp )
2010-03-07 22:50:11 +01:00
run = True
2019-08-29 11:35:34 +02:00
elif delete and ( cp . has_option ( section , opt ) or opt == ' pass ' ) :
if opt == ' pass ' :
creds_mgr = _get_credentials_manager ( section , cp )
2021-07-14 11:31:56 +02:00
user = _extract_user_compat ( cp , section , creds_mgr )
2019-08-29 11:35:34 +02:00
creds_mgr . delete_password ( section , user )
else :
cp . remove_option ( section , opt )
2010-03-07 22:50:11 +01:00
write_config ( config [ ' conffile ' ] , cp )
run = True
if run and update :
2022-08-25 10:29:50 +02:00
kw = {
' override_conffile ' : config [ ' conffile ' ] ,
' override_no_keyring ' : config [ ' use_keyring ' ] ,
}
2010-03-07 22:50:11 +01:00
kw . update ( kwargs )
get_config ( * * kw )
if cp . has_option ( section , opt ) :
return ( opt , cp . get ( section , opt , raw = True ) )
return ( opt , None )
2008-03-15 23:51:37 +01:00
2022-09-12 13:43:10 +02:00
2019-08-29 14:27:30 +02:00
def _extract_user_compat ( cp , section , creds_mgr ) :
"""
This extracts the user either from the ConfigParser or
the creds_mgr . Only needed for deprecated Gnome Keyring
"""
user = cp . get ( section , ' user ' )
if user is None and hasattr ( creds_mgr , ' get_user ' ) :
user = creds_mgr . get_user ( section )
return user
2022-09-12 13:43:10 +02:00
2019-08-27 15:08:38 +02:00
def write_initial_config ( conffile , entries , custom_template = ' ' , creds_mgr_descriptor = None ) :
Merged revisions 3774-3775,3779,3781-3782,3787,3789-3793,3798,3802,3805,3817-3822,3827,3829-3830,3837-3839,3841-3842,3848-3850 via svnmerge from
https://forgesvn1.novell.com/svn/opensuse/branches/buildservice/osc-exception-handling
........
r3774 | poeml | 2008-04-22 17:39:45 +0200 (Tue, 22 Apr 2008) | 3 lines
A first draft on implement systematic exception handling:
Add errors.py with some exceptions defined, and babysitter.py to handle them
........
r3775 | poeml | 2008-04-22 22:34:12 +0200 (Tue, 22 Apr 2008) | 9 lines
- new global options:
--debugger jump into the debugger before executing anything
--post-mortem jump into the debugger in case of errors
-t, --traceback print call trace in case of errors
- traceback and post_mortem can also be set in .oscrc.
- catch more errors (HTTPError).
- make config accessible from outside of the Osc instance, by making it a class
attribute
........
r3779 | poeml | 2008-04-23 00:55:49 +0200 (Wed, 23 Apr 2008) | 5 lines
- new global option:
-d, --debug print info useful for debugging
- catch some more errors (HTTPError), with OscHTTPError which isn't very
advanced yet.
........
r3781 | Marcus_H | 2008-04-23 01:02:00 +0200 (Wed, 23 Apr 2008) | 2 lines
- added OscConfigError class (just for testing).
- small change in the signature of the OscBaseError constructor (actually we should get rid of the 'args' tuple because it will be deprecated sooner or later
........
r3782 | Marcus_H | 2008-04-23 02:02:13 +0200 (Wed, 23 Apr 2008) | 2 lines
- access the prg.conf.config dict in a save way - this way we avoid AttributeErrors if the prg.conf.config dict doesn't exist
- in case of an configparser error we have to use the prg.options object directly (this was removed in r3781 by accident)
........
r3787 | poeml | 2008-04-23 09:23:56 +0200 (Wed, 23 Apr 2008) | 4 lines
- remove local exception handling from do_req
- for HTTPError, print details (headers and response) when in debug mode
- catch AttributeError
........
r3789 | poeml | 2008-04-23 16:23:14 +0200 (Wed, 23 Apr 2008) | 4 lines
- errors: add two new classes named OscWrongOptionsError and OscWrongArgsError
- commandline: raise instances of the new errors in a number of places
- commandline: add get_cmd_help() to Osc instance which returns the formatted help of a subcommand
........
r3790 | Marcus_H | 2008-04-23 16:48:28 +0200 (Wed, 23 Apr 2008) | 4 lines
- added 2 new exception classes: OscNoConfigfileError and OscIOError
- added new method write_config() to the conf.py module: This method writes osc's configuration file
- minor cleanups in the conf module
........
r3791 | poeml | 2008-04-23 17:11:07 +0200 (Wed, 23 Apr 2008) | 3 lines
small compatibility fix for r3790: try-except-finally isn't supported in
python-2.4.2, thus do the same as try-except inside a try-finally.
........
r3792 | poeml | 2008-04-23 17:37:53 +0200 (Wed, 23 Apr 2008) | 2 lines
fix up the remaining places regarding handling of errors related to commandline parsing
........
r3793 | poeml | 2008-04-23 17:40:34 +0200 (Wed, 23 Apr 2008) | 3 lines
raise a NoWorkingCopyError in osc.core.store_read_project() in case of an
IOError
........
r3798 | Marcus_H | 2008-04-23 23:55:24 +0200 (Wed, 23 Apr 2008) | 1 line
ported -r3797 from trunk
........
r3802 | Marcus_H | 2008-04-24 11:00:55 +0200 (Thu, 24 Apr 2008) | 1 line
ported -r3801 from trunk
........
r3805 | poeml | 2008-04-24 12:52:30 +0200 (Thu, 24 Apr 2008) | 2 lines
raise OscHTTPError in show_pattern_meta(), replacing local error handling
........
r3817 | poeml | 2008-04-24 20:21:32 +0200 (Thu, 24 Apr 2008) | 9 lines
- remove errors.OscHTTPError again.
it seems simpler to use urllib2.HTTPError instead (and just add a specific
error text message where appropriate, and re-raise)
- for 404s, check out _which_ part was not found
it is very ugly, but may be considered Good for pragmatic reasons
- removed local exception handling and workaround for returned 500's from
delete_package() and delete_project(), thereby getting rid of 4 possible exit
points.
........
r3818 | Marcus_H | 2008-04-24 22:36:17 +0200 (Thu, 24 Apr 2008) | 1 line
- this check is superfluous because every HTTPError instance has a code attribute
........
r3819 | poeml | 2008-04-25 00:39:39 +0200 (Fri, 25 Apr 2008) | 1 line
remove a forgotten debug line from core.delete_project()
........
r3820 | poeml | 2008-04-25 10:07:58 +0200 (Fri, 25 Apr 2008) | 2 lines
- ditch local error handling from wipebinaries(), rebuild(), and abortbuild()
........
r3821 | poeml | 2008-04-25 10:56:38 +0200 (Fri, 25 Apr 2008) | 2 lines
It is never needed to import the exception module.
........
r3822 | poeml | 2008-04-25 11:13:39 +0200 (Fri, 25 Apr 2008) | 4 lines
- when going into the debugger with --post-mortem, always print a traceback before
(thus implying -t)
- do not jump into the debugger if not on a TTY, or working in interactive mode
........
r3827 | poeml | 2008-04-25 13:07:46 +0200 (Fri, 25 Apr 2008) | 9 lines
- add errors.OscWorkingCopyOutdated, which takes a tuple with three args:
path to working copy, current rev, expected rev
- add handler for urllib2.URLError errors to the babysitter
- simplify the OscWrongArgsError and OscWrongOptionsError handlers, by removing
the extra line "Sorry, wrong ..." that was printed before the messages given
when the error was raised.
- remove one more errors.OscHTTPError which was still there, and raise
urllib2.HTTPError instead (show_package_meta())
........
r3829 | poeml | 2008-04-25 14:19:10 +0200 (Fri, 25 Apr 2008) | 11 lines
- comment some methods in osc.core which are used by nearly all do_* methods in
osc.commandline
- improve "is not a package/project dir" error messages, by printing the
absolute path tried, instead of '.' for the cwd
- make core.store_read_package() raise a proper NoWorkingCopyError instead of
terminating
- give attribution to things in babysitter.py copied from mercurial
- prefix HTTPError exceptions with 'Server returned an error:'
- remove obsolete local error handling from do_prjresults(), do_importsrcpkg(),
do_repos()
........
r3830 | poeml | 2008-04-25 14:29:35 +0200 (Fri, 25 Apr 2008) | 1 line
catch IOError exceptions in the babysitter
........
r3837 | poeml | 2008-04-25 17:27:36 +0200 (Fri, 25 Apr 2008) | 5 lines
- do_remotebuildlog: raise errors for wrong arguments, remove exits
- raise AttributeError in make_meta_url() instead of exiting
- delete unused method core.delete_server_files()
- replace exit call inside make_meta_url() with an AttributeError
........
r3838 | poeml | 2008-04-25 17:49:18 +0200 (Fri, 25 Apr 2008) | 1 line
simplify the check in do_checkout if a project exists, by using show_project_meta() instead of meta_exists
........
r3839 | poeml | 2008-04-25 18:31:26 +0200 (Fri, 25 Apr 2008) | 6 lines
- commandline do_checkout(): change the order of the two checks, first do the
(cheaper) check for existing directory
- core.core checkout_package(): simplify the check in if the package
exists, by using show_package_meta() instead of meta_exists
Let it throw an exception, instead of using sys.exit().
........
r3841 | Marcus_H | 2008-04-27 15:48:06 +0200 (Sun, 27 Apr 2008) | 5 lines
- added 2 new exception classes: PackageError() and PackageExistsError. The PackageError() class is meant to be the base class for all subsequent package exceptions.
- get rid of 2 sys.exit(1) calls
- make the update() method of the Project() class safer: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- minor fix in delPackage(): use getTransActPath() when printing out the filename
........
r3842 | Marcus_H | 2008-04-27 16:52:55 +0200 (Sun, 27 Apr 2008) | 3 lines
- make the commit() method safe: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- removed another sys.exit(1): raise an exception if a package is missing when doing a commit. For now we use the PackageExistsError() exception but this might change in the future (updated description of PackageExistsError() according to this change)
........
r3848 | poeml | 2008-04-28 12:46:45 +0200 (Mon, 28 Apr 2008) | 3 lines
rename several error classes, dropping the "Osc" prefix, and "Error" suffix in
cases where they don't really make sense.
........
r3849 | poeml | 2008-04-28 12:57:32 +0200 (Mon, 28 Apr 2008) | 3 lines
- rename osc.errors module to osc.oscerr, to make it easier to import it from
other programs and have a crystal clear namespace
........
r3850 | poeml | 2008-04-28 13:26:12 +0200 (Mon, 28 Apr 2008) | 2 lines
split PackageExists exception class into PackageExists and PackageMissing
........
2008-04-28 18:37:44 +02:00
"""
2008-08-07 18:40:55 +02:00
write osc ' s intial configuration file. entries is a dict which contains values
Merged revisions 3774-3775,3779,3781-3782,3787,3789-3793,3798,3802,3805,3817-3822,3827,3829-3830,3837-3839,3841-3842,3848-3850 via svnmerge from
https://forgesvn1.novell.com/svn/opensuse/branches/buildservice/osc-exception-handling
........
r3774 | poeml | 2008-04-22 17:39:45 +0200 (Tue, 22 Apr 2008) | 3 lines
A first draft on implement systematic exception handling:
Add errors.py with some exceptions defined, and babysitter.py to handle them
........
r3775 | poeml | 2008-04-22 22:34:12 +0200 (Tue, 22 Apr 2008) | 9 lines
- new global options:
--debugger jump into the debugger before executing anything
--post-mortem jump into the debugger in case of errors
-t, --traceback print call trace in case of errors
- traceback and post_mortem can also be set in .oscrc.
- catch more errors (HTTPError).
- make config accessible from outside of the Osc instance, by making it a class
attribute
........
r3779 | poeml | 2008-04-23 00:55:49 +0200 (Wed, 23 Apr 2008) | 5 lines
- new global option:
-d, --debug print info useful for debugging
- catch some more errors (HTTPError), with OscHTTPError which isn't very
advanced yet.
........
r3781 | Marcus_H | 2008-04-23 01:02:00 +0200 (Wed, 23 Apr 2008) | 2 lines
- added OscConfigError class (just for testing).
- small change in the signature of the OscBaseError constructor (actually we should get rid of the 'args' tuple because it will be deprecated sooner or later
........
r3782 | Marcus_H | 2008-04-23 02:02:13 +0200 (Wed, 23 Apr 2008) | 2 lines
- access the prg.conf.config dict in a save way - this way we avoid AttributeErrors if the prg.conf.config dict doesn't exist
- in case of an configparser error we have to use the prg.options object directly (this was removed in r3781 by accident)
........
r3787 | poeml | 2008-04-23 09:23:56 +0200 (Wed, 23 Apr 2008) | 4 lines
- remove local exception handling from do_req
- for HTTPError, print details (headers and response) when in debug mode
- catch AttributeError
........
r3789 | poeml | 2008-04-23 16:23:14 +0200 (Wed, 23 Apr 2008) | 4 lines
- errors: add two new classes named OscWrongOptionsError and OscWrongArgsError
- commandline: raise instances of the new errors in a number of places
- commandline: add get_cmd_help() to Osc instance which returns the formatted help of a subcommand
........
r3790 | Marcus_H | 2008-04-23 16:48:28 +0200 (Wed, 23 Apr 2008) | 4 lines
- added 2 new exception classes: OscNoConfigfileError and OscIOError
- added new method write_config() to the conf.py module: This method writes osc's configuration file
- minor cleanups in the conf module
........
r3791 | poeml | 2008-04-23 17:11:07 +0200 (Wed, 23 Apr 2008) | 3 lines
small compatibility fix for r3790: try-except-finally isn't supported in
python-2.4.2, thus do the same as try-except inside a try-finally.
........
r3792 | poeml | 2008-04-23 17:37:53 +0200 (Wed, 23 Apr 2008) | 2 lines
fix up the remaining places regarding handling of errors related to commandline parsing
........
r3793 | poeml | 2008-04-23 17:40:34 +0200 (Wed, 23 Apr 2008) | 3 lines
raise a NoWorkingCopyError in osc.core.store_read_project() in case of an
IOError
........
r3798 | Marcus_H | 2008-04-23 23:55:24 +0200 (Wed, 23 Apr 2008) | 1 line
ported -r3797 from trunk
........
r3802 | Marcus_H | 2008-04-24 11:00:55 +0200 (Thu, 24 Apr 2008) | 1 line
ported -r3801 from trunk
........
r3805 | poeml | 2008-04-24 12:52:30 +0200 (Thu, 24 Apr 2008) | 2 lines
raise OscHTTPError in show_pattern_meta(), replacing local error handling
........
r3817 | poeml | 2008-04-24 20:21:32 +0200 (Thu, 24 Apr 2008) | 9 lines
- remove errors.OscHTTPError again.
it seems simpler to use urllib2.HTTPError instead (and just add a specific
error text message where appropriate, and re-raise)
- for 404s, check out _which_ part was not found
it is very ugly, but may be considered Good for pragmatic reasons
- removed local exception handling and workaround for returned 500's from
delete_package() and delete_project(), thereby getting rid of 4 possible exit
points.
........
r3818 | Marcus_H | 2008-04-24 22:36:17 +0200 (Thu, 24 Apr 2008) | 1 line
- this check is superfluous because every HTTPError instance has a code attribute
........
r3819 | poeml | 2008-04-25 00:39:39 +0200 (Fri, 25 Apr 2008) | 1 line
remove a forgotten debug line from core.delete_project()
........
r3820 | poeml | 2008-04-25 10:07:58 +0200 (Fri, 25 Apr 2008) | 2 lines
- ditch local error handling from wipebinaries(), rebuild(), and abortbuild()
........
r3821 | poeml | 2008-04-25 10:56:38 +0200 (Fri, 25 Apr 2008) | 2 lines
It is never needed to import the exception module.
........
r3822 | poeml | 2008-04-25 11:13:39 +0200 (Fri, 25 Apr 2008) | 4 lines
- when going into the debugger with --post-mortem, always print a traceback before
(thus implying -t)
- do not jump into the debugger if not on a TTY, or working in interactive mode
........
r3827 | poeml | 2008-04-25 13:07:46 +0200 (Fri, 25 Apr 2008) | 9 lines
- add errors.OscWorkingCopyOutdated, which takes a tuple with three args:
path to working copy, current rev, expected rev
- add handler for urllib2.URLError errors to the babysitter
- simplify the OscWrongArgsError and OscWrongOptionsError handlers, by removing
the extra line "Sorry, wrong ..." that was printed before the messages given
when the error was raised.
- remove one more errors.OscHTTPError which was still there, and raise
urllib2.HTTPError instead (show_package_meta())
........
r3829 | poeml | 2008-04-25 14:19:10 +0200 (Fri, 25 Apr 2008) | 11 lines
- comment some methods in osc.core which are used by nearly all do_* methods in
osc.commandline
- improve "is not a package/project dir" error messages, by printing the
absolute path tried, instead of '.' for the cwd
- make core.store_read_package() raise a proper NoWorkingCopyError instead of
terminating
- give attribution to things in babysitter.py copied from mercurial
- prefix HTTPError exceptions with 'Server returned an error:'
- remove obsolete local error handling from do_prjresults(), do_importsrcpkg(),
do_repos()
........
r3830 | poeml | 2008-04-25 14:29:35 +0200 (Fri, 25 Apr 2008) | 1 line
catch IOError exceptions in the babysitter
........
r3837 | poeml | 2008-04-25 17:27:36 +0200 (Fri, 25 Apr 2008) | 5 lines
- do_remotebuildlog: raise errors for wrong arguments, remove exits
- raise AttributeError in make_meta_url() instead of exiting
- delete unused method core.delete_server_files()
- replace exit call inside make_meta_url() with an AttributeError
........
r3838 | poeml | 2008-04-25 17:49:18 +0200 (Fri, 25 Apr 2008) | 1 line
simplify the check in do_checkout if a project exists, by using show_project_meta() instead of meta_exists
........
r3839 | poeml | 2008-04-25 18:31:26 +0200 (Fri, 25 Apr 2008) | 6 lines
- commandline do_checkout(): change the order of the two checks, first do the
(cheaper) check for existing directory
- core.core checkout_package(): simplify the check in if the package
exists, by using show_package_meta() instead of meta_exists
Let it throw an exception, instead of using sys.exit().
........
r3841 | Marcus_H | 2008-04-27 15:48:06 +0200 (Sun, 27 Apr 2008) | 5 lines
- added 2 new exception classes: PackageError() and PackageExistsError. The PackageError() class is meant to be the base class for all subsequent package exceptions.
- get rid of 2 sys.exit(1) calls
- make the update() method of the Project() class safer: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- minor fix in delPackage(): use getTransActPath() when printing out the filename
........
r3842 | Marcus_H | 2008-04-27 16:52:55 +0200 (Sun, 27 Apr 2008) | 3 lines
- make the commit() method safe: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- removed another sys.exit(1): raise an exception if a package is missing when doing a commit. For now we use the PackageExistsError() exception but this might change in the future (updated description of PackageExistsError() according to this change)
........
r3848 | poeml | 2008-04-28 12:46:45 +0200 (Mon, 28 Apr 2008) | 3 lines
rename several error classes, dropping the "Osc" prefix, and "Error" suffix in
cases where they don't really make sense.
........
r3849 | poeml | 2008-04-28 12:57:32 +0200 (Mon, 28 Apr 2008) | 3 lines
- rename osc.errors module to osc.oscerr, to make it easier to import it from
other programs and have a crystal clear namespace
........
r3850 | poeml | 2008-04-28 13:26:12 +0200 (Mon, 28 Apr 2008) | 2 lines
split PackageExists exception class into PackageExists and PackageMissing
........
2008-04-28 18:37:44 +02:00
for the config file ( e . g . { ' user ' : ' username ' , ' pass ' : ' password ' } ) .
2008-08-07 18:40:55 +02:00
custom_template is an optional configuration template .
Merged revisions 3774-3775,3779,3781-3782,3787,3789-3793,3798,3802,3805,3817-3822,3827,3829-3830,3837-3839,3841-3842,3848-3850 via svnmerge from
https://forgesvn1.novell.com/svn/opensuse/branches/buildservice/osc-exception-handling
........
r3774 | poeml | 2008-04-22 17:39:45 +0200 (Tue, 22 Apr 2008) | 3 lines
A first draft on implement systematic exception handling:
Add errors.py with some exceptions defined, and babysitter.py to handle them
........
r3775 | poeml | 2008-04-22 22:34:12 +0200 (Tue, 22 Apr 2008) | 9 lines
- new global options:
--debugger jump into the debugger before executing anything
--post-mortem jump into the debugger in case of errors
-t, --traceback print call trace in case of errors
- traceback and post_mortem can also be set in .oscrc.
- catch more errors (HTTPError).
- make config accessible from outside of the Osc instance, by making it a class
attribute
........
r3779 | poeml | 2008-04-23 00:55:49 +0200 (Wed, 23 Apr 2008) | 5 lines
- new global option:
-d, --debug print info useful for debugging
- catch some more errors (HTTPError), with OscHTTPError which isn't very
advanced yet.
........
r3781 | Marcus_H | 2008-04-23 01:02:00 +0200 (Wed, 23 Apr 2008) | 2 lines
- added OscConfigError class (just for testing).
- small change in the signature of the OscBaseError constructor (actually we should get rid of the 'args' tuple because it will be deprecated sooner or later
........
r3782 | Marcus_H | 2008-04-23 02:02:13 +0200 (Wed, 23 Apr 2008) | 2 lines
- access the prg.conf.config dict in a save way - this way we avoid AttributeErrors if the prg.conf.config dict doesn't exist
- in case of an configparser error we have to use the prg.options object directly (this was removed in r3781 by accident)
........
r3787 | poeml | 2008-04-23 09:23:56 +0200 (Wed, 23 Apr 2008) | 4 lines
- remove local exception handling from do_req
- for HTTPError, print details (headers and response) when in debug mode
- catch AttributeError
........
r3789 | poeml | 2008-04-23 16:23:14 +0200 (Wed, 23 Apr 2008) | 4 lines
- errors: add two new classes named OscWrongOptionsError and OscWrongArgsError
- commandline: raise instances of the new errors in a number of places
- commandline: add get_cmd_help() to Osc instance which returns the formatted help of a subcommand
........
r3790 | Marcus_H | 2008-04-23 16:48:28 +0200 (Wed, 23 Apr 2008) | 4 lines
- added 2 new exception classes: OscNoConfigfileError and OscIOError
- added new method write_config() to the conf.py module: This method writes osc's configuration file
- minor cleanups in the conf module
........
r3791 | poeml | 2008-04-23 17:11:07 +0200 (Wed, 23 Apr 2008) | 3 lines
small compatibility fix for r3790: try-except-finally isn't supported in
python-2.4.2, thus do the same as try-except inside a try-finally.
........
r3792 | poeml | 2008-04-23 17:37:53 +0200 (Wed, 23 Apr 2008) | 2 lines
fix up the remaining places regarding handling of errors related to commandline parsing
........
r3793 | poeml | 2008-04-23 17:40:34 +0200 (Wed, 23 Apr 2008) | 3 lines
raise a NoWorkingCopyError in osc.core.store_read_project() in case of an
IOError
........
r3798 | Marcus_H | 2008-04-23 23:55:24 +0200 (Wed, 23 Apr 2008) | 1 line
ported -r3797 from trunk
........
r3802 | Marcus_H | 2008-04-24 11:00:55 +0200 (Thu, 24 Apr 2008) | 1 line
ported -r3801 from trunk
........
r3805 | poeml | 2008-04-24 12:52:30 +0200 (Thu, 24 Apr 2008) | 2 lines
raise OscHTTPError in show_pattern_meta(), replacing local error handling
........
r3817 | poeml | 2008-04-24 20:21:32 +0200 (Thu, 24 Apr 2008) | 9 lines
- remove errors.OscHTTPError again.
it seems simpler to use urllib2.HTTPError instead (and just add a specific
error text message where appropriate, and re-raise)
- for 404s, check out _which_ part was not found
it is very ugly, but may be considered Good for pragmatic reasons
- removed local exception handling and workaround for returned 500's from
delete_package() and delete_project(), thereby getting rid of 4 possible exit
points.
........
r3818 | Marcus_H | 2008-04-24 22:36:17 +0200 (Thu, 24 Apr 2008) | 1 line
- this check is superfluous because every HTTPError instance has a code attribute
........
r3819 | poeml | 2008-04-25 00:39:39 +0200 (Fri, 25 Apr 2008) | 1 line
remove a forgotten debug line from core.delete_project()
........
r3820 | poeml | 2008-04-25 10:07:58 +0200 (Fri, 25 Apr 2008) | 2 lines
- ditch local error handling from wipebinaries(), rebuild(), and abortbuild()
........
r3821 | poeml | 2008-04-25 10:56:38 +0200 (Fri, 25 Apr 2008) | 2 lines
It is never needed to import the exception module.
........
r3822 | poeml | 2008-04-25 11:13:39 +0200 (Fri, 25 Apr 2008) | 4 lines
- when going into the debugger with --post-mortem, always print a traceback before
(thus implying -t)
- do not jump into the debugger if not on a TTY, or working in interactive mode
........
r3827 | poeml | 2008-04-25 13:07:46 +0200 (Fri, 25 Apr 2008) | 9 lines
- add errors.OscWorkingCopyOutdated, which takes a tuple with three args:
path to working copy, current rev, expected rev
- add handler for urllib2.URLError errors to the babysitter
- simplify the OscWrongArgsError and OscWrongOptionsError handlers, by removing
the extra line "Sorry, wrong ..." that was printed before the messages given
when the error was raised.
- remove one more errors.OscHTTPError which was still there, and raise
urllib2.HTTPError instead (show_package_meta())
........
r3829 | poeml | 2008-04-25 14:19:10 +0200 (Fri, 25 Apr 2008) | 11 lines
- comment some methods in osc.core which are used by nearly all do_* methods in
osc.commandline
- improve "is not a package/project dir" error messages, by printing the
absolute path tried, instead of '.' for the cwd
- make core.store_read_package() raise a proper NoWorkingCopyError instead of
terminating
- give attribution to things in babysitter.py copied from mercurial
- prefix HTTPError exceptions with 'Server returned an error:'
- remove obsolete local error handling from do_prjresults(), do_importsrcpkg(),
do_repos()
........
r3830 | poeml | 2008-04-25 14:29:35 +0200 (Fri, 25 Apr 2008) | 1 line
catch IOError exceptions in the babysitter
........
r3837 | poeml | 2008-04-25 17:27:36 +0200 (Fri, 25 Apr 2008) | 5 lines
- do_remotebuildlog: raise errors for wrong arguments, remove exits
- raise AttributeError in make_meta_url() instead of exiting
- delete unused method core.delete_server_files()
- replace exit call inside make_meta_url() with an AttributeError
........
r3838 | poeml | 2008-04-25 17:49:18 +0200 (Fri, 25 Apr 2008) | 1 line
simplify the check in do_checkout if a project exists, by using show_project_meta() instead of meta_exists
........
r3839 | poeml | 2008-04-25 18:31:26 +0200 (Fri, 25 Apr 2008) | 6 lines
- commandline do_checkout(): change the order of the two checks, first do the
(cheaper) check for existing directory
- core.core checkout_package(): simplify the check in if the package
exists, by using show_package_meta() instead of meta_exists
Let it throw an exception, instead of using sys.exit().
........
r3841 | Marcus_H | 2008-04-27 15:48:06 +0200 (Sun, 27 Apr 2008) | 5 lines
- added 2 new exception classes: PackageError() and PackageExistsError. The PackageError() class is meant to be the base class for all subsequent package exceptions.
- get rid of 2 sys.exit(1) calls
- make the update() method of the Project() class safer: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- minor fix in delPackage(): use getTransActPath() when printing out the filename
........
r3842 | Marcus_H | 2008-04-27 16:52:55 +0200 (Sun, 27 Apr 2008) | 3 lines
- make the commit() method safe: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- removed another sys.exit(1): raise an exception if a package is missing when doing a commit. For now we use the PackageExistsError() exception but this might change in the future (updated description of PackageExistsError() according to this change)
........
r3848 | poeml | 2008-04-28 12:46:45 +0200 (Mon, 28 Apr 2008) | 3 lines
rename several error classes, dropping the "Osc" prefix, and "Error" suffix in
cases where they don't really make sense.
........
r3849 | poeml | 2008-04-28 12:57:32 +0200 (Mon, 28 Apr 2008) | 3 lines
- rename osc.errors module to osc.oscerr, to make it easier to import it from
other programs and have a crystal clear namespace
........
r3850 | poeml | 2008-04-28 13:26:12 +0200 (Mon, 28 Apr 2008) | 2 lines
split PackageExists exception class into PackageExists and PackageMissing
........
2008-04-28 18:37:44 +02:00
"""
conf_template = custom_template or new_conf_template
2023-08-22 15:34:45 +02:00
config = globals ( ) [ " config " ] . dict ( )
Merged revisions 3774-3775,3779,3781-3782,3787,3789-3793,3798,3802,3805,3817-3822,3827,3829-3830,3837-3839,3841-3842,3848-3850 via svnmerge from
https://forgesvn1.novell.com/svn/opensuse/branches/buildservice/osc-exception-handling
........
r3774 | poeml | 2008-04-22 17:39:45 +0200 (Tue, 22 Apr 2008) | 3 lines
A first draft on implement systematic exception handling:
Add errors.py with some exceptions defined, and babysitter.py to handle them
........
r3775 | poeml | 2008-04-22 22:34:12 +0200 (Tue, 22 Apr 2008) | 9 lines
- new global options:
--debugger jump into the debugger before executing anything
--post-mortem jump into the debugger in case of errors
-t, --traceback print call trace in case of errors
- traceback and post_mortem can also be set in .oscrc.
- catch more errors (HTTPError).
- make config accessible from outside of the Osc instance, by making it a class
attribute
........
r3779 | poeml | 2008-04-23 00:55:49 +0200 (Wed, 23 Apr 2008) | 5 lines
- new global option:
-d, --debug print info useful for debugging
- catch some more errors (HTTPError), with OscHTTPError which isn't very
advanced yet.
........
r3781 | Marcus_H | 2008-04-23 01:02:00 +0200 (Wed, 23 Apr 2008) | 2 lines
- added OscConfigError class (just for testing).
- small change in the signature of the OscBaseError constructor (actually we should get rid of the 'args' tuple because it will be deprecated sooner or later
........
r3782 | Marcus_H | 2008-04-23 02:02:13 +0200 (Wed, 23 Apr 2008) | 2 lines
- access the prg.conf.config dict in a save way - this way we avoid AttributeErrors if the prg.conf.config dict doesn't exist
- in case of an configparser error we have to use the prg.options object directly (this was removed in r3781 by accident)
........
r3787 | poeml | 2008-04-23 09:23:56 +0200 (Wed, 23 Apr 2008) | 4 lines
- remove local exception handling from do_req
- for HTTPError, print details (headers and response) when in debug mode
- catch AttributeError
........
r3789 | poeml | 2008-04-23 16:23:14 +0200 (Wed, 23 Apr 2008) | 4 lines
- errors: add two new classes named OscWrongOptionsError and OscWrongArgsError
- commandline: raise instances of the new errors in a number of places
- commandline: add get_cmd_help() to Osc instance which returns the formatted help of a subcommand
........
r3790 | Marcus_H | 2008-04-23 16:48:28 +0200 (Wed, 23 Apr 2008) | 4 lines
- added 2 new exception classes: OscNoConfigfileError and OscIOError
- added new method write_config() to the conf.py module: This method writes osc's configuration file
- minor cleanups in the conf module
........
r3791 | poeml | 2008-04-23 17:11:07 +0200 (Wed, 23 Apr 2008) | 3 lines
small compatibility fix for r3790: try-except-finally isn't supported in
python-2.4.2, thus do the same as try-except inside a try-finally.
........
r3792 | poeml | 2008-04-23 17:37:53 +0200 (Wed, 23 Apr 2008) | 2 lines
fix up the remaining places regarding handling of errors related to commandline parsing
........
r3793 | poeml | 2008-04-23 17:40:34 +0200 (Wed, 23 Apr 2008) | 3 lines
raise a NoWorkingCopyError in osc.core.store_read_project() in case of an
IOError
........
r3798 | Marcus_H | 2008-04-23 23:55:24 +0200 (Wed, 23 Apr 2008) | 1 line
ported -r3797 from trunk
........
r3802 | Marcus_H | 2008-04-24 11:00:55 +0200 (Thu, 24 Apr 2008) | 1 line
ported -r3801 from trunk
........
r3805 | poeml | 2008-04-24 12:52:30 +0200 (Thu, 24 Apr 2008) | 2 lines
raise OscHTTPError in show_pattern_meta(), replacing local error handling
........
r3817 | poeml | 2008-04-24 20:21:32 +0200 (Thu, 24 Apr 2008) | 9 lines
- remove errors.OscHTTPError again.
it seems simpler to use urllib2.HTTPError instead (and just add a specific
error text message where appropriate, and re-raise)
- for 404s, check out _which_ part was not found
it is very ugly, but may be considered Good for pragmatic reasons
- removed local exception handling and workaround for returned 500's from
delete_package() and delete_project(), thereby getting rid of 4 possible exit
points.
........
r3818 | Marcus_H | 2008-04-24 22:36:17 +0200 (Thu, 24 Apr 2008) | 1 line
- this check is superfluous because every HTTPError instance has a code attribute
........
r3819 | poeml | 2008-04-25 00:39:39 +0200 (Fri, 25 Apr 2008) | 1 line
remove a forgotten debug line from core.delete_project()
........
r3820 | poeml | 2008-04-25 10:07:58 +0200 (Fri, 25 Apr 2008) | 2 lines
- ditch local error handling from wipebinaries(), rebuild(), and abortbuild()
........
r3821 | poeml | 2008-04-25 10:56:38 +0200 (Fri, 25 Apr 2008) | 2 lines
It is never needed to import the exception module.
........
r3822 | poeml | 2008-04-25 11:13:39 +0200 (Fri, 25 Apr 2008) | 4 lines
- when going into the debugger with --post-mortem, always print a traceback before
(thus implying -t)
- do not jump into the debugger if not on a TTY, or working in interactive mode
........
r3827 | poeml | 2008-04-25 13:07:46 +0200 (Fri, 25 Apr 2008) | 9 lines
- add errors.OscWorkingCopyOutdated, which takes a tuple with three args:
path to working copy, current rev, expected rev
- add handler for urllib2.URLError errors to the babysitter
- simplify the OscWrongArgsError and OscWrongOptionsError handlers, by removing
the extra line "Sorry, wrong ..." that was printed before the messages given
when the error was raised.
- remove one more errors.OscHTTPError which was still there, and raise
urllib2.HTTPError instead (show_package_meta())
........
r3829 | poeml | 2008-04-25 14:19:10 +0200 (Fri, 25 Apr 2008) | 11 lines
- comment some methods in osc.core which are used by nearly all do_* methods in
osc.commandline
- improve "is not a package/project dir" error messages, by printing the
absolute path tried, instead of '.' for the cwd
- make core.store_read_package() raise a proper NoWorkingCopyError instead of
terminating
- give attribution to things in babysitter.py copied from mercurial
- prefix HTTPError exceptions with 'Server returned an error:'
- remove obsolete local error handling from do_prjresults(), do_importsrcpkg(),
do_repos()
........
r3830 | poeml | 2008-04-25 14:29:35 +0200 (Fri, 25 Apr 2008) | 1 line
catch IOError exceptions in the babysitter
........
r3837 | poeml | 2008-04-25 17:27:36 +0200 (Fri, 25 Apr 2008) | 5 lines
- do_remotebuildlog: raise errors for wrong arguments, remove exits
- raise AttributeError in make_meta_url() instead of exiting
- delete unused method core.delete_server_files()
- replace exit call inside make_meta_url() with an AttributeError
........
r3838 | poeml | 2008-04-25 17:49:18 +0200 (Fri, 25 Apr 2008) | 1 line
simplify the check in do_checkout if a project exists, by using show_project_meta() instead of meta_exists
........
r3839 | poeml | 2008-04-25 18:31:26 +0200 (Fri, 25 Apr 2008) | 6 lines
- commandline do_checkout(): change the order of the two checks, first do the
(cheaper) check for existing directory
- core.core checkout_package(): simplify the check in if the package
exists, by using show_package_meta() instead of meta_exists
Let it throw an exception, instead of using sys.exit().
........
r3841 | Marcus_H | 2008-04-27 15:48:06 +0200 (Sun, 27 Apr 2008) | 5 lines
- added 2 new exception classes: PackageError() and PackageExistsError. The PackageError() class is meant to be the base class for all subsequent package exceptions.
- get rid of 2 sys.exit(1) calls
- make the update() method of the Project() class safer: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- minor fix in delPackage(): use getTransActPath() when printing out the filename
........
r3842 | Marcus_H | 2008-04-27 16:52:55 +0200 (Sun, 27 Apr 2008) | 3 lines
- make the commit() method safe: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- removed another sys.exit(1): raise an exception if a package is missing when doing a commit. For now we use the PackageExistsError() exception but this might change in the future (updated description of PackageExistsError() according to this change)
........
r3848 | poeml | 2008-04-28 12:46:45 +0200 (Mon, 28 Apr 2008) | 3 lines
rename several error classes, dropping the "Osc" prefix, and "Error" suffix in
cases where they don't really make sense.
........
r3849 | poeml | 2008-04-28 12:57:32 +0200 (Mon, 28 Apr 2008) | 3 lines
- rename osc.errors module to osc.oscerr, to make it easier to import it from
other programs and have a crystal clear namespace
........
r3850 | poeml | 2008-04-28 13:26:12 +0200 (Mon, 28 Apr 2008) | 2 lines
split PackageExists exception class into PackageExists and PackageMissing
........
2008-04-28 18:37:44 +02:00
config . update ( entries )
2013-04-09 12:36:42 +02:00
sio = StringIO ( conf_template . strip ( ) % config )
2023-08-22 15:34:45 +02:00
cp = OscConfigParser . OscConfigParser ( )
2023-11-15 09:14:52 +01:00
cp . read_file ( sio )
2019-08-27 15:08:38 +02:00
cp . set ( config [ ' apiurl ' ] , ' user ' , config [ ' user ' ] )
if creds_mgr_descriptor :
creds_mgr = creds_mgr_descriptor . create ( cp )
else :
creds_mgr = _get_credentials_manager ( config [ ' apiurl ' ] , cp )
creds_mgr . set_password ( config [ ' apiurl ' ] , config [ ' user ' ] , config [ ' pass ' ] )
2011-11-18 22:27:38 +01:00
write_config ( conffile , cp )
2011-08-17 15:33:56 +02:00
Merged revisions 3774-3775,3779,3781-3782,3787,3789-3793,3798,3802,3805,3817-3822,3827,3829-3830,3837-3839,3841-3842,3848-3850 via svnmerge from
https://forgesvn1.novell.com/svn/opensuse/branches/buildservice/osc-exception-handling
........
r3774 | poeml | 2008-04-22 17:39:45 +0200 (Tue, 22 Apr 2008) | 3 lines
A first draft on implement systematic exception handling:
Add errors.py with some exceptions defined, and babysitter.py to handle them
........
r3775 | poeml | 2008-04-22 22:34:12 +0200 (Tue, 22 Apr 2008) | 9 lines
- new global options:
--debugger jump into the debugger before executing anything
--post-mortem jump into the debugger in case of errors
-t, --traceback print call trace in case of errors
- traceback and post_mortem can also be set in .oscrc.
- catch more errors (HTTPError).
- make config accessible from outside of the Osc instance, by making it a class
attribute
........
r3779 | poeml | 2008-04-23 00:55:49 +0200 (Wed, 23 Apr 2008) | 5 lines
- new global option:
-d, --debug print info useful for debugging
- catch some more errors (HTTPError), with OscHTTPError which isn't very
advanced yet.
........
r3781 | Marcus_H | 2008-04-23 01:02:00 +0200 (Wed, 23 Apr 2008) | 2 lines
- added OscConfigError class (just for testing).
- small change in the signature of the OscBaseError constructor (actually we should get rid of the 'args' tuple because it will be deprecated sooner or later
........
r3782 | Marcus_H | 2008-04-23 02:02:13 +0200 (Wed, 23 Apr 2008) | 2 lines
- access the prg.conf.config dict in a save way - this way we avoid AttributeErrors if the prg.conf.config dict doesn't exist
- in case of an configparser error we have to use the prg.options object directly (this was removed in r3781 by accident)
........
r3787 | poeml | 2008-04-23 09:23:56 +0200 (Wed, 23 Apr 2008) | 4 lines
- remove local exception handling from do_req
- for HTTPError, print details (headers and response) when in debug mode
- catch AttributeError
........
r3789 | poeml | 2008-04-23 16:23:14 +0200 (Wed, 23 Apr 2008) | 4 lines
- errors: add two new classes named OscWrongOptionsError and OscWrongArgsError
- commandline: raise instances of the new errors in a number of places
- commandline: add get_cmd_help() to Osc instance which returns the formatted help of a subcommand
........
r3790 | Marcus_H | 2008-04-23 16:48:28 +0200 (Wed, 23 Apr 2008) | 4 lines
- added 2 new exception classes: OscNoConfigfileError and OscIOError
- added new method write_config() to the conf.py module: This method writes osc's configuration file
- minor cleanups in the conf module
........
r3791 | poeml | 2008-04-23 17:11:07 +0200 (Wed, 23 Apr 2008) | 3 lines
small compatibility fix for r3790: try-except-finally isn't supported in
python-2.4.2, thus do the same as try-except inside a try-finally.
........
r3792 | poeml | 2008-04-23 17:37:53 +0200 (Wed, 23 Apr 2008) | 2 lines
fix up the remaining places regarding handling of errors related to commandline parsing
........
r3793 | poeml | 2008-04-23 17:40:34 +0200 (Wed, 23 Apr 2008) | 3 lines
raise a NoWorkingCopyError in osc.core.store_read_project() in case of an
IOError
........
r3798 | Marcus_H | 2008-04-23 23:55:24 +0200 (Wed, 23 Apr 2008) | 1 line
ported -r3797 from trunk
........
r3802 | Marcus_H | 2008-04-24 11:00:55 +0200 (Thu, 24 Apr 2008) | 1 line
ported -r3801 from trunk
........
r3805 | poeml | 2008-04-24 12:52:30 +0200 (Thu, 24 Apr 2008) | 2 lines
raise OscHTTPError in show_pattern_meta(), replacing local error handling
........
r3817 | poeml | 2008-04-24 20:21:32 +0200 (Thu, 24 Apr 2008) | 9 lines
- remove errors.OscHTTPError again.
it seems simpler to use urllib2.HTTPError instead (and just add a specific
error text message where appropriate, and re-raise)
- for 404s, check out _which_ part was not found
it is very ugly, but may be considered Good for pragmatic reasons
- removed local exception handling and workaround for returned 500's from
delete_package() and delete_project(), thereby getting rid of 4 possible exit
points.
........
r3818 | Marcus_H | 2008-04-24 22:36:17 +0200 (Thu, 24 Apr 2008) | 1 line
- this check is superfluous because every HTTPError instance has a code attribute
........
r3819 | poeml | 2008-04-25 00:39:39 +0200 (Fri, 25 Apr 2008) | 1 line
remove a forgotten debug line from core.delete_project()
........
r3820 | poeml | 2008-04-25 10:07:58 +0200 (Fri, 25 Apr 2008) | 2 lines
- ditch local error handling from wipebinaries(), rebuild(), and abortbuild()
........
r3821 | poeml | 2008-04-25 10:56:38 +0200 (Fri, 25 Apr 2008) | 2 lines
It is never needed to import the exception module.
........
r3822 | poeml | 2008-04-25 11:13:39 +0200 (Fri, 25 Apr 2008) | 4 lines
- when going into the debugger with --post-mortem, always print a traceback before
(thus implying -t)
- do not jump into the debugger if not on a TTY, or working in interactive mode
........
r3827 | poeml | 2008-04-25 13:07:46 +0200 (Fri, 25 Apr 2008) | 9 lines
- add errors.OscWorkingCopyOutdated, which takes a tuple with three args:
path to working copy, current rev, expected rev
- add handler for urllib2.URLError errors to the babysitter
- simplify the OscWrongArgsError and OscWrongOptionsError handlers, by removing
the extra line "Sorry, wrong ..." that was printed before the messages given
when the error was raised.
- remove one more errors.OscHTTPError which was still there, and raise
urllib2.HTTPError instead (show_package_meta())
........
r3829 | poeml | 2008-04-25 14:19:10 +0200 (Fri, 25 Apr 2008) | 11 lines
- comment some methods in osc.core which are used by nearly all do_* methods in
osc.commandline
- improve "is not a package/project dir" error messages, by printing the
absolute path tried, instead of '.' for the cwd
- make core.store_read_package() raise a proper NoWorkingCopyError instead of
terminating
- give attribution to things in babysitter.py copied from mercurial
- prefix HTTPError exceptions with 'Server returned an error:'
- remove obsolete local error handling from do_prjresults(), do_importsrcpkg(),
do_repos()
........
r3830 | poeml | 2008-04-25 14:29:35 +0200 (Fri, 25 Apr 2008) | 1 line
catch IOError exceptions in the babysitter
........
r3837 | poeml | 2008-04-25 17:27:36 +0200 (Fri, 25 Apr 2008) | 5 lines
- do_remotebuildlog: raise errors for wrong arguments, remove exits
- raise AttributeError in make_meta_url() instead of exiting
- delete unused method core.delete_server_files()
- replace exit call inside make_meta_url() with an AttributeError
........
r3838 | poeml | 2008-04-25 17:49:18 +0200 (Fri, 25 Apr 2008) | 1 line
simplify the check in do_checkout if a project exists, by using show_project_meta() instead of meta_exists
........
r3839 | poeml | 2008-04-25 18:31:26 +0200 (Fri, 25 Apr 2008) | 6 lines
- commandline do_checkout(): change the order of the two checks, first do the
(cheaper) check for existing directory
- core.core checkout_package(): simplify the check in if the package
exists, by using show_package_meta() instead of meta_exists
Let it throw an exception, instead of using sys.exit().
........
r3841 | Marcus_H | 2008-04-27 15:48:06 +0200 (Sun, 27 Apr 2008) | 5 lines
- added 2 new exception classes: PackageError() and PackageExistsError. The PackageError() class is meant to be the base class for all subsequent package exceptions.
- get rid of 2 sys.exit(1) calls
- make the update() method of the Project() class safer: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- minor fix in delPackage(): use getTransActPath() when printing out the filename
........
r3842 | Marcus_H | 2008-04-27 16:52:55 +0200 (Sun, 27 Apr 2008) | 3 lines
- make the commit() method safe: in any case we have to write the _packages file otherwise the package tracking will be screwed up.
- removed another sys.exit(1): raise an exception if a package is missing when doing a commit. For now we use the PackageExistsError() exception but this might change in the future (updated description of PackageExistsError() according to this change)
........
r3848 | poeml | 2008-04-28 12:46:45 +0200 (Mon, 28 Apr 2008) | 3 lines
rename several error classes, dropping the "Osc" prefix, and "Error" suffix in
cases where they don't really make sense.
........
r3849 | poeml | 2008-04-28 12:57:32 +0200 (Mon, 28 Apr 2008) | 3 lines
- rename osc.errors module to osc.oscerr, to make it easier to import it from
other programs and have a crystal clear namespace
........
r3850 | poeml | 2008-04-28 13:26:12 +0200 (Mon, 28 Apr 2008) | 2 lines
split PackageExists exception class into PackageExists and PackageMissing
........
2008-04-28 18:37:44 +02:00
2022-04-07 09:09:28 +02:00
def add_section ( filename , url , user , passwd , creds_mgr_descriptor = None , allow_http = None ) :
2009-05-11 09:46:01 +02:00
"""
Add a section to config file for new api url .
"""
global config
cp = get_configParser ( filename )
try :
cp . add_section ( url )
correctly refer to exception
this is left-over from 87d354e1a013806ef37f11e22f015e5cc43e533d
Addressing:
Traceback (most recent call last):
File "/usr/bin/osc", line 26, in <module>
r = babysitter.run(osccli)
File "/usr/lib/python2.7/site-packages/osc/babysitter.py", line 60, in run
return prg.main()
File "/usr/lib/python2.7/site-packages/osc/cmdln.py", line 335, in main
self.postoptparse()
File "/usr/lib/python2.7/site-packages/osc/commandline.py", line 136, in postoptparse
override_verbose = self.options.verbose)
File "/usr/lib/python2.7/site-packages/osc/conf.py", line 873, in get_config
add_section(conffile, url, user, passwordx)
File "/usr/lib/python2.7/site-packages/osc/conf.py", line 712, in add_section
except OscConfigParser.ConfigParser.DuplicateSectionError:
AttributeError: class OscConfigParser has no attribute 'ConfigParser'
2013-07-17 10:18:10 +02:00
except OscConfigParser . configparser . DuplicateSectionError :
2009-05-11 09:46:01 +02:00
# Section might have existed, but was empty
pass
2019-08-27 15:08:38 +02:00
cp . set ( url , ' user ' , user )
if creds_mgr_descriptor :
creds_mgr = creds_mgr_descriptor . create ( cp )
2009-05-11 09:46:01 +02:00
else :
2019-08-27 15:08:38 +02:00
creds_mgr = _get_credentials_manager ( url , cp )
creds_mgr . set_password ( url , user , passwd )
2022-04-07 09:09:28 +02:00
if allow_http :
cp . set ( url , ' allow_http ' , " 1 " )
2011-11-18 22:27:38 +01:00
write_config ( filename , cp )
2011-08-17 15:33:56 +02:00
2019-08-27 15:08:38 +02:00
def _get_credentials_manager ( url , cp ) :
if cp . has_option ( url , credentials . AbstractCredentialsManager . config_entry ) :
2019-10-16 10:41:06 +02:00
creds_mgr = credentials . create_credentials_manager ( url , cp )
if creds_mgr is None :
2024-01-06 09:54:57 +01:00
msg = f ' Unable to instantiate creds mgr (section: { url } ) '
2019-10-16 10:41:06 +02:00
conffile = get_configParser . conffile
raise oscerr . ConfigMissingCredentialsError ( msg , conffile , url )
return creds_mgr
2019-08-27 15:08:38 +02:00
if config [ ' use_keyring ' ] and GENERIC_KEYRING :
return credentials . get_keyring_credentials_manager ( cp )
2023-10-13 20:45:29 +02:00
elif cp . get ( url , " passx " , fallback = None ) is not None :
return credentials . ObfuscatedConfigFileCredentialsManager ( cp , None )
2019-08-27 15:08:38 +02:00
return credentials . PlaintextConfigFileCredentialsManager ( cp , None )
2019-08-27 16:26:20 +02:00
2011-08-17 15:33:56 +02:00
def get_config ( override_conffile = None ,
override_apiurl = None ,
override_debug = None ,
override_http_debug = None ,
override_http_full_debug = None ,
override_traceback = None ,
override_post_mortem = None ,
2024-01-24 09:49:22 +01:00
override_quiet = None ,
2011-08-17 15:33:56 +02:00
override_no_keyring = None ,
2023-07-17 08:59:10 +02:00
override_verbose = None ,
overrides = None
) :
2023-08-22 15:34:45 +02:00
"""
Configure osc .
2006-10-10 16:04:34 +02:00
2023-08-22 15:34:45 +02:00
The configuration options are loaded with the following priority :
2023-09-25 14:24:57 +02:00
1. environment variables : OSC_ < uppercase_option >
2023-08-22 15:34:45 +02:00
2. override arguments provided to get_config ( )
3. oscrc config file
"""
if overrides :
overrides = overrides . copy ( )
2017-10-27 11:29:00 +02:00
else :
2023-08-22 15:34:45 +02:00
overrides = { }
if override_apiurl is not None :
overrides [ " apiurl " ] = override_apiurl
if override_debug is not None :
overrides [ " debug " ] = override_debug
if override_http_debug is not None :
overrides [ " http_debug " ] = override_http_debug
if override_http_full_debug is not None :
overrides [ " http_full_debug " ] = override_http_full_debug
if override_traceback is not None :
overrides [ " traceback " ] = override_traceback
if override_post_mortem is not None :
overrides [ " post_mortem " ] = override_post_mortem
if override_no_keyring is not None :
overrides [ " use_keyring " ] = not override_no_keyring
2024-01-24 09:49:22 +01:00
if override_quiet is not None :
overrides [ " quiet " ] = override_quiet
2023-08-22 15:34:45 +02:00
if override_verbose is not None :
overrides [ " verbose " ] = override_verbose
if override_conffile is not None :
2017-10-27 11:29:00 +02:00
conffile = override_conffile
2023-08-22 15:34:45 +02:00
else :
conffile = identify_conf ( )
2006-10-10 16:04:34 +02:00
2024-01-04 16:33:38 +01:00
if conffile in [ " " , " /dev/null " ] :
cp = OscConfigParser . OscConfigParser ( )
cp . add_section ( " general " )
else :
conffile = os . path . expanduser ( conffile )
if not os . path . exists ( conffile ) :
raise oscerr . NoConfigfile ( conffile , account_not_configured_text % conffile )
2006-10-10 16:04:34 +02:00
2024-01-04 16:33:38 +01:00
# make sure oscrc is not world readable, it may contain a password
conffile_stat = os . stat ( conffile )
if conffile_stat . st_mode != 0o600 :
try :
os . chmod ( conffile , 0o600 )
except OSError as e :
if e . errno in ( errno . EROFS , errno . EPERM ) :
print ( f " Warning: Configuration file ' { conffile } ' may have insecure file permissions. " )
else :
raise e
cp = get_configParser ( conffile )
if not cp . has_section ( " general " ) :
# FIXME: it might be sufficient to just assume defaults?
msg = config_incomplete_text % conffile
defaults = Options ( ) . dict ( )
msg + = new_conf_template % defaults
raise oscerr . ConfigError ( msg , conffile )
2006-10-10 16:04:34 +02:00
2023-08-22 15:34:45 +02:00
global config
2007-07-24 12:46:03 +02:00
2023-08-22 15:34:45 +02:00
config = Options ( )
config . conffile = conffile
2008-08-20 16:07:11 +02:00
2023-10-19 14:23:04 +02:00
# read 'debug' value before it gets properly stored into Options for early debug messages
if override_debug :
debug_str = str ( override_debug )
elif " OSC_DEBUG " in os . environ :
debug_str = os . environ [ " OSC_DEBUG " ]
elif " debug " in cp [ " general " ] :
debug_str = cp [ " general " ] [ " debug " ]
else :
debug_str = " 0 "
debug = True if debug_str . strip ( ) . lower ( ) in ( " 1 " , " yes " , " true " , " on " ) else False
2023-08-22 15:34:45 +02:00
# read host options first in order to populate apiurl aliases
urls = [ i for i in cp . sections ( ) if i != " general " ]
for url in urls :
apiurl = sanitize_apiurl ( url )
2024-01-04 16:41:24 +01:00
# the username will be overwritten later while reading actual config values
username = cp [ url ] . get ( " user " , " " )
2023-08-22 15:34:45 +02:00
host_options = HostOptions ( apiurl = apiurl , username = username , _parent = config )
2024-01-04 16:41:24 +01:00
2023-10-19 14:23:04 +02:00
known_ini_keys = set ( )
2023-08-22 15:34:45 +02:00
for name , field in host_options . __fields__ . items ( ) :
2024-01-04 16:41:24 +01:00
# the following code relies on interating through fields in a given order: aliases, username, credentials_mgr_class, password
2023-08-22 15:34:45 +02:00
ini_key = field . extra . get ( " ini_key " , name )
2023-10-19 14:23:04 +02:00
known_ini_keys . add ( ini_key )
2009-05-11 09:46:01 +02:00
2024-01-04 16:41:24 +01:00
# iterate through aliases and store the value of the the first env that matches OSC_HOST_{ALIAS}_{NAME}
env_value = None
for alias in host_options . aliases :
alias = alias . replace ( " - " , " _ " )
env_key = f " OSC_HOST_ { alias . upper ( ) } _ { name . upper ( ) } "
env_value = os . environ . get ( env_key , None )
if env_value is not None :
break
if env_value is not None :
value = env_value
2023-10-03 08:56:15 +02:00
elif ini_key in cp [ url ] :
value = cp [ url ] [ ini_key ]
else :
2024-01-04 16:41:24 +01:00
value = None
if name == " credentials_mgr_class " :
# HACK: inject credentials_mgr_class back in case we have specified it from env to have it available for reading password
if value :
cp [ url ] [ credentials . AbstractCredentialsManager . config_entry ] = value
elif name == " password " :
creds_mgr = _get_credentials_manager ( url , cp )
if env_value is None :
value = creds_mgr . get_password ( url , host_options . username , defer = True , apiurl = host_options . apiurl )
2023-08-22 15:34:45 +02:00
2024-01-04 16:41:24 +01:00
if value is not None :
host_options . set_value_from_string ( name , value )
2023-08-22 15:34:45 +02:00
2023-10-19 14:23:04 +02:00
for key , value in cp [ url ] . items ( ) :
if key . startswith ( " _ " ) :
continue
if key in known_ini_keys :
continue
if debug :
print ( f " DEBUG: Config option ' [ { url } ]/ { key } ' doesn ' t map to any HostOptions field " , file = sys . stderr )
host_options [ key ] = value
2023-08-22 15:34:45 +02:00
scheme = urlsplit ( apiurl ) [ 0 ]
if scheme == " http " and not host_options . allow_http :
msg = " The apiurl ' {apiurl} ' uses HTTP protocol without any encryption. \n "
msg + = " All communication incl. sending your password IS NOT ENCRYPTED! \n "
msg + = " Add ' allow_http=1 ' to the [ {apiurl} ] config file section to mute this message. \n "
print ( msg . format ( apiurl = apiurl ) , file = sys . stderr )
config . api_host_options [ apiurl ] = host_options
# read the main options
2023-10-19 14:23:04 +02:00
known_ini_keys = set ( )
2023-08-22 15:34:45 +02:00
for name , field in config . __fields__ . items ( ) :
ini_key = field . extra . get ( " ini_key " , name )
2023-10-19 14:23:04 +02:00
known_ini_keys . add ( ini_key )
2023-08-22 15:34:45 +02:00
env_key = f " OSC_ { name . upper ( ) } "
# priority: env, overrides, config
if env_key in os . environ :
2023-09-29 09:54:50 +02:00
value = os . environ [ env_key ]
2023-08-22 15:34:45 +02:00
elif name in overrides :
value = overrides . pop ( name )
elif ini_key in overrides :
value = overrides . pop ( ini_key )
elif ini_key in cp [ " general " ] :
value = cp [ " general " ] [ ini_key ]
else :
continue
2007-04-25 12:24:51 +02:00
2023-08-22 15:34:45 +02:00
if name == " apiurl " :
# resolve an apiurl alias to an actual apiurl
apiurl = config . apiurl_aliases . get ( value , None )
if not apiurl :
# no alias matched, try again with a sanitized apiurl (with https:// prefix)
# and if there's no match again, just use the sanitized apiurl
apiurl = sanitize_apiurl ( value )
apiurl = config . apiurl_aliases . get ( apiurl , apiurl )
value = apiurl
2023-09-11 21:06:34 +02:00
2023-08-22 15:34:45 +02:00
config . set_value_from_string ( name , value )
2023-09-11 21:06:34 +02:00
2024-01-04 16:41:24 +01:00
# BEGIN: override credentials for the default apiurl
# OSC_APIURL is handled already because it's a regular field
env_username = os . environ . get ( " OSC_USERNAME " , " " )
env_credentials_mgr_class = os . environ . get ( " OSC_CREDENTIALS_MGR_CLASS " , None )
env_password = os . environ . get ( " OSC_PASSWORD " , None )
if config . apiurl not in config . api_host_options :
host_options = HostOptions ( apiurl = config . apiurl , username = env_username , _parent = config )
config . api_host_options [ config . apiurl ] = host_options
# HACK: inject section so we can add credentials_mgr_class later
cp . add_section ( config . apiurl )
host_options = config . api_host_options [ config . apiurl ]
if env_username :
host_options . set_value_from_string ( " username " , env_username )
if env_credentials_mgr_class :
host_options . set_value_from_string ( " credentials_mgr_class " , env_credentials_mgr_class )
# HACK: inject credentials_mgr_class in case we have specified it from env to have it available for reading password
cp [ config . apiurl ] [ " credentials_mgr_class " ] = env_credentials_mgr_class
if env_password :
password = Password ( env_password )
host_options . password = password
elif env_credentials_mgr_class :
creds_mgr = _get_credentials_manager ( config . apiurl , cp )
password = creds_mgr . get_password ( config . apiurl , host_options . username , defer = True , apiurl = host_options . apiurl )
host_options . password = password
# END: override credentials for the default apiurl
for apiurl , host_options in config . api_host_options . items ( ) :
if not host_options . username :
raise oscerr . ConfigMissingCredentialsError ( f " No user configured for apiurl { apiurl } " , conffile , apiurl )
2024-01-09 11:11:52 +01:00
if host_options . password is None :
2024-01-04 16:41:24 +01:00
raise oscerr . ConfigMissingCredentialsError ( f " No password configured for apiurl { apiurl } " , conffile , apiurl )
2023-10-19 14:23:04 +02:00
for key , value in cp [ " general " ] . items ( ) :
if key . startswith ( " _ " ) :
continue
if key in known_ini_keys :
continue
if debug :
print ( f " DEBUG: Config option ' [general]/ { key } ' doesn ' t map to any Options field " , file = sys . stderr )
config [ key ] = value
2023-08-22 15:34:45 +02:00
if overrides :
unused_overrides_str = " , " . join ( ( f " ' { i } ' " for i in overrides ) )
raise oscerr . ConfigError ( f " Unknown config options: { unused_overrides_str } " , " <command-line> " )
2007-08-22 12:18:25 +02:00
2009-08-20 21:28:05 +02:00
# XXX unless config['user'] goes away (and is replaced with a handy function, or
2008-03-13 17:15:41 +01:00
# config becomes an object, even better), set the global 'user' here as well,
2009-02-24 00:29:32 +01:00
# provided that there _are_ credentials for the chosen apiurl:
try :
2009-02-24 21:17:23 +01:00
config [ ' user ' ] = get_apiurl_usr ( config [ ' apiurl ' ] )
2013-04-09 11:27:02 +02:00
except oscerr . ConfigMissingApiurl as e :
2009-02-24 00:29:32 +01:00
e . msg = config_missing_apiurl_text % config [ ' apiurl ' ]
e . file = conffile
raise e
2007-08-22 12:18:25 +02:00
2022-02-03 11:11:40 +01:00
# enable connection debugging after all config options are set
from . connection import enable_http_debug
enable_http_debug ( config )
2007-08-22 12:18:25 +02:00
2017-10-27 11:29:00 +02:00
def identify_conf ( ) :
# needed for compat reasons(users may have their oscrc still in ~
if ' OSC_CONFIG ' in os . environ :
return os . environ . get ( ' OSC_CONFIG ' )
2024-02-14 14:19:59 +01:00
conffile = os . path . join ( xdg . XDG_CONFIG_HOME , " osc " , " oscrc " )
2017-10-27 11:29:00 +02:00
2024-02-21 09:23:29 +01:00
if os . path . exists ( os . path . expanduser ( " ~/.oscrc " ) ) or os . path . islink ( os . path . expanduser ( " ~/.oscrc " ) ) :
if " XDG_CONFIG_HOME " in os . environ :
print ( f " { tty . colorize ( ' WARNING ' , ' yellow,bold ' ) } : Ignoring XDG_CONFIG_HOME env, loading an existing config from ' ~/.oscrc ' instead " , file = sys . stderr )
print ( " To fix this, move the existing ' ~/.oscrc ' to XDG location such as ' ~/.config/osc/oscrc ' " , file = sys . stderr )
elif os . path . exists ( os . path . expanduser ( conffile ) ) :
print ( f " { tty . colorize ( ' WARNING ' , ' yellow,bold ' ) } : Ignoring config ' { conffile } ' in XDG location, loading an existing config from ~/.oscrc instead " , file = sys . stderr )
print ( " To fix this, remove ' ~/.oscrc ' " , file = sys . stderr )
return ' ~/.oscrc '
2017-10-27 11:29:00 +02:00
return conffile
2011-08-17 15:33:56 +02:00
2022-09-12 13:43:10 +02:00
2019-08-26 11:30:41 +02:00
def interactive_config_setup ( conffile , apiurl , initial = True ) :
2023-04-11 11:11:25 +02:00
if not apiurl :
2023-08-22 15:34:45 +02:00
apiurl = Options ( ) [ " apiurl " ]
2023-04-11 11:11:25 +02:00
2022-04-07 09:09:28 +02:00
scheme = urlsplit ( apiurl ) [ 0 ]
http = scheme == " http "
if http :
msg = " The apiurl ' {apiurl} ' uses HTTP protocol without any encryption. \n "
msg + = " All communication incl. sending your password WILL NOT BE ENCRYPTED! \n "
msg + = " Do you really want to continue with no encryption? \n "
print ( msg . format ( apiurl = apiurl ) , file = sys . stderr )
yes = raw_input ( " Type ' YES ' to continue: " )
if yes != " YES " :
raise oscerr . UserAbort ( )
print ( )
2023-10-10 16:13:59 +02:00
apiurl_no_scheme = urlsplit ( apiurl ) [ 1 ] or apiurl
2023-04-11 11:25:24 +02:00
user_prompt = f " Username [ { apiurl_no_scheme } ]: "
user = raw_input ( user_prompt )
pass_prompt = f " Password [ { user } @ { apiurl_no_scheme } ]: "
passwd = getpass . getpass ( pass_prompt )
2019-08-29 11:35:34 +02:00
creds_mgr_descr = select_credentials_manager_descr ( )
if initial :
config = { ' user ' : user , ' pass ' : passwd }
if apiurl :
config [ ' apiurl ' ] = apiurl
2022-04-07 09:09:28 +02:00
if http :
config [ ' allow_http ' ] = 1
2019-08-29 11:35:34 +02:00
write_initial_config ( conffile , config , creds_mgr_descriptor = creds_mgr_descr )
else :
2022-04-07 09:09:28 +02:00
add_section ( conffile , apiurl , user , passwd , creds_mgr_descriptor = creds_mgr_descr , allow_http = http )
2019-08-29 11:35:34 +02:00
2022-09-12 13:43:10 +02:00
2019-08-29 11:35:34 +02:00
def select_credentials_manager_descr ( ) :
2019-08-27 15:08:38 +02:00
if not credentials . has_keyring_support ( ) :
2020-02-29 01:28:20 +01:00
print ( ' To use keyrings please install python %d -keyring. ' % sys . version_info . major )
2019-08-27 15:08:38 +02:00
creds_mgr_descriptors = credentials . get_credentials_manager_descriptors ( )
2022-03-24 10:27:36 +01:00
rows = [ ]
2019-08-27 15:08:38 +02:00
for i , creds_mgr_descr in enumerate ( creds_mgr_descriptors , 1 ) :
2022-03-24 10:27:36 +01:00
rows + = [ str ( i ) , creds_mgr_descr . name ( ) , creds_mgr_descr . description ( ) ]
from . core import build_table
headline = ( ' NUM ' , ' NAME ' , ' DESCRIPTION ' )
table = build_table ( len ( headline ) , rows , headline )
print ( )
for row in table :
print ( row )
2022-03-24 11:33:10 +01:00
i = raw_input ( ' Select credentials manager [default=1]: ' )
if not i :
i = " 1 "
2019-08-27 15:08:38 +02:00
if not i . isdigit ( ) :
sys . exit ( ' Invalid selection ' )
i = int ( i ) - 1
if i < 0 or i > = len ( creds_mgr_descriptors ) :
sys . exit ( ' Invalid selection ' )
2019-08-29 11:35:34 +02:00
return creds_mgr_descriptors [ i ]
2019-08-26 11:30:41 +02:00
2009-11-13 11:46:23 +01:00
# vim: sw=4 et