We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Handle missing config file
## Description of the problem, including code/CLI snippet

When '~/.python-gitlab.cfg' is missing, an full traceback is printed

## Expected Behavior

Create a default '~/.python-gitlab.cfg' file and print
"The tool is not configured yet. Edit ~/.python-gitlab.cfg and run the command again"

## Actual Behavior

See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=912537

## Specifications

  - python-gitlab version: 1.6.0



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gitlab/cli.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # Copyright (C) 2013-2017 Gauvain Pocentek <gauvain@pocentek.net>
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Lesser General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 
19 from __future__ import print_function
20 import argparse
21 import functools
22 import importlib
23 import re
24 import sys
25 
26 import gitlab.config
27 
28 camel_re = re.compile('(.)([A-Z])')
29 
30 # custom_actions = {
31 #    cls: {
32 #        action: (mandatory_args, optional_args, in_obj),
33 #    },
34 # }
35 custom_actions = {}
36 
37 
38 def register_custom_action(cls_names, mandatory=tuple(), optional=tuple()):
39     def wrap(f):
40         @functools.wraps(f)
41         def wrapped_f(*args, **kwargs):
42             return f(*args, **kwargs)
43 
44         # in_obj defines whether the method belongs to the obj or the manager
45         in_obj = True
46         classes = cls_names
47         if type(cls_names) != tuple:
48             classes = (cls_names, )
49 
50         for cls_name in classes:
51             final_name = cls_name
52             if cls_name.endswith('Manager'):
53                 final_name = cls_name.replace('Manager', '')
54                 in_obj = False
55             if final_name not in custom_actions:
56                 custom_actions[final_name] = {}
57 
58             action = f.__name__.replace('_', '-')
59             custom_actions[final_name][action] = (mandatory, optional, in_obj)
60 
61         return wrapped_f
62     return wrap
63 
64 
65 def die(msg, e=None):
66     if e:
67         msg = "%s (%s)" % (msg, e)
68     sys.stderr.write(msg + "\n")
69     sys.exit(1)
70 
71 
72 def what_to_cls(what):
73     return "".join([s.capitalize() for s in what.split("-")])
74 
75 
76 def cls_to_what(cls):
77     return camel_re.sub(r'\1-\2', cls.__name__).lower()
78 
79 
80 def _get_base_parser(add_help=True):
81     parser = argparse.ArgumentParser(
82         add_help=add_help,
83         description="GitLab API Command Line Interface")
84     parser.add_argument("--version", help="Display the version.",
85                         action="store_true")
86     parser.add_argument("-v", "--verbose", "--fancy",
87                         help="Verbose mode (legacy format only)",
88                         action="store_true")
89     parser.add_argument("-d", "--debug",
90                         help="Debug mode (display HTTP requests)",
91                         action="store_true")
92     parser.add_argument("-c", "--config-file", action='append',
93                         help=("Configuration file to use. Can be used "
94                               "multiple times."))
95     parser.add_argument("-g", "--gitlab",
96                         help=("Which configuration section should "
97                               "be used. If not defined, the default selection "
98                               "will be used."),
99                         required=False)
100     parser.add_argument("-o", "--output",
101                         help="Output format (v4 only): json|legacy|yaml",
102                         required=False,
103                         choices=['json', 'legacy', 'yaml'],
104                         default="legacy")
105     parser.add_argument("-f", "--fields",
106                         help=("Fields to display in the output (comma "
107                               "separated). Not used with legacy output"),
108                         required=False)
109 
110     return parser
111 
112 
113 def _get_parser(cli_module):
114     parser = _get_base_parser()
115     return cli_module.extend_parser(parser)
116 
117 
118 def _parse_value(v):
119     if isinstance(v, str) and v.startswith('@'):
120         # If the user-provided value starts with @, we try to read the file
121         # path provided after @ as the real value. Exit on any error.
122         try:
123             with open(v[1:]) as fl:
124                 return fl.read()
125         except Exception as e:
126             sys.stderr.write("%s\n" % e)
127             sys.exit(1)
128 
129     return v
130 
131 
132 def main():
133     if "--version" in sys.argv:
134         print(gitlab.__version__)
135         exit(0)
136 
137     parser = _get_base_parser(add_help=False)
138     if "--help" in sys.argv or "-h" in sys.argv:
139         parser.print_help()
140         exit(0)
141 
142     # This first parsing step is used to find the gitlab config to use, and
143     # load the propermodule (v3 or v4) accordingly. At that point we don't have
144     # any subparser setup
145     (options, args) = parser.parse_known_args(sys.argv)
146 
147     config = gitlab.config.GitlabConfigParser(options.gitlab,
148                                               options.config_file)
149     cli_module = importlib.import_module('gitlab.v%s.cli' % config.api_version)
150 
151     # Now we build the entire set of subcommands and do the complete parsing
152     parser = _get_parser(cli_module)
153     args = parser.parse_args(sys.argv[1:])
154 
155     config_files = args.config_file
156     gitlab_id = args.gitlab
157     verbose = args.verbose
158     output = args.output
159     fields = []
160     if args.fields:
161         fields = [x.strip() for x in args.fields.split(',')]
162     debug = args.debug
163     action = args.action
164     what = args.what
165 
166     args = args.__dict__
167     # Remove CLI behavior-related args
168     for item in ('gitlab', 'config_file', 'verbose', 'debug', 'what', 'action',
169                  'version', 'output'):
170         args.pop(item)
171     args = {k: _parse_value(v) for k, v in args.items() if v is not None}
172 
173     try:
174         gl = gitlab.Gitlab.from_config(gitlab_id, config_files)
175         if gl.private_token or gl.oauth_token:
176             gl.auth()
177     except Exception as e:
178         die(str(e))
179 
180     if debug:
181         gl.enable_debug()
182 
183     cli_module.run(gl, what, action, args, verbose, output, fields)
184 
185     sys.exit(0)
186
```

Path: `gitlab/config.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2013-2017 Gauvain Pocentek <gauvain@pocentek.net>
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 import os
19 
20 from six.moves import configparser
21 
22 _DEFAULT_FILES = [
23     '/etc/python-gitlab.cfg',
24     os.path.expanduser('~/.python-gitlab.cfg')
25 ]
26 
27 
28 class ConfigError(Exception):
29     pass
30 
31 
32 class GitlabIDError(ConfigError):
33     pass
34 
35 
36 class GitlabDataError(ConfigError):
37     pass
38 
39 
40 class GitlabConfigParser(object):
41     def __init__(self, gitlab_id=None, config_files=None):
42         self.gitlab_id = gitlab_id
43         _files = config_files or _DEFAULT_FILES
44         self._config = configparser.ConfigParser()
45         self._config.read(_files)
46 
47         if self.gitlab_id is None:
48             try:
49                 self.gitlab_id = self._config.get('global', 'default')
50             except Exception:
51                 raise GitlabIDError("Impossible to get the gitlab id "
52                                     "(not specified in config file)")
53 
54         try:
55             self.url = self._config.get(self.gitlab_id, 'url')
56         except Exception:
57             raise GitlabDataError("Impossible to get gitlab informations from "
58                                   "configuration (%s)" % self.gitlab_id)
59 
60         self.ssl_verify = True
61         try:
62             self.ssl_verify = self._config.getboolean('global', 'ssl_verify')
63         except ValueError:
64             # Value Error means the option exists but isn't a boolean.
65             # Get as a string instead as it should then be a local path to a
66             # CA bundle.
67             try:
68                 self.ssl_verify = self._config.get('global', 'ssl_verify')
69             except Exception:
70                 pass
71         except Exception:
72             pass
73         try:
74             self.ssl_verify = self._config.getboolean(self.gitlab_id,
75                                                       'ssl_verify')
76         except ValueError:
77             # Value Error means the option exists but isn't a boolean.
78             # Get as a string instead as it should then be a local path to a
79             # CA bundle.
80             try:
81                 self.ssl_verify = self._config.get(self.gitlab_id,
82                                                    'ssl_verify')
83             except Exception:
84                 pass
85         except Exception:
86             pass
87 
88         self.timeout = 60
89         try:
90             self.timeout = self._config.getint('global', 'timeout')
91         except Exception:
92             pass
93         try:
94             self.timeout = self._config.getint(self.gitlab_id, 'timeout')
95         except Exception:
96             pass
97 
98         self.private_token = None
99         try:
100             self.private_token = self._config.get(self.gitlab_id,
101                                                   'private_token')
102         except Exception:
103             pass
104 
105         self.oauth_token = None
106         try:
107             self.oauth_token = self._config.get(self.gitlab_id, 'oauth_token')
108         except Exception:
109             pass
110 
111         self.http_username = None
112         self.http_password = None
113         try:
114             self.http_username = self._config.get(self.gitlab_id,
115                                                   'http_username')
116             self.http_password = self._config.get(self.gitlab_id,
117                                                   'http_password')
118         except Exception:
119             pass
120 
121         self.http_username = None
122         self.http_password = None
123         try:
124             self.http_username = self._config.get(self.gitlab_id,
125                                                   'http_username')
126             self.http_password = self._config.get(self.gitlab_id,
127                                                   'http_password')
128         except Exception:
129             pass
130 
131         self.api_version = '4'
132         try:
133             self.api_version = self._config.get('global', 'api_version')
134         except Exception:
135             pass
136         try:
137             self.api_version = self._config.get(self.gitlab_id, 'api_version')
138         except Exception:
139             pass
140         if self.api_version not in ('4',):
141             raise GitlabDataError("Unsupported API version: %s" %
142                                   self.api_version)
143 
144         self.per_page = None
145         for section in ['global', self.gitlab_id]:
146             try:
147                 self.per_page = self._config.getint(section, 'per_page')
148             except Exception:
149                 pass
150         if self.per_page is not None and not 0 <= self.per_page <= 100:
151             raise GitlabDataError("Unsupported per_page number: %s" %
152                                   self.per_page)
153
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gitlab/cli.py b/gitlab/cli.py
--- a/gitlab/cli.py
+++ b/gitlab/cli.py
@@ -17,6 +17,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from __future__ import print_function
+
 import argparse
 import functools
 import importlib
