Hello community, here is the log from the commit of package python-dparse for openSUSE:Leap:15.2 checked in at 2020-04-08 12:49:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Leap:15.2/python-dparse (Old) and /work/SRC/openSUSE:Leap:15.2/.python-dparse.new.3248 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-dparse" Wed Apr 8 12:49:04 2020 rev:2 rq:791640 version:0.5.0 Changes: -------- --- /work/SRC/openSUSE:Leap:15.2/python-dparse/python-dparse.changes 2020-02-22 18:49:30.276368694 +0100 +++ /work/SRC/openSUSE:Leap:15.2/.python-dparse.new.3248/python-dparse.changes 2020-04-08 12:49:30.986377670 +0200 @@ -1,0 +2,9 @@ +Fri Apr 3 08:12:12 UTC 2020 - Marketa Calabkova <mcalabk...@suse.com> + +- update to 0.5.0 + * Dropped Python 2.7, 3.3, 3.4 support + * Removed six package + * Removed pinned dependencies of tests + * Dropped setup.py tests support in favor of tox + +------------------------------------------------------------------- Old: ---- dparse-0.4.1.tar.gz New: ---- dparse-0.5.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-dparse.spec ++++++ --- /var/tmp/diff_new_pack.3q15cg/_old 2020-04-08 12:49:31.410377892 +0200 +++ /var/tmp/diff_new_pack.3q15cg/_new 2020-04-08 12:49:31.410377892 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-dparse # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,8 +18,9 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %bcond_without test +%define skip_python2 1 Name: python-dparse -Version: 0.4.1 +Version: 0.5.0 Release: 0 Summary: Python dependency file parser License: MIT @@ -31,14 +32,13 @@ BuildRequires: python-rpm-macros Requires: python-PyYAML Requires: python-packaging -Requires: python-six Recommends: python-pipenv BuildArch: noarch %if %{with test} BuildRequires: %{python_module PyYAML} BuildRequires: %{python_module packaging} BuildRequires: %{python_module pytest} -BuildRequires: %{python_module six} +BuildRequires: %{python_module toml} %endif %python_subpackages @@ -60,6 +60,7 @@ %check # There is a bug in the pipenv support, related to writing a new toml file. # Both dparse and pipenv have a vendored copy of different toml libraries. +# and even more, we do not have pipenv in our distribution %pytest --deselect 'tests/test_updater.py::test_update_pipfile' %endif ++++++ dparse-0.4.1.tar.gz -> dparse-0.5.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/CONTRIBUTING.rst new/dparse-0.5.0/CONTRIBUTING.rst --- old/dparse-0.4.1/CONTRIBUTING.rst 2018-04-06 13:46:35.000000000 +0200 +++ new/dparse-0.5.0/CONTRIBUTING.rst 2020-03-14 17:40:22.000000000 +0100 @@ -15,7 +15,7 @@ Report Bugs ~~~~~~~~~~~ -Report bugs at https://github.com/jayfk/dparse/issues. +Report bugs at https://github.com/pyupio/dparse/issues. If you are reporting a bug, please include: @@ -45,7 +45,7 @@ Submit Feedback ~~~~~~~~~~~~~~~ -The best way to send feedback is to file an issue at https://github.com/jayfk/dparse/issues. +The best way to send feedback is to file an issue at https://github.com/pyupio/dparse/issues. If you are proposing a feature: @@ -78,12 +78,9 @@ 5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: - $ flake8 dparse tests - $ python setup.py test or py.test + $ pip install tox $ tox - To get flake8 and tox, just pip install them into your virtualenv. - 6. Commit your changes and push your branch to GitHub:: $ git add . @@ -101,8 +98,8 @@ 2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst. -3. The pull request should work for Python 2.6, 2.7, 3.3, 3.4 and 3.5, and for PyPy. Check - https://travis-ci.org/jayfk/dparse/pull_requests +3. The pull request should work for Python 3.5+ and PyPy. Check + https://travis-ci.org/pyupio/dparse/pull_requests and make sure that the tests pass for all supported Python versions. Tips diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/HISTORY.rst new/dparse-0.5.0/HISTORY.rst --- old/dparse-0.4.1/HISTORY.rst 2018-04-06 13:46:35.000000000 +0200 +++ new/dparse-0.5.0/HISTORY.rst 2020-03-14 17:40:22.000000000 +0100 @@ -2,6 +2,14 @@ History ======= +0.5.0 (2020-03-14) +------------------ + +* Dropped Python 2.7, 3.3, 3.4 support +* Removed six package +* Removed pinned dependencies of tests +* Dropped setup.py tests support in favor of tox + 0.4.1 (2018-04-06) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/PKG-INFO new/dparse-0.5.0/PKG-INFO --- old/dparse-0.4.1/PKG-INFO 2018-04-06 13:48:31.000000000 +0200 +++ new/dparse-0.5.0/PKG-INFO 2020-03-14 17:41:13.000000000 +0100 @@ -1,8 +1,8 @@ Metadata-Version: 2.1 Name: dparse -Version: 0.4.1 +Version: 0.5.0 Summary: A parser for Python dependency files -Home-page: https://github.com/jayfk/dparse +Home-page: https://github.com/pyupio/dparse Author: Jannis Gebauer Author-email: j...@pyup.io License: MIT license @@ -50,7 +50,7 @@ +------------------+------------+-----------+ | Pipfile | yes | yes | +------------------+------------+-----------+ - | Pifile.lock | yes | yes | + | Pipfile.lock | yes | yes | +------------------+------------+-----------+ | setup.py | no (# 2_) | no (# 2_) | +------------------+------------+-----------+ @@ -149,6 +149,14 @@ History ======= + 0.5.0 (2020-03-14) + ------------------ + + * Dropped Python 2.7, 3.3, 3.4 support + * Removed six package + * Removed pinned dependencies of tests + * Dropped setup.py tests support in favor of tox + 0.4.1 (2018-04-06) ------------------ @@ -196,10 +204,9 @@ Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Natural Language :: English -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Provides-Extra: pipenv diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/README.rst new/dparse-0.5.0/README.rst --- old/dparse-0.4.1/README.rst 2018-04-06 13:46:35.000000000 +0200 +++ new/dparse-0.5.0/README.rst 2020-03-14 17:40:22.000000000 +0100 @@ -42,7 +42,7 @@ +------------------+------------+-----------+ | Pipfile | yes | yes | +------------------+------------+-----------+ -| Pifile.lock | yes | yes | +| Pipfile.lock | yes | yes | +------------------+------------+-----------+ | setup.py | no (# 2_) | no (# 2_) | +------------------+------------+-----------+ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/dparse/__init__.py new/dparse-0.5.0/dparse/__init__.py --- old/dparse-0.4.1/dparse/__init__.py 2018-04-06 13:46:35.000000000 +0200 +++ new/dparse-0.5.0/dparse/__init__.py 2020-03-14 17:40:22.000000000 +0100 @@ -4,6 +4,6 @@ __author__ = """Jannis Gebauer""" __email__ = 'j...@pyup.io' -__version__ = '0.4.1' +__version__ = '0.5.0' from .parser import parse diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/dparse/parser.py new/dparse-0.5.0/dparse/parser.py --- old/dparse-0.4.1/dparse/parser.py 2018-04-06 13:46:35.000000000 +0200 +++ new/dparse-0.5.0/dparse/parser.py 2020-03-14 17:40:22.000000000 +0100 @@ -4,31 +4,17 @@ import re import yaml -# Python 2 & 3 compatible StringIO -try: - from StringIO import StringIO -except ImportError: - from io import StringIO - -# Python 2 & 3 compatible Configparser -try: - from ConfigParser import SafeConfigParser, NoOptionError -except ImportError: - from configparser import SafeConfigParser, NoOptionError - -# Python 2 & 3 compatible basestring -try: # pragma: no cover - basestring -except NameError: # pragma: no cover - basestring = str +from io import StringIO + +from configparser import SafeConfigParser, NoOptionError + from .regex import URL_REGEX, HASH_REGEX from .dependencies import DependencyFile, Dependency from packaging.requirements import Requirement as PackagingRequirement, InvalidRequirement -import six from . import filetypes -from .vendor import toml +import toml from packaging.specifiers import SpecifierSet import json @@ -61,7 +47,7 @@ # create a steppable iterator, so we can handle \-continuations def yield_lines(strs): """Yield non-empty/non-comment lines of a string or sequence""" - if isinstance(strs, six.string_types): + if isinstance(strs, str): for s in strs.splitlines(): s = s.strip() # skip blank lines/comments @@ -345,7 +331,7 @@ if package_type in data: for name, specs in data[package_type].items(): # skip on VCS dependencies - if not isinstance(specs, basestring): + if not isinstance(specs, str): continue if specs == '*': specs = '' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/dparse/updater.py new/dparse-0.5.0/dparse/updater.py --- old/dparse-0.4.1/dparse/updater.py 2018-04-06 13:46:35.000000000 +0200 +++ new/dparse-0.5.0/dparse/updater.py 2020-03-14 17:40:22.000000000 +0100 @@ -2,9 +2,8 @@ from __future__ import absolute_import, print_function, unicode_literals import re import json -# Python 2 & 3 compatible StringIO import tempfile -from .vendor import toml +import toml import os diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/dparse/vendor/toml.py new/dparse-0.5.0/dparse/vendor/toml.py --- old/dparse-0.4.1/dparse/vendor/toml.py 2018-04-06 13:46:35.000000000 +0200 +++ new/dparse-0.5.0/dparse/vendor/toml.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,923 +0,0 @@ -"""Python module which parses and emits TOML. - -Released under the MIT license. -""" -import re -import io -import datetime -from os import linesep - -__version__ = "0.9.2" -__spec__ = "0.4.0" - - -class TomlDecodeError(Exception): - """Base toml Exception / Error.""" - pass - - -class TomlTz(datetime.tzinfo): - def __init__(self, toml_offset): - if toml_offset == "Z": - self._raw_offset = "+00:00" - else: - self._raw_offset = toml_offset - self._sign = -1 if self._raw_offset[0] == '-' else 1 - self._hours = int(self._raw_offset[1:3]) - self._minutes = int(self._raw_offset[4:6]) - - def tzname(self, dt): - return "UTC" + self._raw_offset - - def utcoffset(self, dt): - return self._sign * datetime.timedelta(hours=self._hours, - minutes=self._minutes) - - def dst(self, dt): - return datetime.timedelta(0) - - -class InlineTableDict(object): - """Sentinel subclass of dict for inline tables.""" - - -def _get_empty_inline_table(_dict): - class DynamicInlineTableDict(_dict, InlineTableDict): - """Concrete sentinel subclass for inline tables. - It is a subclass of _dict which is passed in dynamically at load time - It is also a subclass of InlineTableDict - """ - - return DynamicInlineTableDict() - - -try: - _range = xrange -except NameError: - unicode = str - _range = range - basestring = str - unichr = chr - -try: - FNFError = FileNotFoundError -except NameError: - FNFError = IOError - - -def load(f, _dict=dict): - """Parses named file or files as toml and returns a dictionary - - Args: - f: Path to the file to open, array of files to read into single dict - or a file descriptor - _dict: (optional) Specifies the class of the returned toml dictionary - - Returns: - Parsed toml file represented as a dictionary - - Raises: - TypeError -- When f is invalid type - TomlDecodeError: Error while decoding toml - IOError / FileNotFoundError -- When an array with no valid (existing) - (Python 2 / Python 3) file paths is passed - """ - - if isinstance(f, basestring): - with io.open(f, encoding='utf-8') as ffile: - return loads(ffile.read(), _dict) - elif isinstance(f, list): - from os import path as op - from warnings import warn - if not [path for path in f if op.exists(path)]: - error_msg = "Load expects a list to contain filenames only." - error_msg += linesep - error_msg += ("The list needs to contain the path of at least one " - "existing file.") - raise FNFError(error_msg) - d = _dict() - for l in f: - if op.exists(l): - d.update(load(l)) - else: - warn("Non-existent filename in list with at least one valid " - "filename") - return d - else: - try: - return loads(f.read(), _dict) - except AttributeError: - raise TypeError("You can only load a file descriptor, filename or " - "list") - - -_groupname_re = re.compile(r'^[A-Za-z0-9_-]+$') - - -def loads(s, _dict=dict): - """Parses string as toml - - Args: - s: String to be parsed - _dict: (optional) Specifies the class of the returned toml dictionary - - Returns: - Parsed toml file represented as a dictionary - - Raises: - TypeError: When a non-string is passed - TomlDecodeError: Error while decoding toml - """ - - implicitgroups = [] - retval = _dict() - currentlevel = retval - if not isinstance(s, basestring): - raise TypeError("Expecting something like a string") - - if not isinstance(s, unicode): - s = s.decode('utf8') - - sl = list(s) - openarr = 0 - openstring = False - openstrchar = "" - multilinestr = False - arrayoftables = False - beginline = True - keygroup = False - keyname = 0 - for i, item in enumerate(sl): - if item == '\r' and sl[i + 1] == '\n': - sl[i] = ' ' - continue - if keyname: - if item == '\n': - raise TomlDecodeError("Key name found without value." - " Reached end of line.") - if openstring: - if item == openstrchar: - keyname = 2 - openstring = False - openstrchar = "" - continue - elif keyname == 1: - if item.isspace(): - keyname = 2 - continue - elif item.isalnum() or item == '_' or item == '-': - continue - elif keyname == 2 and item.isspace(): - continue - if item == '=': - keyname = 0 - else: - raise TomlDecodeError("Found invalid character in key name: '" + - item + "'. Try quoting the key name.") - if item == "'" and openstrchar != '"': - k = 1 - try: - while sl[i - k] == "'": - k += 1 - if k == 3: - break - except IndexError: - pass - if k == 3: - multilinestr = not multilinestr - openstring = multilinestr - else: - openstring = not openstring - if openstring: - openstrchar = "'" - else: - openstrchar = "" - if item == '"' and openstrchar != "'": - oddbackslash = False - k = 1 - tripquote = False - try: - while sl[i - k] == '"': - k += 1 - if k == 3: - tripquote = True - break - if k == 1 or (k == 3 and tripquote): - while sl[i - k] == '\\': - oddbackslash = not oddbackslash - k += 1 - except IndexError: - pass - if not oddbackslash: - if tripquote: - multilinestr = not multilinestr - openstring = multilinestr - else: - openstring = not openstring - if openstring: - openstrchar = '"' - else: - openstrchar = "" - if item == '#' and (not openstring and not keygroup and - not arrayoftables): - j = i - try: - while sl[j] != '\n': - sl[j] = ' ' - j += 1 - except IndexError: - break - if item == '[' and (not openstring and not keygroup and - not arrayoftables): - if beginline: - if sl[i + 1] == '[': - arrayoftables = True - else: - keygroup = True - else: - openarr += 1 - if item == ']' and not openstring: - if keygroup: - keygroup = False - elif arrayoftables: - if sl[i - 1] == ']': - arrayoftables = False - else: - openarr -= 1 - if item == '\n': - if openstring or multilinestr: - if not multilinestr: - raise TomlDecodeError("Unbalanced quotes") - if ((sl[i - 1] == "'" or sl[i - 1] == '"') and ( - sl[i - 2] == sl[i - 1])): - sl[i] = sl[i - 1] - if sl[i - 3] == sl[i - 1]: - sl[i - 3] = ' ' - elif openarr: - sl[i] = ' ' - else: - beginline = True - elif beginline and sl[i] != ' ' and sl[i] != '\t': - beginline = False - if not keygroup and not arrayoftables: - if sl[i] == '=': - raise TomlDecodeError("Found empty keyname. ") - keyname = 1 - s = ''.join(sl) - s = s.split('\n') - multikey = None - multilinestr = "" - multibackslash = False - for line in s: - if not multilinestr or multibackslash or '\n' not in multilinestr: - line = line.strip() - if line == "" and (not multikey or multibackslash): - continue - if multikey: - if multibackslash: - multilinestr += line - else: - multilinestr += line - multibackslash = False - if len(line) > 2 and (line[-1] == multilinestr[0] and - line[-2] == multilinestr[0] and - line[-3] == multilinestr[0]): - value, vtype = _load_value(multilinestr, _dict) - currentlevel[multikey] = value - multikey = None - multilinestr = "" - else: - k = len(multilinestr) - 1 - while k > -1 and multilinestr[k] == '\\': - multibackslash = not multibackslash - k -= 1 - if multibackslash: - multilinestr = multilinestr[:-1] - else: - multilinestr += "\n" - continue - if line[0] == '[': - arrayoftables = False - if line[1] == '[': - arrayoftables = True - line = line[2:].split(']]', 1) - else: - line = line[1:].split(']', 1) - if line[1].strip() != "": - raise TomlDecodeError("Key group not on a line by itself.") - groups = line[0].split('.') - i = 0 - while i < len(groups): - groups[i] = groups[i].strip() - if groups[i][0] == '"' or groups[i][0] == "'": - groupstr = groups[i] - j = i + 1 - while not groupstr[0] == groupstr[-1]: - j += 1 - groupstr = '.'.join(groups[i:j]) - groups[i] = groupstr[1:-1] - groups[i + 1:j] = [] - else: - if not _groupname_re.match(groups[i]): - raise TomlDecodeError("Invalid group name '" + - groups[i] + "'. Try quoting it.") - i += 1 - currentlevel = retval - for i in _range(len(groups)): - group = groups[i] - if group == "": - raise TomlDecodeError("Can't have a keygroup with an empty " - "name") - try: - currentlevel[group] - if i == len(groups) - 1: - if group in implicitgroups: - implicitgroups.remove(group) - if arrayoftables: - raise TomlDecodeError("An implicitly defined " - "table can't be an array") - elif arrayoftables: - currentlevel[group].append(_dict()) - else: - raise TomlDecodeError("What? " + group + - " already exists?" + - str(currentlevel)) - except TypeError: - currentlevel = currentlevel[-1] - try: - currentlevel[group] - except KeyError: - currentlevel[group] = _dict() - if i == len(groups) - 1 and arrayoftables: - currentlevel[group] = [_dict()] - except KeyError: - if i != len(groups) - 1: - implicitgroups.append(group) - currentlevel[group] = _dict() - if i == len(groups) - 1 and arrayoftables: - currentlevel[group] = [_dict()] - currentlevel = currentlevel[group] - if arrayoftables: - try: - currentlevel = currentlevel[-1] - except KeyError: - pass - elif line[0] == "{": - if line[-1] != "}": - raise TomlDecodeError("Line breaks are not allowed in inline" - "objects") - _load_inline_object(line, currentlevel, _dict, multikey, - multibackslash) - elif "=" in line: - ret = _load_line(line, currentlevel, _dict, multikey, - multibackslash) - if ret is not None: - multikey, multilinestr, multibackslash = ret - return retval - - -def _load_inline_object(line, currentlevel, _dict, multikey=False, - multibackslash=False): - candidate_groups = line[1:-1].split(",") - groups = [] - if len(candidate_groups) == 1 and not candidate_groups[0].strip(): - candidate_groups.pop() - while len(candidate_groups) > 0: - candidate_group = candidate_groups.pop(0) - try: - _, value = candidate_group.split('=', 1) - except ValueError: - raise TomlDecodeError("Invalid inline table encountered") - value = value.strip() - if ((value[0] == value[-1] and value[0] in ('"', "'")) or ( - value[0] in '-0123456789' or - value in ('true', 'false') or - (value[0] == "[" and value[-1] == "]"))): - groups.append(candidate_group) - else: - candidate_groups[0] = candidate_group + "," + candidate_groups[0] - for group in groups: - status = _load_line(group, currentlevel, _dict, multikey, - multibackslash) - if status is not None: - break - - -# Matches a TOML number, which allows underscores for readability -_number_with_underscores = re.compile('([0-9])(_([0-9]))*') - - -def _strictly_valid_num(n): - n = n.strip() - if not n: - return False - if n[0] == '_': - return False - if n[-1] == '_': - return False - if "_." in n or "._" in n: - return False - if len(n) == 1: - return True - if n[0] == '0' and n[1] != '.': - return False - if n[0] == '+' or n[0] == '-': - n = n[1:] - if n[0] == '0' and n[1] != '.': - return False - if '__' in n: - return False - return True - - -def _load_line(line, currentlevel, _dict, multikey, multibackslash): - i = 1 - pair = line.split('=', i) - strictly_valid = _strictly_valid_num(pair[-1]) - if _number_with_underscores.match(pair[-1]): - pair[-1] = pair[-1].replace('_', '') - while len(pair[-1]) and (pair[-1][0] != ' ' and pair[-1][0] != '\t' and - pair[-1][0] != "'" and pair[-1][0] != '"' and - pair[-1][0] != '[' and pair[-1][0] != '{' and - pair[-1] != 'true' and pair[-1] != 'false'): - try: - float(pair[-1]) - break - except ValueError: - pass - if _load_date(pair[-1]) is not None: - break - i += 1 - prev_val = pair[-1] - pair = line.split('=', i) - if prev_val == pair[-1]: - raise TomlDecodeError("Invalid date or number") - if strictly_valid: - strictly_valid = _strictly_valid_num(pair[-1]) - pair = ['='.join(pair[:-1]).strip(), pair[-1].strip()] - if (pair[0][0] == '"' or pair[0][0] == "'") and \ - (pair[0][-1] == '"' or pair[0][-1] == "'"): - pair[0] = pair[0][1:-1] - if len(pair[1]) > 2 and ((pair[1][0] == '"' or pair[1][0] == "'") and - pair[1][1] == pair[1][0] and - pair[1][2] == pair[1][0] and - not (len(pair[1]) > 5 and - pair[1][-1] == pair[1][0] and - pair[1][-2] == pair[1][0] and - pair[1][-3] == pair[1][0])): - k = len(pair[1]) - 1 - while k > -1 and pair[1][k] == '\\': - multibackslash = not multibackslash - k -= 1 - if multibackslash: - multilinestr = pair[1][:-1] - else: - multilinestr = pair[1] + "\n" - multikey = pair[0] - else: - value, vtype = _load_value(pair[1], _dict, strictly_valid) - try: - currentlevel[pair[0]] - raise TomlDecodeError("Duplicate keys!") - except KeyError: - if multikey: - return multikey, multilinestr, multibackslash - else: - currentlevel[pair[0]] = value - except: - raise TomlDecodeError("Duplicate keys!") - - -def _load_date(val): - microsecond = 0 - tz = None - try: - if len(val) > 19: - if val[19] == '.': - microsecond = int(val[20:26]) - if len(val) > 26: - tz = TomlTz(val[26:32]) - else: - tz = TomlTz(val[19:25]) - except ValueError: - tz = None - try: - d = datetime.datetime( - int(val[:4]), int(val[5:7]), - int(val[8:10]), int(val[11:13]), - int(val[14:16]), int(val[17:19]), microsecond, tz) - except ValueError: - return None - return d - - -def _load_unicode_escapes(v, hexbytes, prefix): - hexchars = ['0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'] - skip = False - i = len(v) - 1 - while i > -1 and v[i] == '\\': - skip = not skip - i -= 1 - for hx in hexbytes: - if skip: - skip = False - i = len(hx) - 1 - while i > -1 and hx[i] == '\\': - skip = not skip - i -= 1 - v += prefix - v += hx - continue - hxb = "" - i = 0 - hxblen = 4 - if prefix == "\\U": - hxblen = 8 - while i < hxblen: - try: - if not hx[i].lower() in hexchars: - raise IndexError("This is a hack") - except IndexError: - raise TomlDecodeError("Invalid escape sequence") - hxb += hx[i].lower() - i += 1 - v += unichr(int(hxb, 16)) - v += unicode(hx[len(hxb):]) - return v - - -# Unescape TOML string values. - -# content after the \ -_escapes = ['0', 'b', 'f', 'n', 'r', 't', '"'] -# What it should be replaced by -_escapedchars = ['\0', '\b', '\f', '\n', '\r', '\t', '\"'] -# Used for substitution -_escape_to_escapedchars = dict(zip(_escapes, _escapedchars)) - - -def _unescape(v): - """Unescape characters in a TOML string.""" - i = 0 - backslash = False - while i < len(v): - if backslash: - backslash = False - if v[i] in _escapes: - v = v[:i - 1] + _escape_to_escapedchars[v[i]] + v[i + 1:] - elif v[i] == '\\': - v = v[:i - 1] + v[i:] - elif v[i] == 'u' or v[i] == 'U': - i += 1 - else: - raise TomlDecodeError("Reserved escape sequence used") - continue - elif v[i] == '\\': - backslash = True - i += 1 - return v - - -def _load_value(v, _dict, strictly_valid=True): - if not v: - raise TomlDecodeError("Empty value is invalid") - if v == 'true': - return (True, "bool") - elif v == 'false': - return (False, "bool") - elif v[0] == '"': - testv = v[1:].split('"') - if testv[0] == '' and testv[1] == '': - testv = testv[2:-2] - closed = False - for tv in testv: - if tv == '': - closed = True - else: - oddbackslash = False - try: - i = -1 - j = tv[i] - while j == '\\': - oddbackslash = not oddbackslash - i -= 1 - j = tv[i] - except IndexError: - pass - if not oddbackslash: - if closed: - raise TomlDecodeError("Stuff after closed string. WTF?") - else: - closed = True - escapeseqs = v.split('\\')[1:] - backslash = False - for i in escapeseqs: - if i == '': - backslash = not backslash - else: - if i[0] not in _escapes and (i[0] != 'u' and i[0] != 'U' and - not backslash): - raise TomlDecodeError("Reserved escape sequence used") - if backslash: - backslash = False - for prefix in ["\\u", "\\U"]: - if prefix in v: - hexbytes = v.split(prefix) - v = _load_unicode_escapes(hexbytes[0], hexbytes[1:], prefix) - v = _unescape(v) - if v[1] == '"' and (len(v) < 3 or v[1] == v[2]): - v = v[2:-2] - return (v[1:-1], "str") - elif v[0] == "'": - if v[1] == "'" and (len(v) < 3 or v[1] == v[2]): - v = v[2:-2] - return (v[1:-1], "str") - elif v[0] == '[': - return (_load_array(v, _dict), "array") - elif v[0] == '{': - inline_object = _get_empty_inline_table(_dict) - _load_inline_object(v, inline_object, _dict) - return (inline_object, "inline_object") - else: - parsed_date = _load_date(v) - if parsed_date is not None: - return (parsed_date, "date") - if not strictly_valid: - raise TomlDecodeError("Weirdness with leading zeroes or underscores" - " in your number.") - itype = "int" - neg = False - if v[0] == '-': - neg = True - v = v[1:] - elif v[0] == '+': - v = v[1:] - v = v.replace('_', '') - if '.' in v or 'e' in v or 'E' in v: - if '.' in v and v.split('.', 1)[1] == '': - raise TomlDecodeError("This float is missing digits after " - "the point") - if v[0] not in '0123456789': - raise TomlDecodeError("This float doesn't have a leading digit") - v = float(v) - itype = "float" - else: - v = int(v) - if neg: - return (0 - v, itype) - return (v, itype) - - -def _load_array(a, _dict): - atype = None - retval = [] - a = a.strip() - if '[' not in a[1:-1] or "" != a[1:-1].split('[')[0].strip(): - strarray = False - tmpa = a[1:-1].strip() - if tmpa != '' and (tmpa[0] == '"' or tmpa[0] == "'"): - strarray = True - if not a[1:-1].strip().startswith('{'): - a = a[1:-1].split(',') - else: - # a is an inline object, we must find the matching parenthesis - # to define groups - new_a = [] - start_group_index = 1 - end_group_index = 2 - in_str = False - while end_group_index < len(a[1:]): - if a[end_group_index] == '"' or a[end_group_index] == "'": - in_str = not in_str - if in_str or a[end_group_index] != '}': - end_group_index += 1 - continue - - # Increase end_group_index by 1 to get the closing bracket - end_group_index += 1 - new_a.append(a[start_group_index:end_group_index]) - - # The next start index is at least after the closing bracket, a - # closing bracket can be followed by a comma since we are in - # an array. - start_group_index = end_group_index + 1 - while (start_group_index < len(a[1:]) and - a[start_group_index] != '{'): - start_group_index += 1 - end_group_index = start_group_index + 1 - a = new_a - b = 0 - if strarray: - while b < len(a) - 1: - ab = a[b].strip() - while ab[-1] != ab[0] or (ab[0] == ab[1] == ab[2] and - ab[-2] != ab[0] and ab[-3] != ab[0]): - a[b] = a[b] + ',' + a[b + 1] - ab = a[b].strip() - if b < len(a) - 2: - a = a[:b + 1] + a[b + 2:] - else: - a = a[:b + 1] - b += 1 - else: - al = list(a[1:-1]) - a = [] - openarr = 0 - j = 0 - for i in _range(len(al)): - if al[i] == '[': - openarr += 1 - elif al[i] == ']': - openarr -= 1 - elif al[i] == ',' and not openarr: - a.append(''.join(al[j:i])) - j = i + 1 - a.append(''.join(al[j:])) - for i in _range(len(a)): - a[i] = a[i].strip() - if a[i] != '': - nval, ntype = _load_value(a[i], _dict) - if atype: - if ntype != atype: - raise TomlDecodeError("Not a homogeneous array") - else: - atype = ntype - retval.append(nval) - return retval - - -def dump(o, f): - """Writes out dict as toml to a file - - Args: - o: Object to dump into toml - f: File descriptor where the toml should be stored - - Returns: - String containing the toml corresponding to dictionary - - Raises: - TypeError: When anything other than file descriptor is passed - """ - - if not f.write: - raise TypeError("You can only dump an object to a file descriptor") - d = dumps(o) - f.write(d) - return d - - -def dumps(o, preserve=False): - """Stringifies input dict as toml - - Args: - o: Object to dump into toml - - preserve: Boolean parameter. If true, preserve inline tables. - - Returns: - String containing the toml corresponding to dict - """ - - retval = "" - addtoretval, sections = _dump_sections(o, "") - retval += addtoretval - while sections != {}: - newsections = {} - for section in sections: - addtoretval, addtosections = _dump_sections(sections[section], - section, preserve) - if addtoretval or (not addtoretval and not addtosections): - if retval and retval[-2:] != "\n\n": - retval += "\n" - retval += "[" + section + "]\n" - if addtoretval: - retval += addtoretval - for s in addtosections: - newsections[section + "." + s] = addtosections[s] - sections = newsections - return retval - - -def _dump_sections(o, sup, preserve=False): - retstr = "" - if sup != "" and sup[-1] != ".": - sup += '.' - retdict = o.__class__() - arraystr = "" - for section in o: - section = str(section) - qsection = section - if not re.match(r'^[A-Za-z0-9_-]+$', section): - if '"' in section: - qsection = "'" + section + "'" - else: - qsection = '"' + section + '"' - if not isinstance(o[section], dict): - arrayoftables = False - if isinstance(o[section], list): - for a in o[section]: - if isinstance(a, dict): - arrayoftables = True - if arrayoftables: - for a in o[section]: - arraytabstr = "\n" - arraystr += "[[" + sup + qsection + "]]\n" - s, d = _dump_sections(a, sup + qsection) - if s: - if s[0] == "[": - arraytabstr += s - else: - arraystr += s - while d != {}: - newd = {} - for dsec in d: - s1, d1 = _dump_sections(d[dsec], sup + qsection + - "." + dsec) - if s1: - arraytabstr += ("[" + sup + qsection + "." + - dsec + "]\n") - arraytabstr += s1 - for s1 in d1: - newd[dsec + "." + s1] = d1[s1] - d = newd - arraystr += arraytabstr - else: - if o[section] is not None: - retstr += (qsection + " = " + - str(_dump_value(o[section])) + '\n') - elif preserve and isinstance(o[section], InlineTableDict): - retstr += (section + " = " + _dump_inline_table(o[section])) - else: - retdict[qsection] = o[section] - retstr += arraystr - return (retstr, retdict) - - -def _dump_inline_table(section): - """Preserve inline table in its compact syntax instead of expanding - into subsection. - - https://github.com/toml-lang/toml#user-content-inline-table - """ - retval = "" - if isinstance(section, dict): - val_list = [] - for k, v in section.items(): - val = _dump_inline_table(v) - val_list.append(k + " = " + val) - retval += "{ " + ", ".join(val_list) + " }\n" - return retval - else: - return str(_dump_value(section)) - - -def _dump_value(v): - dump_funcs = { - str: lambda: _dump_str(v), - unicode: lambda: _dump_str(v), - list: lambda: _dump_list(v), - bool: lambda: str(v).lower(), - float: lambda: _dump_float(v), - datetime.datetime: lambda: v.isoformat(), - } - # Lookup function corresponding to v's type - dump_fn = dump_funcs.get(type(v)) - # Evaluate function (if it exists) else return v - return dump_fn() if dump_fn is not None else v - - -def _dump_str(v): - v = "%r" % v - if v[0] == 'u': - v = v[1:] - singlequote = v.startswith("'") - v = v[1:-1] - if singlequote: - v = v.replace("\\'", "'") - v = v.replace('"', '\\"') - v = v.replace("\\x", "\\u00") - return str('"' + v + '"') - - -def _dump_list(v): - t = [] - retval = "[" - for u in v: - t.append(_dump_value(u)) - while t != []: - s = [] - for u in t: - if isinstance(u, list): - for r in u: - s.append(r) - else: - retval += " " + str(u) + "," - t = s - retval += "]" - return retval - - -def _dump_float(v): - return "{0:.16g}".format(v).replace("e+0", "e+").replace("e-0", "e-") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/dparse.egg-info/PKG-INFO new/dparse-0.5.0/dparse.egg-info/PKG-INFO --- old/dparse-0.4.1/dparse.egg-info/PKG-INFO 2018-04-06 13:48:31.000000000 +0200 +++ new/dparse-0.5.0/dparse.egg-info/PKG-INFO 2020-03-14 17:41:12.000000000 +0100 @@ -1,8 +1,8 @@ Metadata-Version: 2.1 Name: dparse -Version: 0.4.1 +Version: 0.5.0 Summary: A parser for Python dependency files -Home-page: https://github.com/jayfk/dparse +Home-page: https://github.com/pyupio/dparse Author: Jannis Gebauer Author-email: j...@pyup.io License: MIT license @@ -50,7 +50,7 @@ +------------------+------------+-----------+ | Pipfile | yes | yes | +------------------+------------+-----------+ - | Pifile.lock | yes | yes | + | Pipfile.lock | yes | yes | +------------------+------------+-----------+ | setup.py | no (# 2_) | no (# 2_) | +------------------+------------+-----------+ @@ -149,6 +149,14 @@ History ======= + 0.5.0 (2020-03-14) + ------------------ + + * Dropped Python 2.7, 3.3, 3.4 support + * Removed six package + * Removed pinned dependencies of tests + * Dropped setup.py tests support in favor of tox + 0.4.1 (2018-04-06) ------------------ @@ -196,10 +204,9 @@ Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Natural Language :: English -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Provides-Extra: pipenv diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/dparse.egg-info/SOURCES.txt new/dparse-0.5.0/dparse.egg-info/SOURCES.txt --- old/dparse-0.4.1/dparse.egg-info/SOURCES.txt 2018-04-06 13:48:31.000000000 +0200 +++ new/dparse-0.5.0/dparse.egg-info/SOURCES.txt 2020-03-14 17:41:12.000000000 +0100 @@ -26,8 +26,6 @@ dparse.egg-info/not-zip-safe dparse.egg-info/requires.txt dparse.egg-info/top_level.txt -dparse/vendor/__init__.py -dparse/vendor/toml.py tests/__init__.py tests/test_dependencies.py tests/test_parse.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/dparse.egg-info/requires.txt new/dparse-0.5.0/dparse.egg-info/requires.txt --- old/dparse-0.4.1/dparse.egg-info/requires.txt 2018-04-06 13:48:31.000000000 +0200 +++ new/dparse-0.5.0/dparse.egg-info/requires.txt 2020-03-14 17:41:12.000000000 +0100 @@ -1,6 +1,7 @@ +pipenv packaging -six pyyaml +toml [pipenv] pipenv diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/setup.py new/dparse-0.5.0/setup.py --- old/dparse-0.4.1/setup.py 2018-04-06 13:46:35.000000000 +0200 +++ new/dparse-0.5.0/setup.py 2020-03-14 17:40:22.000000000 +0100 @@ -4,7 +4,6 @@ """The setup script.""" from setuptools import setup, find_packages -import sys with open('README.rst') as readme_file: readme = readme_file.read() @@ -13,31 +12,20 @@ history = history_file.read() requirements = [ + "pipenv", "packaging", - "six", "pyyaml", -] - -# make pytest-runner a conditional requirement, per: https://pypi.org/project/pytest-runner/ -needs_pytest = {'pytest', 'test', 'ptr'}.intersection(sys.argv) -pytest_runner = ['pytest-runner'] if needs_pytest else [] - -setup_requirements = [ - # other setup requirements -] + pytest_runner - -test_requirements = [ - 'pytest', + "toml", ] setup( name='dparse', - version='0.4.1', + version='0.5.0', description="A parser for Python dependency files", long_description=readme + '\n\n' + history, author="Jannis Gebauer", author_email='j...@pyup.io', - url='https://github.com/jayfk/dparse', + url='https://github.com/pyupio/dparse', packages=find_packages(include=['dparse']), include_package_data=True, install_requires=requirements, @@ -49,16 +37,12 @@ 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Natural Language :: English', - "Programming Language :: Python :: 2", - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', ], - test_suite='tests', - tests_require=test_requirements, - setup_requires=setup_requirements, extras_require={ 'pipenv': ["pipenv"], } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dparse-0.4.1/tests/test_updater.py new/dparse-0.5.0/tests/test_updater.py --- old/dparse-0.4.1/tests/test_updater.py 2018-04-06 13:46:35.000000000 +0200 +++ new/dparse-0.5.0/tests/test_updater.py 2020-03-14 17:40:22.000000000 +0100 @@ -436,7 +436,7 @@ dependency=dep) == new_content -def test_update_pipfile(): +def test_update_pipfile(monkeypatch): content = """[[source]] url = "http://some.pypi.mirror.server.org/simple" @@ -455,6 +455,12 @@ toml = "*" """ + import pipenv.project + monkeypatch.setattr( + pipenv.project.pipfile.Pipfile, + 'find', + lambda max_depth: '/tmp/MockPipFile' + ) dep_file = parse(content=content, file_type=filetypes.pipfile) dep = dep_file.dependencies[0] new_content = PipfileUpdater.update(content, version="2.1", dependency=dep)