mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
Update dotenv, semver, and scandir
Signed-off-by: Dan Ryan <dan@danryan.co>
This commit is contained in:
Vendored
+17
-1
@@ -8,7 +8,8 @@ except ImportError:
|
||||
'Run pip install "python-dotenv[cli]" to fix this.')
|
||||
sys.exit(1)
|
||||
|
||||
from .main import dotenv_values, get_key, set_key, unset_key
|
||||
from .main import dotenv_values, get_key, set_key, unset_key, run_command
|
||||
from .version import __version__
|
||||
|
||||
|
||||
@click.group()
|
||||
@@ -18,6 +19,7 @@ from .main import dotenv_values, get_key, set_key, unset_key
|
||||
@click.option('-q', '--quote', default='always',
|
||||
type=click.Choice(['always', 'never', 'auto']),
|
||||
help="Whether to quote or not the variable values. Default mode is always. This does not affect parsing.")
|
||||
@click.version_option(version=__version__)
|
||||
@click.pass_context
|
||||
def cli(ctx, file, quote):
|
||||
'''This script is used to set, get or unset values from a .env file.'''
|
||||
@@ -78,5 +80,19 @@ def unset(ctx, key):
|
||||
exit(1)
|
||||
|
||||
|
||||
@cli.command(context_settings={'ignore_unknown_options': True})
|
||||
@click.pass_context
|
||||
@click.argument('commandline', nargs=-1, type=click.UNPROCESSED)
|
||||
def run(ctx, commandline):
|
||||
"""Run command with environment variables present."""
|
||||
file = ctx.obj['FILE']
|
||||
dotenv_as_dict = dotenv_values(file)
|
||||
if not commandline:
|
||||
click.echo('No command given.')
|
||||
exit(1)
|
||||
ret = run_command(commandline, dotenv_as_dict)
|
||||
exit(ret)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
||||
|
||||
Vendored
+50
-2
@@ -7,6 +7,7 @@ import io
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
import warnings
|
||||
from collections import OrderedDict
|
||||
|
||||
@@ -30,7 +31,7 @@ def parse_line(line):
|
||||
k, v = line.split('=', 1)
|
||||
|
||||
if k.startswith('export '):
|
||||
k = k.lstrip('export ')
|
||||
(_, _, k) = k.partition('export ')
|
||||
|
||||
# Remove any leading and trailing spaces in key, value
|
||||
k, v = k.strip(), v.strip()
|
||||
@@ -238,7 +239,11 @@ def find_dotenv(filename='.env', raise_error_if_not_found=False, usecwd=False):
|
||||
path = os.getcwd()
|
||||
else:
|
||||
# will work for .py files
|
||||
frame_filename = sys._getframe().f_back.f_code.co_filename
|
||||
frame = sys._getframe()
|
||||
# find first frame that is outside of this file
|
||||
while frame.f_code.co_filename == __file__:
|
||||
frame = frame.f_back
|
||||
frame_filename = frame.f_code.co_filename
|
||||
path = os.path.dirname(os.path.abspath(frame_filename))
|
||||
|
||||
for dirname in _walk_to_root(path):
|
||||
@@ -260,3 +265,46 @@ def load_dotenv(dotenv_path=None, stream=None, verbose=False, override=False):
|
||||
def dotenv_values(dotenv_path=None, stream=None, verbose=False):
|
||||
f = dotenv_path or stream or find_dotenv()
|
||||
return DotEnv(f, verbose=verbose).dict()
|
||||
|
||||
|
||||
def run_command(command, env):
|
||||
"""Run command in sub process.
|
||||
|
||||
Runs the command in a sub process with the variables from `env`
|
||||
added in the current environment variables.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
command: List[str]
|
||||
The command and it's parameters
|
||||
env: Dict
|
||||
The additional environment variables
|
||||
|
||||
Returns
|
||||
-------
|
||||
int
|
||||
The return code of the command
|
||||
|
||||
"""
|
||||
# copy the current environment variables and add the vales from
|
||||
# `env`
|
||||
cmd_env = os.environ.copy()
|
||||
cmd_env.update(env)
|
||||
|
||||
p = Popen(command,
|
||||
stdin=PIPE,
|
||||
stdout=PIPE,
|
||||
stderr=STDOUT,
|
||||
universal_newlines=True,
|
||||
bufsize=0,
|
||||
shell=False,
|
||||
env=cmd_env)
|
||||
try:
|
||||
out, _ = p.communicate()
|
||||
print(out)
|
||||
except Exception:
|
||||
warnings.warn('An error occured, running the command:')
|
||||
out, _ = p.communicate()
|
||||
warnings.warn(out)
|
||||
|
||||
return p.returncode
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
__version__ = "0.9.1"
|
||||
Vendored
+15
-2
@@ -23,7 +23,6 @@ from os import listdir, lstat, stat, strerror
|
||||
from os.path import join, islink
|
||||
from stat import S_IFDIR, S_IFLNK, S_IFREG
|
||||
import collections
|
||||
import os
|
||||
import sys
|
||||
|
||||
_scandir = None
|
||||
@@ -38,7 +37,7 @@ if _scandir is None and ctypes is None:
|
||||
warnings.warn("scandir can't find the compiled _scandir C module "
|
||||
"or ctypes, using slow generic fallback")
|
||||
|
||||
__version__ = '1.7'
|
||||
__version__ = '1.9.0'
|
||||
__all__ = ['scandir', 'walk']
|
||||
|
||||
# Windows FILE_ATTRIBUTE constants for interpreting the
|
||||
@@ -93,6 +92,10 @@ class GenericDirEntry(object):
|
||||
self._lstat = lstat(self.path)
|
||||
return self._lstat
|
||||
|
||||
# The code duplication below is intentional: this is for slightly
|
||||
# better performance on systems that fall back to GenericDirEntry.
|
||||
# It avoids an additional attribute lookup and method call, which
|
||||
# are relatively slow on CPython.
|
||||
def is_dir(self, follow_symlinks=True):
|
||||
try:
|
||||
st = self.stat(follow_symlinks=follow_symlinks)
|
||||
@@ -416,6 +419,16 @@ elif sys.platform.startswith(('linux', 'darwin', 'sunos5')) or 'bsd' in sys.plat
|
||||
('d_type', ctypes.c_byte),
|
||||
('d_name', ctypes.c_char * 256),
|
||||
)
|
||||
elif 'openbsd' in sys.platform:
|
||||
_fields_ = (
|
||||
('d_ino', ctypes.c_uint64),
|
||||
('d_off', ctypes.c_uint64),
|
||||
('d_reclen', ctypes.c_uint16),
|
||||
('d_type', ctypes.c_uint8),
|
||||
('d_namlen', ctypes.c_uint8),
|
||||
('__d_padding', ctypes.c_uint8 * 4),
|
||||
('d_name', ctypes.c_char * 256),
|
||||
)
|
||||
else:
|
||||
_fields_ = (
|
||||
('d_ino', ctypes.c_uint32), # must be uint32, not ulong
|
||||
|
||||
Vendored
+143
-12
@@ -6,7 +6,7 @@ import collections
|
||||
import re
|
||||
|
||||
|
||||
__version__ = '2.8.0'
|
||||
__version__ = '2.8.1'
|
||||
__author__ = 'Kostiantyn Rybnikov'
|
||||
__author_email__ = 'k-bx@k-bx.com'
|
||||
__maintainer__ = 'Sebastien Celles'
|
||||
@@ -46,6 +46,19 @@ def parse(version):
|
||||
and 'prerelease'. The prerelease or build keys can be None
|
||||
if not provided
|
||||
:rtype: dict
|
||||
|
||||
>>> import semver
|
||||
>>> ver = semver.parse('3.4.5-pre.2+build.4')
|
||||
>>> ver['major']
|
||||
3
|
||||
>>> ver['minor']
|
||||
4
|
||||
>>> ver['patch']
|
||||
5
|
||||
>>> ver['prerelease']
|
||||
'pre.2'
|
||||
>>> ver['build']
|
||||
'build.4'
|
||||
"""
|
||||
match = _REGEX.match(version)
|
||||
if match is None:
|
||||
@@ -60,8 +73,7 @@ def parse(version):
|
||||
return version_parts
|
||||
|
||||
|
||||
class VersionInfo(collections.namedtuple(
|
||||
'VersionInfo', 'major minor patch prerelease build')):
|
||||
class VersionInfo(object):
|
||||
"""
|
||||
:param int major: version when you make incompatible API changes.
|
||||
:param int minor: version when you add functionality in
|
||||
@@ -69,14 +81,48 @@ class VersionInfo(collections.namedtuple(
|
||||
:param int patch: version when you make backwards-compatible bug fixes.
|
||||
:param str prerelease: an optional prerelease string
|
||||
:param str build: an optional build string
|
||||
|
||||
>>> import semver
|
||||
>>> ver = semver.parse('3.4.5-pre.2+build.4')
|
||||
>>> ver
|
||||
{'build': 'build.4', 'major': 3, 'minor': 4, 'patch': 5,
|
||||
'prerelease': 'pre.2'}
|
||||
"""
|
||||
__slots__ = ()
|
||||
__slots__ = ('_major', '_minor', '_patch', '_prerelease', '_build')
|
||||
|
||||
def __init__(self, major, minor, patch, prerelease=None, build=None):
|
||||
self._major = major
|
||||
self._minor = minor
|
||||
self._patch = patch
|
||||
self._prerelease = prerelease
|
||||
self._build = build
|
||||
|
||||
@property
|
||||
def major(self):
|
||||
return self._major
|
||||
|
||||
@property
|
||||
def minor(self):
|
||||
return self._minor
|
||||
|
||||
@property
|
||||
def patch(self):
|
||||
return self._patch
|
||||
|
||||
@property
|
||||
def prerelease(self):
|
||||
return self._prerelease
|
||||
|
||||
@property
|
||||
def build(self):
|
||||
return self._build
|
||||
|
||||
def _astuple(self):
|
||||
return (self.major, self.minor, self.patch,
|
||||
self.prerelease, self.build)
|
||||
|
||||
def _asdict(self):
|
||||
return collections.OrderedDict((
|
||||
("major", self.major),
|
||||
("minor", self.minor),
|
||||
("patch", self.patch),
|
||||
("prerelease", self.prerelease),
|
||||
("build", self.build)
|
||||
))
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, (VersionInfo, dict)):
|
||||
@@ -108,11 +154,31 @@ class VersionInfo(collections.namedtuple(
|
||||
return NotImplemented
|
||||
return _compare_by_keys(self._asdict(), _to_dict(other)) >= 0
|
||||
|
||||
def __repr__(self):
|
||||
s = ", ".join("%s=%r" % (key, val)
|
||||
for key, val in self._asdict().items())
|
||||
return "VersionInfo(%s)" % s
|
||||
|
||||
def __str__(self):
|
||||
return format_version(*self)
|
||||
return format_version(*(self._astuple()))
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self))
|
||||
return hash(self._astuple())
|
||||
|
||||
@staticmethod
|
||||
def parse(version):
|
||||
"""Parse version string to a VersionInfo instance.
|
||||
|
||||
>>> from semver import VersionInfo
|
||||
>>> VersionInfo.parse('3.4.5-pre.2+build.4')
|
||||
VersionInfo(major=3, minor=4, patch=5, \
|
||||
prerelease='pre.2', build='build.4')
|
||||
|
||||
:param version: version string
|
||||
:return: a :class:`VersionInfo` instance
|
||||
:rtype: :class:`VersionInfo`
|
||||
"""
|
||||
return parse_version_info(version)
|
||||
|
||||
|
||||
def _to_dict(obj):
|
||||
@@ -127,6 +193,19 @@ def parse_version_info(version):
|
||||
:param version: version string
|
||||
:return: a :class:`VersionInfo` instance
|
||||
:rtype: :class:`VersionInfo`
|
||||
|
||||
>>> import semver
|
||||
>>> version_info = semver.parse_version_info("3.4.5-pre.2+build.4")
|
||||
>>> version_info.major
|
||||
3
|
||||
>>> version_info.minor
|
||||
4
|
||||
>>> version_info.patch
|
||||
5
|
||||
>>> version_info.prerelease
|
||||
'pre.2'
|
||||
>>> version_info.build
|
||||
'build.4'
|
||||
"""
|
||||
parts = parse(version)
|
||||
version_info = VersionInfo(
|
||||
@@ -190,6 +269,14 @@ def compare(ver1, ver2):
|
||||
:return: The return value is negative if ver1 < ver2,
|
||||
zero if ver1 == ver2 and strictly positive if ver1 > ver2
|
||||
:rtype: int
|
||||
|
||||
>>> import semver
|
||||
>>> semver.compare("1.0.0", "2.0.0")
|
||||
-1
|
||||
>>> semver.compare("2.0.0", "1.0.0")
|
||||
1
|
||||
>>> semver.compare("2.0.0", "2.0.0")
|
||||
0
|
||||
"""
|
||||
|
||||
v1, v2 = parse(ver1), parse(ver2)
|
||||
@@ -210,6 +297,12 @@ def match(version, match_expr):
|
||||
!= not equal
|
||||
:return: True if the expression matches the version, otherwise False
|
||||
:rtype: bool
|
||||
|
||||
>>> import semver
|
||||
>>> semver.match("2.0.0", ">=1.0.0")
|
||||
True
|
||||
>>> semver.match("1.0.0", ">1.0.0")
|
||||
False
|
||||
"""
|
||||
prefix = match_expr[:2]
|
||||
if prefix in ('>=', '<=', '==', '!='):
|
||||
@@ -245,6 +338,10 @@ def max_ver(ver1, ver2):
|
||||
:param ver2: version string 2
|
||||
:return: the greater version of the two
|
||||
:rtype: :class:`VersionInfo`
|
||||
|
||||
>>> import semver
|
||||
>>> semver.max_ver("1.0.0", "2.0.0")
|
||||
'2.0.0'
|
||||
"""
|
||||
cmp_res = compare(ver1, ver2)
|
||||
if cmp_res == 0 or cmp_res == 1:
|
||||
@@ -260,6 +357,10 @@ def min_ver(ver1, ver2):
|
||||
:param ver2: version string 2
|
||||
:return: the smaller version of the two
|
||||
:rtype: :class:`VersionInfo`
|
||||
|
||||
>>> import semver
|
||||
>>> semver.min_ver("1.0.0", "2.0.0")
|
||||
'1.0.0'
|
||||
"""
|
||||
cmp_res = compare(ver1, ver2)
|
||||
if cmp_res == 0 or cmp_res == -1:
|
||||
@@ -278,6 +379,10 @@ def format_version(major, minor, patch, prerelease=None, build=None):
|
||||
:param str build: the optional build part of a version
|
||||
:return: the formatted string
|
||||
:rtype: str
|
||||
|
||||
>>> import semver
|
||||
>>> semver.format_version(3, 4, 5, 'pre.2', 'build.4')
|
||||
'3.4.5-pre.2+build.4'
|
||||
"""
|
||||
version = "%d.%d.%d" % (major, minor, patch)
|
||||
if prerelease is not None:
|
||||
@@ -308,6 +413,10 @@ def bump_major(version):
|
||||
:param: version string
|
||||
:return: the raised version string
|
||||
:rtype: str
|
||||
|
||||
>>> import semver
|
||||
>>> semver.bump_major("3.4.5")
|
||||
'4.0.0'
|
||||
"""
|
||||
verinfo = parse(version)
|
||||
return format_version(verinfo['major'] + 1, 0, 0)
|
||||
@@ -319,6 +428,10 @@ def bump_minor(version):
|
||||
:param: version string
|
||||
:return: the raised version string
|
||||
:rtype: str
|
||||
|
||||
>>> import semver
|
||||
>>> semver.bump_minor("3.4.5")
|
||||
'3.5.0'
|
||||
"""
|
||||
verinfo = parse(version)
|
||||
return format_version(verinfo['major'], verinfo['minor'] + 1, 0)
|
||||
@@ -330,6 +443,10 @@ def bump_patch(version):
|
||||
:param: version string
|
||||
:return: the raised version string
|
||||
:rtype: str
|
||||
|
||||
>>> import semver
|
||||
>>> semver.bump_patch("3.4.5")
|
||||
'3.4.6'
|
||||
"""
|
||||
verinfo = parse(version)
|
||||
return format_version(verinfo['major'], verinfo['minor'],
|
||||
@@ -343,6 +460,9 @@ def bump_prerelease(version, token='rc'):
|
||||
:param token: defaults to 'rc'
|
||||
:return: the raised version string
|
||||
:rtype: str
|
||||
|
||||
>>> bump_prerelease('3.4.5', 'dev')
|
||||
'3.4.5-dev.1'
|
||||
"""
|
||||
verinfo = parse(version)
|
||||
verinfo['prerelease'] = _increment_string(
|
||||
@@ -359,6 +479,9 @@ def bump_build(version, token='build'):
|
||||
:param token: defaults to 'build'
|
||||
:return: the raised version string
|
||||
:rtype: str
|
||||
|
||||
>>> bump_build('3.4.5-rc.1+build.9')
|
||||
'3.4.5-rc.1+build.10'
|
||||
"""
|
||||
verinfo = parse(version)
|
||||
verinfo['build'] = _increment_string(
|
||||
@@ -374,6 +497,14 @@ def finalize_version(version):
|
||||
:param version: version string
|
||||
:return: the finalized version string
|
||||
:rtype: str
|
||||
|
||||
>>> finalize_version('1.2.3-rc.5')
|
||||
'1.2.3'
|
||||
"""
|
||||
verinfo = parse(version)
|
||||
return format_version(verinfo['major'], verinfo['minor'], verinfo['patch'])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
Reference in New Issue
Block a user