@@ -143,9 +144,13 @@
     # load the propermodule (v3 or v4) accordingly. At that point we don't have
     # any subparser setup
     (options, args) = parser.parse_known_args(sys.argv)
-
-    config = gitlab.config.GitlabConfigParser(options.gitlab,
-                                              options.config_file)
+    try:
+        config = gitlab.config.GitlabConfigParser(
+            options.gitlab,
+            options.config_file
+        )
+    except gitlab.config.ConfigError as e:
+        sys.exit(e)
     cli_module = importlib.import_module('gitlab.v%s.cli' % config.api_version)
 
     # Now we build the entire set of subcommands and do the complete parsing
diff --git a/gitlab/config.py b/gitlab/config.py
--- a/gitlab/config.py
+++ b/gitlab/config.py
@@ -37,10 +37,27 @@
     pass
 
 
+class GitlabConfigMissingError(ConfigError):
+    pass
+
+
 class GitlabConfigParser(object):
     def __init__(self, gitlab_id=None, config_files=None):
         self.gitlab_id = gitlab_id
         _files = config_files or _DEFAULT_FILES
+        file_exist = False
+        for file in _files:
+            if os.path.exists(file):
+                file_exist = True
+        if not file_exist:
+            raise GitlabConfigMissingError(
+                "Config file not found. \nPlease create one in "
+                "one of the following locations: {} \nor "
+                "specify a config file using the '-c' parameter.".format(
+                    ", ".join(_DEFAULT_FILES)
+                )
+            )
+
         self._config = configparser.ConfigParser()
         self._config.read(_files)

