docmanagerconfig()   F
last analyzed

Complexity

Conditions 9

Size

Total Lines 91

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 9
c 4
b 0
f 0
dl 0
loc 91
rs 3.3804

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
#
2
# Copyright (c) 2014-2015 SUSE Linux GmbH
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of version 3 of the GNU General Public License as
6
# published by the Free Software Foundation.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, contact SUSE LLC.
15
#
16
# To contact SUSE about this file by physical or electronic mail,
17
# you may find current contact information at www.suse.com
18
19
import os
20
import shlex
21
import subprocess
22
import sys
23
from configparser import ConfigParser
24
from docmanager.exceptions import DMConfigFileNotFound
25
from docmanager.logmanager import log
26
27
BASECONFIG_NAME = 'docmanager.conf'
28
CONFIG_NAME = os.path.join('docmanager', BASECONFIG_NAME)
29
GLOBAL_CONFIG = [os.path.join('/etc', CONFIG_NAME)]
30
GIT_CONFIG = None # Will be set below
31
XDG_CONFIG_HOME = os.path.expanduser(os.environ.get('XDG_CONFIG_HOME', '~/.config/'))
32
USER_CONFIG = os.path.join(XDG_CONFIG_HOME, CONFIG_NAME)
33
34
def get_git_repo_config():
35
    """Return root Git repository, if available
36
37
    :return: absolut path to Git repository
38
    :rtype: str
39
    """
40
    try:
41
        cmd = shlex.split("git rev-parse --show-toplevel")
42
        git = subprocess.Popen(cmd,
43
                               stdout=subprocess.PIPE,
44
                               stderr=subprocess.PIPE)
45
        gitrepo = git.communicate()
46
        # Not a git repository?
47
        if git.returncode != 128:
48
            gitrepo = gitrepo[0].decode("utf-8").strip()
49
            return os.path.join(gitrepo, os.path.join('.git', BASECONFIG_NAME))
50
51
    except FileNotFoundError: # pylint:disable=undefined-variable
52
        # If we don't find the git command, we skip the local config file
53
        # alltogether
54
        return None
55
56
57
GIT_CONFIG = get_git_repo_config()
58
59
60
def docmanagerconfig(cfgfiles=None, include_etc=True):
61
    """Read DocManager configuration files. The following files are
62
       searched for and its configuration is merged together
63
       (in this order, from lowest to highest):
64
65
       * /etc/docmanager/config
66
       * $XDG_CONFIG_HOME/docmanager/docmanager.config if not found, falls back
67
         to ~/.config/docmanager/docmanager.config
68
       * GIT_REPO_DIR/.git/docmanager.conf
69
         (GIT_REPO_DIR is retrieved by the command
70
         `git rev-parse --show-toplevel`)
71
       * DOCMANAGER_GIT_REPO/etc/config
72
73
      See the XDG Base Directory Specification:
74
      http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
75
76
      :param list cfgfiles: your own list of configfiles
77
      :param bool include_etc: Should the develop(!) 'etc/' directory included?
78
                               Only useful for development
79
      :return: merged configuration object
80
      :rtype: configparser.ConfigParser
81
82
    """
83
    # Start with the global ones
84
    configfiles = GLOBAL_CONFIG[:]
85
86
    if cfgfiles is None:
87
        # We need to assemble our configuration file list
88
        #
89
        # Append user config; env variable XDG_CONFIG_HOME is used if set
90
        configfiles.append(USER_CONFIG)
91
92
        # Append config when a .git repo is found
93
        gitcfg = get_git_repo_config()
94
        if gitcfg:
95
            configfiles.append(gitcfg)
96
    else:
97
        log.debug("Using own config file %s", cfgfiles)
98
        # In case the user passes its own config file list, use it but
99
        # take care, it's a list:
100
        if isinstance(cfgfiles, str):
101
            configfiles = [cfgfiles]
102
        else:
103
            configfiles = cfgfiles
104
105
    # Support pyvenv virtual environments; add it as a last item
106
    #
107
    # See http://stackoverflow.com/a/1883251
108
    if (cfgfiles is None) and include_etc and hasattr(sys, 'base_prefix'):
109
        #dd = os.path.dirname(__file__)
110
        #cc = os.path.join(dd, BASECONFIG_NAME)
111
        #configfiles.append(cc)
112
        #log.debug("Running inside a virtual env, using %s", cc)
113
        #
114
        # When code with __file__ is packed inside a zipfile, it can no longer
115
        # assume that __file__ or __path__ contain filenames or directory
116
        # names, and so it will fail (see also PEP 302)
117
        #
118
        # As such:
119
        # 1. First try to use pkg_resources from setuptools (which is installed
120
        #    anyway in a virtual Python environment)
121
        # 2. If that doesn't work, fallback to the __file__ method
122
        #
123
        # Source:
124
        # http://peak.telecommunity.com/DevCenter/PythonEggs#accessing-package-resources
125
        #
126
        try:
127
            from pkg_resources import resource_filename
128
            cc = resource_filename(__name__, BASECONFIG_NAME)
129
            configfiles.append(cc)
130
        except ImportError:
131
            # Use fallback method
132
            dd = os.path.dirname(__file__)
133
            cc = os.path.join(dd, BASECONFIG_NAME)
134
            configfiles.append(cc)
135
        log.info("Running inside a virtual env, using %r", configfiles[-1])
136
137
    config = ConfigParser()
138
    x = config.read(configfiles)
139
140
    if not x:
141
142
        raise DMConfigFileNotFound(configfiles)
143
144
    # Save state of configuration files
145
    config.configfiles = configfiles
146
    config.usedconfigfile = x
147
    log.debug("All configfiles %s", configfiles)
148
    log.debug("Used config file: %s", x)
149
150
    return config
151
152
153
def create_userconfig():
154
    """Copies template for user config to USER_CONFIG
155
       If user config already exists, do nothing
156
157
     :raise: FileNotFoundError
158
    """
159
    if os.path.exists(USER_CONFIG):
160
        return
161
162
    import shutil
163
164
    tmpldir = os.path.join(os.path.dirname(__file__), "template")
165
    cfgtmpl = os.path.join(tmpldir, "config")
166
167
    # From http://stackoverflow.com/a/600612
168
    try:
169
        os.makedirs(os.path.dirname(USER_CONFIG))
170
        log.debug("UserConfig: Created directory for %s", USER_CONFIG)
171
    except OSError as err:
172
        import errno
173
        if not(err.errno == errno.EEXIST and os.path.isdir(tmpldir)):
174
            raise
175
176
    shutil.copyfile(cfgtmpl, USER_CONFIG)
177
    log.debug("UserConfig: Copied template %s to %s", cfgtmpl, USER_CONFIG)
178