Source code for skelpy.utils.helpers
#!/usr/bin/env python
# encoding: utf-8
"""Other helper functions"""
from __future__ import print_function, absolute_import
import sys
import os
[docs]def is_valid_identifier(string):
"""Check if the string is a valid project/package name.
.. note::
Valid characters for ``projectName`` are::
* uppercase and lowercase letters A through Z
* underscore '_'
* the digits 0 through 9 except for the first character
Args:
string (str): project/package name
Returns:
bool: True if string is valid project/package name else False
"""
import re
import keyword
if not re.match("[_A-Za-z][_a-zA-Z0-9]*$", string):
return False
if keyword.iskeyword(string):
return False
return True
[docs]def has_command(cmd):
"""Check if the given command is available on the system
Args:
cmd (str): command to check
Returns:
bool: True if available, otherwise False
"""
import subprocess
try:
from subprocess import DEVNULL
except ImportError:
DEVNULL = open(os.devnull, 'wb')
if sys.platform == 'win32':
checker = 'where'
else: # linux, OSX, cygwin
checker = 'which'
return not bool(subprocess.call([checker, cmd], stdout=DEVNULL, stderr=DEVNULL))
[docs]def has_module(modName):
"""Check if the module is installed
Args:
modName (str): module name to check
Returns:
bool: True if installed, otherwise False
"""
from pkgutil import iter_modules
return modName in (name for loader, name, ispkg in iter_modules())
[docs]def get_gitConfig():
"""read ``.gitconfig`` file in the user's ``$HOME`` directory, if exists
Returns:
:class:`ConfigParser` or None: ConfigParser object filled with info
read from ``.gitconfig``
"""
import errno
try:
from configparser import ConfigParser
except ImportError:
from ConfigParser import ConfigParser
home = 'HOMEPATH' if sys.platform == 'win32' else 'HOME'
git_config_file = os.path.join(os.environ[home], '.gitconfig')
try:
with open(git_config_file, 'r') as f:
data = f.readlines()
except (IOError, OSError) as e: # no .gitconfig
if e.errno == errno.ENOENT:
return None
try:
from StringIO import StringIO # python 2
except ImportError:
from io import StringIO # python 3
# white space on the left side hinders ConfigParse's parsing
stripped_data = ''.join([line.lstrip() for line in data])
fp = StringIO(stripped_data)
gitConfig = ConfigParser()
if sys.version_info[0] == 2:
gitConfig.readfp(fp)
else:
gitConfig.read_file(fp)
return gitConfig
[docs]def get_userName():
"""read the user's name from ``.gitconfig`` file in the ``$HOME`` directory or
the environmental variable ``USER``
Returns:
str: user's name
"""
try:
from configparser import NoOptionError
except ImportError:
from ConfigParser import NoOptionError
name = ''
# first, try .gitconfig
gitConfig = get_gitConfig()
if gitConfig:
try:
name = gitConfig.get('user', 'name')
except (KeyError, NoOptionError):
pass
# if fail, try environment variables
if not name:
user = 'USERNAME' if sys.platform == 'win32' else 'USER'
name = os.environ.get(user, '')
return name
[docs]def get_email():
"""read the user's name from ``.gitconfig`` file in the ``$HOME`` directory.
If ``.gitconfig`` file does not exist, this function improvises an email
address by concatenating user's name and host name.
Returns:
str: user's email address
"""
from six.moves.configparser import NoOptionError
email = ''
gitConfig = get_gitConfig()
if gitConfig:
try:
email = gitConfig.get('user', 'email')
except (KeyError, NoOptionError):
pass
# if not successful, we improvise
if not email:
import socket
user = get_userName()
host = socket.gethostname()
email = "{user}@{host}".format(user=user, host=host)
return email
[docs]def get_python_version(short=False):
"""get system's python version
Args:
short (bool): select the short version number(major.minor only) or not
Returns:
str: major.minor if *short* is True, major.minor.release otherwise
"""
long_ver = sys.version.split()[0]
short_ver = '.'.join(long_ver.split('.')[:2])
return short_ver if short else long_ver
[docs]def read_setup_cfg(cfg_file):
"""read ``setup.cfg`` file
``cfg_file`` may contain a path
Note:
:func:`setuptools.config.read_configuration` has a `problem with encoding under python2`_
Args:
cfg_file (str): path of ``setup.cfg`` file
Returns:
dict: information read from the setup.cfg file if successful, otherwise an empty dict.
.. _problem with encoding under python2:
https://github.com/pypa/setuptools/issues/1136
"""
conf_dict = {}
try:
from StringIO import StringIO # python 2
except ImportError:
from io import StringIO # python 3
try:
from configparser import ConfigParser # python3
except ImportError:
from ConfigParser import ConfigParser # python2
try:
with open(cfg_file, 'r') as f:
data = f.read()
content = StringIO(remove_comment_lines_in_str(data))
except IOError:
return conf_dict
parser = ConfigParser()
if sys.version_info[0] == 2:
parser.readfp(content)
else:
parser.read_file(content)
# prevent pollution by too many options
sections_to_read = ['metadata', 'options', 'options.packages.find']
for section in sections_to_read:
options = parser.options(section)
for opt in options:
value = parser.get(section, opt)
conf_dict[opt] = value[1:] if value.startswith('\n') else value
# remove leading '=' of package_dir
package_dir = conf_dict['package_dir']
conf_dict['package_dir'] = package_dir.split('=')[-1].strip()
# special handling for 'extras_require' section
section = 'options.extras_require'
require = []
options = parser.options('options.extras_require')
for opt in options:
val_list = parser.get(section, opt).split('; ')
require.append(repr(opt) + ': ' + str(val_list))
conf_dict['extras_require'] = '\n'.join(require)
return conf_dict
[docs]def is_rootDir(path):
"""check if the path given is the root directory
Args:
path (str): path to check
Returns:
bool: True if the *path* is root directory, False otherwise
"""
if path == '':
return False
return os.path.dirname(path) == path
[docs]def root_path():
"""get the root path
This function is OS-independent.
"""
return os.path.abspath(os.sep)