{"golden_diff": "diff --git a/gitlab/cli.py b/gitlab/cli.py\n--- a/gitlab/cli.py\n+++ b/gitlab/cli.py\n@@ -17,6 +17,7 @@\n # along with this program.  If not, see <http://www.gnu.org/licenses/>.\n \n from __future__ import print_function\n+\n import argparse\n import functools\n import importlib\n@@ -143,9 +144,13 @@\n     # load the propermodule (v3 or v4) accordingly. At that point we don't have\n     # any subparser setup\n     (options, args) = parser.parse_known_args(sys.argv)\n-\n-    config = gitlab.config.GitlabConfigParser(options.gitlab,\n-                                              options.config_file)\n+    try:\n+        config = gitlab.config.GitlabConfigParser(\n+            options.gitlab,\n+            options.config_file\n+        )\n+    except gitlab.config.ConfigError as e:\n+        sys.exit(e)\n     cli_module = importlib.import_module('gitlab.v%s.cli' % config.api_version)\n \n     # Now we build the entire set of subcommands and do the complete parsing\ndiff --git a/gitlab/config.py b/gitlab/config.py\n--- a/gitlab/config.py\n+++ b/gitlab/config.py\n@@ -37,10 +37,27 @@\n     pass\n \n \n+class GitlabConfigMissingError(ConfigError):\n+    pass\n+\n+\n class GitlabConfigParser(object):\n     def __init__(self, gitlab_id=None, config_files=None):\n         self.gitlab_id = gitlab_id\n         _files = config_files or _DEFAULT_FILES\n+        file_exist = False\n+        for file in _files:\n+            if os.path.exists(file):\n+                file_exist = True\n+        if not file_exist:\n+            raise GitlabConfigMissingError(\n+                \"Config file not found. \\nPlease create one in \"\n+                \"one of the following locations: {} \\nor \"\n+                \"specify a config file using the '-c' parameter.\".format(\n+                    \", \".join(_DEFAULT_FILES)\n+                )\n+            )\n+\n         self._config = configparser.ConfigParser()\n         self._config.read(_files)\n", "issue": "Handle missing config file\n## Description of the problem, including code/CLI snippet\r\n\r\nWhen '~/.python-gitlab.cfg' is missing, an full traceback is printed\r\n\r\n## Expected Behavior\r\n\r\nCreate a default '~/.python-gitlab.cfg' file and print\r\n\"The tool is not configured yet. Edit ~/.python-gitlab.cfg and run the command again\"\r\n\r\n## Actual Behavior\r\n\r\nSee https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=912537\r\n\r\n## Specifications\r\n\r\n  - python-gitlab version: 1.6.0\r\n\r\n\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#\n# Copyright (C) 2013-2017 Gauvain Pocentek <gauvain@pocentek.net>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nfrom __future__ import print_function\nimport argparse\nimport functools\nimport importlib\nimport re\nimport sys\n\nimport gitlab.config\n\ncamel_re = re.compile('(.)([A-Z])')\n\n# custom_actions = {\n#    cls: {\n#        action: (mandatory_args, optional_args, in_obj),\n#    },\n# }\ncustom_actions = {}\n\n\ndef register_custom_action(cls_names, mandatory=tuple(), optional=tuple()):\n    def wrap(f):\n        @functools.wraps(f)\n        def wrapped_f(*args, **kwargs):\n            return f(*args, **kwargs)\n\n        # in_obj defines whether the method belongs to the obj or the manager\n        in_obj = True\n        classes = cls_names\n        if type(cls_names) != tuple:\n            classes = (cls_names, )\n\n        for cls_name in classes:\n            final_name = cls_name\n            if cls_name.endswith('Manager'):\n                final_name = cls_name.replace('Manager', '')\n                in_obj = False\n            if final_name not in custom_actions:\n                custom_actions[final_name] = {}\n\n            action = f.__name__.replace('_', '-')\n            custom_actions[final_name][action] = (mandatory, optional, in_obj)\n\n        return wrapped_f\n    return wrap\n\n\ndef die(msg, e=None):\n    if e:\n        msg = \"%s (%s)\" % (msg, e)\n    sys.stderr.write(msg + \"\\n\")\n    sys.exit(1)\n\n\ndef what_to_cls(what):\n    return \"\".join([s.capitalize() for s in what.split(\"-\")])\n\n\ndef cls_to_what(cls):\n    return camel_re.sub(r'\\1-\\2', cls.__name__).lower()\n\n\ndef _get_base_parser(add_help=True):\n    parser = argparse.ArgumentParser(\n        add_help=add_help,\n        description=\"GitLab API Command Line Interface\")\n    parser.add_argument(\"--version\", help=\"Display the version.\",\n                        action=\"store_true\")\n    parser.add_argument(\"-v\", \"--verbose\", \"--fancy\",\n                        help=\"Verbose mode (legacy format only)\",\n                        action=\"store_true\")\n    parser.add_argument(\"-d\", \"--debug\",\n                        help=\"Debug mode (display HTTP requests)\",\n                        action=\"store_true\")\n    parser.add_argument(\"-c\", \"--config-file\", action='append',\n                        help=(\"Configuration file to use. Can be used \"\n                              \"multiple times.\"))\n    parser.add_argument(\"-g\", \"--gitlab\",\n                        help=(\"Which configuration section should \"\n                              \"be used. If not defined, the default selection \"\n                              \"will be used.\"),\n                        required=False)\n    parser.add_argument(\"-o\", \"--output\",\n                        help=\"Output format (v4 only): json|legacy|yaml\",\n                        required=False,\n                        choices=['json', 'legacy', 'yaml'],\n                        default=\"legacy\")\n    parser.add_argument(\"-f\", \"--fields\",\n                        help=(\"Fields to display in the output (comma \"\n                              \"separated). Not used with legacy output\"),\n                        required=False)\n\n    return parser\n\n\ndef _get_parser(cli_module):\n    parser = _get_base_parser()\n    return cli_module.extend_parser(parser)\n\n\ndef _parse_value(v):\n    if isinstance(v, str) and v.startswith('@'):\n        # If the user-provided value starts with @, we try to read the file\n        # path provided after @ as the real value. Exit on any error.\n        try:\n            with open(v[1:]) as fl:\n                return fl.read()\n        except Exception as e:\n            sys.stderr.write(\"%s\\n\" % e)\n            sys.exit(1)\n\n    return v\n\n\ndef main():\n    if \"--version\" in sys.argv:\n        print(gitlab.__version__)\n        exit(0)\n\n    parser = _get_base_parser(add_help=False)\n    if \"--help\" in sys.argv or \"-h\" in sys.argv:\n        parser.print_help()\n        exit(0)\n\n    # This first parsing step is used to find the gitlab config to use, and\n    # load the propermodule (v3 or v4) accordingly. At that point we don't have\n    # any subparser setup\n    (options, args) = parser.parse_known_args(sys.argv)\n\n    config = gitlab.config.GitlabConfigParser(options.gitlab,\n                                              options.config_file)\n    cli_module = importlib.import_module('gitlab.v%s.cli' % config.api_version)\n\n    # Now we build the entire set of subcommands and do the complete parsing\n    parser = _get_parser(cli_module)\n    args = parser.parse_args(sys.argv[1:])\n\n    config_files = args.config_file\n    gitlab_id = args.gitlab\n    verbose = args.verbose\n    output = args.output\n    fields = []\n    if args.fields:\n        fields = [x.strip() for x in args.fields.split(',')]\n    debug = args.debug\n    action = args.action\n    what = args.what\n\n    args = args.__dict__\n    # Remove CLI behavior-related args\n    for item in ('gitlab', 'config_file', 'verbose', 'debug', 'what', 'action',\n                 'version', 'output'):\n        args.pop(item)\n    args = {k: _parse_value(v) for k, v in args.items() if v is not None}\n\n    try:\n        gl = gitlab.Gitlab.from_config(gitlab_id, config_files)\n        if gl.private_token or gl.oauth_token:\n            gl.auth()\n    except Exception as e:\n        die(str(e))\n\n    if debug:\n        gl.enable_debug()\n\n    cli_module.run(gl, what, action, args, verbose, output, fields)\n\n    sys.exit(0)\n", "path": "gitlab/cli.py"}, {"content": "# -*- coding: utf-8 -*-\n#\n# Copyright (C) 2013-2017 Gauvain Pocentek <gauvain@pocentek.net>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nimport os\n\nfrom six.moves import configparser\n\n_DEFAULT_FILES = [\n    '/etc/python-gitlab.cfg',\n    os.path.expanduser('~/.python-gitlab.cfg')\n]\n\n\nclass ConfigError(Exception):\n    pass\n\n\nclass GitlabIDError(ConfigError):\n    pass\n\n\nclass GitlabDataError(ConfigError):\n    pass\n\n\nclass GitlabConfigParser(object):\n    def __init__(self, gitlab_id=None, config_files=None):\n        self.gitlab_id = gitlab_id\n        _files = config_files or _DEFAULT_FILES\n        self._config = configparser.ConfigParser()\n        self._config.read(_files)\n\n        if self.gitlab_id is None:\n            try:\n                self.gitlab_id = self._config.get('global', 'default')\n            except Exception:\n                raise GitlabIDError(\"Impossible to get the gitlab id \"\n                                    \"(not specified in config file)\")\n\n        try:\n            self.url = self._config.get(self.gitlab_id, 'url')\n        except Exception:\n            raise GitlabDataError(\"Impossible to get gitlab informations from \"\n                                  \"configuration (%s)\" % self.gitlab_id)\n\n        self.ssl_verify = True\n        try:\n            self.ssl_verify = self._config.getboolean('global', 'ssl_verify')\n        except ValueError:\n            # Value Error means the option exists but isn't a boolean.\n            # Get as a string instead as it should then be a local path to a\n            # CA bundle.\n            try:\n                self.ssl_verify = self._config.get('global', 'ssl_verify')\n            except Exception:\n                pass\n        except Exception:\n            pass\n        try:\n            self.ssl_verify = self._config.getboolean(self.gitlab_id,\n                                                      'ssl_verify')\n        except ValueError:\n            # Value Error means the option exists but isn't a boolean.\n            # Get as a string instead as it should then be a local path to a\n            # CA bundle.\n            try:\n                self.ssl_verify = self._config.get(self.gitlab_id,\n                                                   'ssl_verify')\n            except Exception:\n                pass\n        except Exception:\n            pass\n\n        self.timeout = 60\n        try:\n            self.timeout = self._config.getint('global', 'timeout')\n        except Exception:\n            pass\n        try:\n            self.timeout = self._config.getint(self.gitlab_id, 'timeout')\n        except Exception:\n            pass\n\n        self.private_token = None\n        try:\n            self.private_token = self._config.get(self.gitlab_id,\n                                                  'private_token')\n        except Exception:\n            pass\n\n        self.oauth_token = None\n        try:\n            self.oauth_token = self._config.get(self.gitlab_id, 'oauth_token')\n        except Exception:\n            pass\n\n        self.http_username = None\n        self.http_password = None\n        try:\n            self.http_username = self._config.get(self.gitlab_id,\n                                                  'http_username')\n            self.http_password = self._config.get(self.gitlab_id,\n                                                  'http_password')\n        except Exception:\n            pass\n\n        self.http_username = None\n        self.http_password = None\n        try:\n            self.http_username = self._config.get(self.gitlab_id,\n                                                  'http_username')\n            self.http_password = self._config.get(self.gitlab_id,\n                                                  'http_password')\n        except Exception:\n            pass\n\n        self.api_version = '4'\n        try:\n            self.api_version = self._config.get('global', 'api_version')\n        except Exception:\n            pass\n        try:\n            self.api_version = self._config.get(self.gitlab_id, 'api_version')\n        except Exception:\n            pass\n        if self.api_version not in ('4',):\n            raise GitlabDataError(\"Unsupported API version: %s\" %\n                                  self.api_version)\n\n        self.per_page = None\n        for section in ['global', self.gitlab_id]:\n            try:\n                self.per_page = self._config.getint(section, 'per_page')\n            except Exception:\n                pass\n        if self.per_page is not None and not 0 <= self.per_page <= 100:\n            raise GitlabDataError(\"Unsupported per_page number: %s\" %\n                                  self.per_page)\n", "path": "gitlab/config.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#\n# Copyright (C) 2013-2017 Gauvain Pocentek <gauvain@pocentek.net>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nfrom __future__ import print_function\n\nimport argparse\nimport functools\nimport importlib\nimport re\nimport sys\n\nimport gitlab.config\n\ncamel_re = re.compile('(.)([A-Z])')\n\n# custom_actions = {\n#    cls: {\n#        action: (mandatory_args, optional_args, in_obj),\n#    },\n# }\ncustom_actions = {}\n\n\ndef register_custom_action(cls_names, mandatory=tuple(), optional=tuple()):\n    def wrap(f):\n        @functools.wraps(f)\n        def wrapped_f(*args, **kwargs):\n            return f(*args, **kwargs)\n\n        # in_obj defines whether the method belongs to the obj or the manager\n        in_obj = True\n        classes = cls_names\n        if type(cls_names) != tuple:\n            classes = (cls_names, )\n\n        for cls_name in classes:\n            final_name = cls_name\n            if cls_name.endswith('Manager'):\n                final_name = cls_name.replace('Manager', '')\n                in_obj = False\n            if final_name not in custom_actions:\n                custom_actions[final_name] = {}\n\n            action = f.__name__.replace('_', '-')\n            custom_actions[final_name][action] = (mandatory, optional, in_obj)\n\n        return wrapped_f\n    return wrap\n\n\ndef die(msg, e=None):\n    if e:\n        msg = \"%s (%s)\" % (msg, e)\n    sys.stderr.write(msg + \"\\n\")\n    sys.exit(1)\n\n\ndef what_to_cls(what):\n    return \"\".join([s.capitalize() for s in what.split(\"-\")])\n\n\ndef cls_to_what(cls):\n    return camel_re.sub(r'\\1-\\2', cls.__name__).lower()\n\n\ndef _get_base_parser(add_help=True):\n    parser = argparse.ArgumentParser(\n        add_help=add_help,\n        description=\"GitLab API Command Line Interface\")\n    parser.add_argument(\"--version\", help=\"Display the version.\",\n                        action=\"store_true\")\n    parser.add_argument(\"-v\", \"--verbose\", \"--fancy\",\n                        help=\"Verbose mode (legacy format only)\",\n                        action=\"store_true\")\n    parser.add_argument(\"-d\", \"--debug\",\n                        help=\"Debug mode (display HTTP requests)\",\n                        action=\"store_true\")\n    parser.add_argument(\"-c\", \"--config-file\", action='append',\n                        help=(\"Configuration file to use. Can be used \"\n                              \"multiple times.\"))\n    parser.add_argument(\"-g\", \"--gitlab\",\n                        help=(\"Which configuration section should \"\n                              \"be used. If not defined, the default selection \"\n                              \"will be used.\"),\n                        required=False)\n    parser.add_argument(\"-o\", \"--output\",\n                        help=\"Output format (v4 only): json|legacy|yaml\",\n                        required=False,\n                        choices=['json', 'legacy', 'yaml'],\n                        default=\"legacy\")\n    parser.add_argument(\"-f\", \"--fields\",\n                        help=(\"Fields to display in the output (comma \"\n                              \"separated). Not used with legacy output\"),\n                        required=False)\n\n    return parser\n\n\ndef _get_parser(cli_module):\n    parser = _get_base_parser()\n    return cli_module.extend_parser(parser)\n\n\ndef _parse_value(v):\n    if isinstance(v, str) and v.startswith('@'):\n        # If the user-provided value starts with @, we try to read the file\n        # path provided after @ as the real value. Exit on any error.\n        try:\n            with open(v[1:]) as fl:\n                return fl.read()\n        except Exception as e:\n            sys.stderr.write(\"%s\\n\" % e)\n            sys.exit(1)\n\n    return v\n\n\ndef main():\n    if \"--version\" in sys.argv:\n        print(gitlab.__version__)\n        exit(0)\n\n    parser = _get_base_parser(add_help=False)\n    if \"--help\" in sys.argv or \"-h\" in sys.argv:\n        parser.print_help()\n        exit(0)\n\n    # This first parsing step is used to find the gitlab config to use, and\n    # load the propermodule (v3 or v4) accordingly. At that point we don't have\n    # any subparser setup\n    (options, args) = parser.parse_known_args(sys.argv)\n    try:\n        config = gitlab.config.GitlabConfigParser(\n            options.gitlab,\n            options.config_file\n        )\n    except gitlab.config.ConfigError as e:\n        sys.exit(e)\n    cli_module = importlib.import_module('gitlab.v%s.cli' % config.api_version)\n\n    # Now we build the entire set of subcommands and do the complete parsing\n    parser = _get_parser(cli_module)\n    args = parser.parse_args(sys.argv[1:])\n\n    config_files = args.config_file\n    gitlab_id = args.gitlab\n    verbose = args.verbose\n    output = args.output\n    fields = []\n    if args.fields:\n        fields = [x.strip() for x in args.fields.split(',')]\n    debug = args.debug\n    action = args.action\n    what = args.what\n\n    args = args.__dict__\n    # Remove CLI behavior-related args\n    for item in ('gitlab', 'config_file', 'verbose', 'debug', 'what', 'action',\n                 'version', 'output'):\n        args.pop(item)\n    args = {k: _parse_value(v) for k, v in args.items() if v is not None}\n\n    try:\n        gl = gitlab.Gitlab.from_config(gitlab_id, config_files)\n        if gl.private_token or gl.oauth_token:\n            gl.auth()\n    except Exception as e:\n        die(str(e))\n\n    if debug:\n        gl.enable_debug()\n\n    cli_module.run(gl, what, action, args, verbose, output, fields)\n\n    sys.exit(0)\n", "path": "gitlab/cli.py"}, {"content": "# -*- coding: utf-8 -*-\n#\n# Copyright (C) 2013-2017 Gauvain Pocentek <gauvain@pocentek.net>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nimport os\n\nfrom six.moves import configparser\n\n_DEFAULT_FILES = [\n    '/etc/python-gitlab.cfg',\n    os.path.expanduser('~/.python-gitlab.cfg')\n]\n\n\nclass ConfigError(Exception):\n    pass\n\n\nclass GitlabIDError(ConfigError):\n    pass\n\n\nclass GitlabDataError(ConfigError):\n    pass\n\n\nclass GitlabConfigMissingError(ConfigError):\n    pass\n\n\nclass GitlabConfigParser(object):\n    def __init__(self, gitlab_id=None, config_files=None):\n        self.gitlab_id = gitlab_id\n        _files = config_files or _DEFAULT_FILES\n        file_exist = False\n        for file in _files:\n            if os.path.exists(file):\n                file_exist = True\n        if not file_exist:\n            raise GitlabConfigMissingError(\n                \"Config file not found. \\nPlease create one in \"\n                \"one of the following locations: {} \\nor \"\n                \"specify a config file using the '-c' parameter.\".format(\n                    \", \".join(_DEFAULT_FILES)\n                )\n            )\n\n        self._config = configparser.ConfigParser()\n        self._config.read(_files)\n\n        if self.gitlab_id is None:\n            try:\n                self.gitlab_id = self._config.get('global', 'default')\n            except Exception:\n                raise GitlabIDError(\"Impossible to get the gitlab id \"\n                                    \"(not specified in config file)\")\n\n        try:\n            self.url = self._config.get(self.gitlab_id, 'url')\n        except Exception:\n            raise GitlabDataError(\"Impossible to get gitlab informations from \"\n                                  \"configuration (%s)\" % self.gitlab_id)\n\n        self.ssl_verify = True\n        try:\n            self.ssl_verify = self._config.getboolean('global', 'ssl_verify')\n        except ValueError:\n            # Value Error means the option exists but isn't a boolean.\n            # Get as a string instead as it should then be a local path to a\n            # CA bundle.\n            try:\n                self.ssl_verify = self._config.get('global', 'ssl_verify')\n            except Exception:\n                pass\n        except Exception:\n            pass\n        try:\n            self.ssl_verify = self._config.getboolean(self.gitlab_id,\n                                                      'ssl_verify')\n        except ValueError:\n            # Value Error means the option exists but isn't a boolean.\n            # Get as a string instead as it should then be a local path to a\n            # CA bundle.\n            try:\n                self.ssl_verify = self._config.get(self.gitlab_id,\n                                                   'ssl_verify')\n            except Exception:\n                pass\n        except Exception:\n            pass\n\n        self.timeout = 60\n        try:\n            self.timeout = self._config.getint('global', 'timeout')\n        except Exception:\n            pass\n        try:\n            self.timeout = self._config.getint(self.gitlab_id, 'timeout')\n        except Exception:\n            pass\n\n        self.private_token = None\n        try:\n            self.private_token = self._config.get(self.gitlab_id,\n                                                  'private_token')\n        except Exception:\n            pass\n\n        self.oauth_token = None\n        try:\n            self.oauth_token = self._config.get(self.gitlab_id, 'oauth_token')\n        except Exception:\n            pass\n\n        self.http_username = None\n        self.http_password = None\n        try:\n            self.http_username = self._config.get(self.gitlab_id,\n                                                  'http_username')\n            self.http_password = self._config.get(self.gitlab_id,\n                                                  'http_password')\n        except Exception:\n            pass\n\n        self.http_username = None\n        self.http_password = None\n        try:\n            self.http_username = self._config.get(self.gitlab_id,\n                                                  'http_username')\n            self.http_password = self._config.get(self.gitlab_id,\n                                                  'http_password')\n        except Exception:\n            pass\n\n        self.api_version = '4'\n        try:\n            self.api_version = self._config.get('global', 'api_version')\n        except Exception:\n            pass\n        try:\n            self.api_version = self._config.get(self.gitlab_id, 'api_version')\n        except Exception:\n            pass\n        if self.api_version not in ('4',):\n            raise GitlabDataError(\"Unsupported API version: %s\" %\n                                  self.api_version)\n\n        self.per_page = None\n        for section in ['global', self.gitlab_id]:\n            try:\n                self.per_page = self._config.getint(section, 'per_page')\n            except Exception:\n                pass\n        if self.per_page is not None and not 0 <= self.per_page <= 100:\n            raise GitlabDataError(\"Unsupported per_page number: %s\" %\n                                  self.per_page)\n", "path": "gitlab/config.py"}]}