KApiDox

utils.py
1 # -*- coding: utf-8 -*-
2 #
3 # SPDX-FileCopyrightText: 2014 Aurélien Gâteau <[email protected]>
4 #
5 # SPDX-License-Identifier: BSD-2-Clause
6 
7 from fnmatch import fnmatch
8 import logging
9 import os
10 import re
11 import subprocess
12 import shutil
13 import sys
14 import tempfile
15 import requests
16 
17 ## @package kapidox.utils
18 #
19 # Multiple usage utils.
20 #
21 # This module contains code which is shared between depdiagram-prepare and
22 # other components.
23 #
24 # Code in this dir should not import any module which is not shipped with
25 # Python because this module is used by depdiagram-prepare, which must be able
26 # to run on builds.kde.org, which may not have all the required dependencies.
27 #
28 
29 def setup_logging():
30  FORMAT = '%(asctime)s %(levelname)s %(message)s'
31  logging.basicConfig(format=FORMAT, datefmt='%H:%M:%S', level=logging.DEBUG)
32 
33 
34 def tolist(a):
35  """ Return a list based on `a`. """
36  return a if type(a) is list else [a]
37 
38 
39 def serialize_name(name):
40  """ Return a serialized name.
41 
42  For now it only replaces ' ' with '_' and lower the letters.
43  """
44  if name is not None:
45  return '_'.join(name.lower().split(' '))
46  else:
47  return None
48 
49 def set_repopath(id):
50  """ Return the repopath for the repo id, queried from projects.kde.org
51 
52  Args:
53  id: unique KDE repo identifier
54  """
55  if id is None:
56  return None
57 
58  try:
59  r = requests.get('https://projects.kde.org/api/v1/identifier/' + id)
60  return r.json()['repo']
61  except Exception as exc:
62  # Catch all exceptions here: whatever fails in this function should not
63  # cause the code to fail
64  logging.warning("Failed to get repository url for '{}' from projects.kde.org: {}".format(id, exc))
65  # This means there is no canonical repo identifier for this repo:
66  # generally that means that the repo was checked out into a non-
67  # canonical pathname (e.g. kitemviews checkout out into a directory
68  # called KItemViews, or kitemviews.git .. anything other than
69  # kitemviews is not recognized).
70  return None
71 
72 def set_maintainers(maintainer_keys, all_maintainers):
73  """ Expend the name of the maintainers.
74 
75  Args:
76  dictionary: (dict) Dictionary from which the name to expend will be read.
77  key: (string) Key of the dictionary where the name to expend is saved.
78  all_maintainers: (dict of dict) Look-up table where the names and emails of
79  the maintainers are stored.
80 
81  Examples:
82  >>> maintainer_keys = ['arthur', 'toto']
83 
84  >>> myteam = {'arthur': {'name': 'Arthur Pendragon',
85  'email': '[email protected]'},
86  'toto': {'name': 'Toto',
87  'email: '[email protected]'}
88  }
89 
90  >>> set_maintainers(maintainer_keys, my_team)
91  """
92 
93  if not maintainer_keys:
94  maintainers = []
95  elif isinstance(maintainer_keys, list):
96  maintainers = map(lambda x: all_maintainers.get(x, None),
97  maintainer_keys)
98  else:
99  maintainers = [all_maintainers.get(maintainer_keys, None)]
100 
101  maintainers = [x for x in maintainers if x is not None]
102  return maintainers
103 
104 
105 def parse_fancyname(fw_dir):
106  """Return the framework name for a given source dir
107 
108  The framework name is the name of the toplevel CMake project
109  """
110  cmakelists_path = os.path.join(fw_dir, "CMakeLists.txt")
111  if not os.path.exists(cmakelists_path):
112  for f in os.listdir(fw_dir):
113  if ".qbs" in f and not "Test" in f:
114  return f[:-4]
115  logging.error("No CMakeLists.txt in {}".format(fw_dir))
116  return None
117  project_re = re.compile(r"^\s*project\s*\(\s*([\w\-\_]+)", re.I | re.M)
118  with open(cmakelists_path) as f:
119  cmakelists_content = f.read()
120  match = project_re.search(cmakelists_content)
121  if match:
122  return match.group(1)
123 
124  logging.error("Failed to find framework name: Could not find a "
125  "'project()' command in {}.".format(cmakelists_path))
126  return None
127 
128 
129 def cache_dir():
130  """Find/create a semi-long-term cache directory.
131 
132  We do not use tempdir, except as a fallback, because temporary directories
133  are intended for files that only last for the program's execution.
134  """
135  cachedir = None
136  if sys.platform == 'darwin':
137  try:
138  from AppKit import NSSearchPathForDirectoriesInDomains
139  # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains
140  # NSApplicationSupportDirectory = 14
141  # NSUserDomainMask = 1
142  # True for expanding the tilde into a fully qualified path
143  cachedir = os.path.join(
144  NSSearchPathForDirectoriesInDomains(14, 1, True)[0],
145  'KApiDox')
146  except:
147  pass
148  elif os.name == "posix":
149  if 'HOME' in os.environ and os.path.exists(os.environ['HOME']):
150  cachedir = os.path.join(os.environ['HOME'], '.cache', 'kapidox')
151  elif os.name == "nt":
152  if 'APPDATA' in os.environ and os.path.exists(os.environ['APPDATA']):
153  cachedir = os.path.join(os.environ['APPDATA'], 'KApiDox')
154  if cachedir is None:
155  cachedir = os.path.join(tempfile.gettempdir(), 'kapidox')
156  if not os.path.isdir(cachedir):
157  os.makedirs(cachedir)
158  return cachedir
159 
160 
161 def svn_export(remote, local, overwrite=False):
162  """Wraps svn export.
163 
164  Args:
165  remote: (string) the remote url.
166  local: (string) the local path where to download.
167  overwrite: (bool) whether to overwrite `local` or not. (optional,
168  default = False)
169 
170  Returns:
171  True if success.
172 
173  Raises:
174  FileNotFoundError: &nbsp;
175  subprocess.CalledProcessError: &nbsp;
176  """
177  try:
178  import svn.core
179  import svn.client
180  logging.debug("Using Python libsvn bindings to fetch %s", remote)
181  ctx = svn.client.create_context()
182  ctx.auth_baton = svn.core.svn_auth_open([])
183 
184  latest = svn.core.svn_opt_revision_t()
185  latest.type = svn.core.svn_opt_revision_head
186 
187  svn.client.export(remote, local, latest, True, ctx)
188  except ImportError:
189  logging.debug("Using external svn client to fetch %s", remote)
190  cmd = ['svn', 'export', '--quiet']
191  if overwrite:
192  cmd.append('--force')
193  cmd += [remote, local]
194  try:
195  subprocess.check_call(cmd, stderr=subprocess.STDOUT)
196  except subprocess.CalledProcessError as e:
197  raise subprocess.StandardException(e.output)
198  except FileNotFoundError as e:
199  logging.debug("External svn client not found")
200  return False
201  # subversion will set the timestamp to match the server
202  os.utime(local, None)
203  return True
204 
205 
206 def copy_dir_contents(directory, dest):
207  """Copy the contents of a directory
208 
209  Args:
210  directory: (string) the directory to copy the contents of.
211  dest: (string) the directory to copy them into.
212  """
213  ignored = ['CMakeLists.txt']
214  ignore = shutil.ignore_patterns(*ignored)
215  for fn in os.listdir(directory):
216  f = os.path.join(directory, fn)
217  if os.path.isfile(f):
218  docopy = True
219  for i in ignored:
220  if fnmatch(fn, i):
221  docopy = False
222  break
223  if docopy:
224  shutil.copy(f, dest)
225  elif os.path.isdir(f):
226  dest_f = os.path.join(dest, fn)
227  if os.path.isdir(dest_f):
228  shutil.rmtree(dest_f)
229  shutil.copytree(f, dest_f, ignore=ignore)
230 
231 
232 _KAPIDOX_VERSION = None
233 def get_kapidox_version():
234  """Get commit id of running code if it is running from git repository.
235 
236  May return an empty string if it failed to extract the commit id.
237 
238  Assumes .git/HEAD looks like this:
239 
240  ref: refs/heads/master
241 
242  and assumes .git/refs/heads/master contains the commit id
243  """
244  global _KAPIDOX_VERSION
245 
246  if _KAPIDOX_VERSION is not None:
247  return _KAPIDOX_VERSION
248 
249  _KAPIDOX_VERSION = ""
250  bin_dir = os.path.dirname(sys.argv[0])
251  git_dir = os.path.join(bin_dir, "..", ".git")
252  if not os.path.isdir(git_dir):
253  # Looks like we are not running from the git repo, exit silently
254  return _KAPIDOX_VERSION
255 
256  git_HEAD = os.path.join(git_dir, "HEAD")
257  if not os.path.isfile(git_HEAD):
258  logging.warning("Getting git info failed: {} is not a file".format(git_HEAD))
259  return _KAPIDOX_VERSION
260 
261  try:
262  line = open(git_HEAD).readline()
263  ref_name = line.split(": ")[1].strip()
264  with open(os.path.join(git_dir, ref_name)) as f:
265  _KAPIDOX_VERSION = f.read().strip()
266  except Exception as exc:
267  # Catch all exceptions here: whatever fails in this function should not
268  # cause the code to fail
269  logging.warning("Getting git info failed: {}".format(exc))
270  return _KAPIDOX_VERSION
271 
272 
273 def find_dot_files(dot_dir):
274  """Returns a list of path to files ending with .dot in subdirs of `dot_dir`."""
275  lst = []
276  for (root, dirs, files) in os.walk(dot_dir):
277  lst.extend([os.path.join(root, x) for x in files if x.endswith('.dot')])
278  return lst
def serialize_name(name)
Return a serialized name.
Definition: utils.py:43
def parse_fancyname(fw_dir)
Return the framework name for a given source dir.
Definition: utils.py:113
def find_dot_files(dot_dir)
Returns a list of path to files ending with .dot in subdirs of dot_dir.
Definition: utils.py:287
def set_repopath(id)
Return the repopath for the repo id, queried from projects.kde.org.
Definition: utils.py:54
def tolist(a)
Return a list based on a.
Definition: utils.py:35
def cache_dir()
Find/create a semi-long-term cache directory.
Definition: utils.py:138
def svn_export(remote, local, overwrite=False)
Wraps svn export.
Definition: utils.py:180
def get_kapidox_version()
Get commit id of running code if it is running from git repository.
Definition: utils.py:250
def set_maintainers(maintainer_keys, all_maintainers)
Expend the name of the maintainers.
Definition: utils.py:95
def copy_dir_contents(directory, dest)
Copy the contents of a directory.
Definition: utils.py:216
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 16 2021 22:55:44 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.