Hello community,

here is the log from the commit of package python-requirements-detector for 
openSUSE:Factory checked in at 2015-05-16 19:01:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-requirements-detector (Old)
 and      /work/SRC/openSUSE:Factory/.python-requirements-detector.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-requirements-detector"

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-requirements-detector/python-requirements-detector.changes
        2014-01-23 15:54:42.000000000 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-requirements-detector.new/python-requirements-detector.changes
   2015-05-16 19:01:50.000000000 +0200
@@ -1,0 +2,6 @@
+Tue May 12 14:22:20 UTC 2015 - benoit.mo...@gmx.fr
+
+- update to version 0.4:
+  * no changelog available
+
+-------------------------------------------------------------------

Old:
----
  requirements-detector-0.1.1.tar.gz

New:
----
  requirements-detector-0.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-requirements-detector.spec ++++++
--- /var/tmp/diff_new_pack.wDojQR/_old  2015-05-16 19:01:51.000000000 +0200
+++ /var/tmp/diff_new_pack.wDojQR/_new  2015-05-16 19:01:51.000000000 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-requirements-detector
 #
-# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           python-requirements-detector
-Version:        0.1.1
+Version:        0.4
 Release:        0
 Summary:        Python tool to find and list requirements of a Python project
 License:        MIT

++++++ requirements-detector-0.1.1.tar.gz -> requirements-detector-0.4.tar.gz 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/requirements-detector-0.1.1/PKG-INFO 
new/requirements-detector-0.4/PKG-INFO
--- old/requirements-detector-0.1.1/PKG-INFO    2013-10-26 17:50:56.000000000 
+0200
+++ new/requirements-detector-0.4/PKG-INFO      2015-03-24 07:41:47.000000000 
+0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.0
+Metadata-Version: 1.1
 Name: requirements-detector
-Version: 0.1.1
+Version: 0.4
 Summary: Python tool to find and list requirements of a Python project
 Home-page: https://github.com/landscapeio/requirements-detector
 Author: landscape.io
@@ -9,3 +9,12 @@
 Description: UNKNOWN
 Keywords: python requirements detector
 Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Developers
+Classifier: Operating System :: Unix
+Classifier: Topic :: Software Development :: Quality Assurance
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.3
+Classifier: License :: OSI Approved :: GNU General Public License v2 or later 
(GPLv2+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/requirements-detector-0.1.1/requirements_detector/detect.py 
new/requirements-detector-0.4/requirements_detector/detect.py
--- old/requirements-detector-0.1.1/requirements_detector/detect.py     
2013-10-26 17:48:58.000000000 +0200
+++ new/requirements-detector-0.4/requirements_detector/detect.py       
2015-03-23 23:06:42.000000000 +0100
@@ -1,14 +1,21 @@
 import re
 import os
+import sys
 from astroid.builder import AstroidBuilder
 from astroid import MANAGER, CallFunc, Name, Assign, Keyword, List, Tuple, 
Const, AssName
 from requirements_detector.requirement import DetectedRequirement
 
 
-__all__ = ['find_dependencies',
+__all__ = ['find_requirements',
            'RequirementsNotFound',
-           'CouldNotParseRequirements',
-           'get_prospector_profiles']
+           'CouldNotParseRequirements']
+
+
+# PEP263, see http://legacy.python.org/dev/peps/pep-0263/
+_ENCODING_REGEXP = re.compile(r'coding[:=]\s*([-\w.]+)')
+
+
+_PY3K = sys.version_info >= (3, 0)
 
 
 _PIP_OPTIONS = (
@@ -28,6 +35,34 @@
     pass
 
 
+def _load_file_contents(filepath):
+    # This function is a bit of a tedious workaround (AKA 'hack').
+    # Astroid calls 'compile' under the hood, which refuses to accept a Unicode
+    # object which contains a PEP-263 encoding definition. However if we give
+    # Astroid raw bytes, it'll assume ASCII. Therefore we need to detect the 
encoding
+    # here, convert the file contents to a Unicode object, *and also strip the 
encoding
+    # declaration* to avoid the compile step breaking.
+    with open(filepath) as f:
+        if _PY3K:
+            return f.read()
+        
+        contents = f.readlines()
+
+        result = []
+        encoding_lines = contents[0:2]
+        encoding = 'utf-8'
+        for line in encoding_lines:
+            match = _ENCODING_REGEXP.search(line)
+            if match is None:
+                result.append(line)
+            else:
+                encoding = match.group(1)
+
+        result += contents[2:]
+        result = '\n'.join(result)
+        return result.decode(encoding)
+
+
 def find_requirements(path):
     """
     This method tries to determine the requirements of a particular project
@@ -36,7 +71,7 @@
     It will attempt, in order:
 
     1) to parse setup.py in the root for an install_requires value
-    2) to read a requirements.txt file in the root
+    2) to read a requirements.txt file or a requirements.pip in the root
     3) to read all .txt files in a folder called 'requirements' in the root
     4) to read files matching "*requirements*.txt" and "*reqs*.txt" in the 
root,
        excluding any starting or ending with 'test'
@@ -45,29 +80,38 @@
     will be returned. If none can be found, then a RequirementsNotFound
     will be raised
     """
+    requirements = []
 
     setup_py = os.path.join(path, 'setup.py')
     if os.path.exists(setup_py) and os.path.isfile(setup_py):
         try:
-            return from_setup_py(setup_py)
+            requirements = from_setup_py(setup_py)
+            requirements.sort()
+            return requirements
         except CouldNotParseRequirements:
             pass
 
-    requirements_txt = os.path.join(path, 'requirements.txt')
-    if os.path.exists(requirements_txt) and os.path.isfile(requirements_txt):
-        try:
-            return from_requirements_txt(requirements_txt)
-        except CouldNotParseRequirements:
-            pass
+    for reqfile_name in ('requirements.txt', 'requirements.pip'):
+        reqfile_path = os.path.join(path, reqfile_name)
+        if os.path.exists(reqfile_path) and os.path.isfile(reqfile_path):
+            try:
+                requirements += from_requirements_txt(reqfile_path)
+            except CouldNotParseRequirements as e:
+                pass
 
     requirements_dir = os.path.join(path, 'requirements')
     if os.path.exists(requirements_dir) and os.path.isdir(requirements_dir):
-        requirements = from_requirements_dir(requirements_dir)
-        if requirements:
-            return requirements
-
-    requirements = from_requirements_blob(path)
-    if requirements:
+        from_dir = from_requirements_dir(requirements_dir)
+        if from_dir is not None:
+            requirements += from_dir
+
+    from_blob = from_requirements_blob(path)
+    if from_blob is not None:
+        requirements += from_blob
+
+    requirements = list(set(requirements))
+    if len(requirements) > 0:
+        requirements.sort()
         return requirements
 
     raise RequirementsNotFound
@@ -108,23 +152,26 @@
             values.append(child_node.value)
         return values
 
-    def get_install_requires(self):
+    def get_requires(self):
         # first, if we have a call to setup, then we can see what its 
"install_requires" argument is
         if not self._setup_call:
             raise CouldNotParseRequirements
 
+        found_requirements = []
+
         for child_node in self._setup_call.get_children():
             if not isinstance(child_node, Keyword):
                 # do we want to try to handle positional arguments?
                 continue
 
-            if child_node.arg != 'install_requires':
+            if child_node.arg not in ('install_requires', 'requires'):
                 continue
 
             if isinstance(child_node.value, (List, Tuple)):
                 # joy! this is a simple list or tuple of requirements
                 # this is a Keyword -> List or Keyword -> Tuple
-                return self._get_list_value(child_node.value)
+                found_requirements += self._get_list_value(child_node.value)
+                continue
 
             if isinstance(child_node.value, Name):
                 # otherwise, it's referencing a value defined elsewhere
@@ -135,26 +182,33 @@
                     raise CouldNotParseRequirements
                 else:
                     if isinstance(reqs, (List, Tuple)):
-                        return self._get_list_value(reqs)
+                        found_requirements += self._get_list_value(reqs)
+                        continue
 
             # otherwise it's something funky and we can't handle it
             raise CouldNotParseRequirements
 
-        # if we've fallen off the bottom, we simply didn't find anything useful
+        # if we've fallen off the bottom with nothing in our list of 
requirements,
+        #  we simply didn't find anything useful
+        if len(found_requirements) > 0:
+            return found_requirements
         raise CouldNotParseRequirements
 
 
 def from_setup_py(setup_file):
-    with open(setup_file) as f:
-        ast = AstroidBuilder(MANAGER).string_build(f.read())
+    try:
+        contents = _load_file_contents(setup_file)
+        ast = AstroidBuilder(MANAGER).string_build(contents)
+    except SyntaxError:
+        # if the setup file is broken, we can't do much about that...
+        raise CouldNotParseRequirements
 
     walker = SetupWalker(ast)
 
     requirements = []
-    for req in walker.get_install_requires():
-        requirements.append(DetectedRequirement.parse(req))
+    for req in walker.get_requires():
+        requirements.append(DetectedRequirement.parse(req, setup_file))
 
-    requirements.sort(key=lambda r: r.name)
     return requirements
 
 
@@ -172,9 +226,11 @@
             if req.strip().split()[0] in _PIP_OPTIONS:
                 # this is a pip option
                 continue
-            requirements.append(DetectedRequirement.parse(req))
+            detected = DetectedRequirement.parse(req, requirements_file)
+            if detected is None:
+                continue
+            requirements.append(detected)
 
-    requirements.sort(key=lambda r: r.name)
     return requirements
 
 
@@ -182,11 +238,12 @@
     requirements = []
     for entry in os.listdir(path):
         filepath = os.path.join(path, entry)
-        if os.path.isfile(filepath) and entry.endswith('.txt'):
+        if not os.path.isfile(filepath):
+            continue
+        if entry.endswith('.txt') or entry.endswith('.pip'):
             # TODO: deal with duplicates
             requirements += from_requirements_txt(filepath)
 
-    requirements.sort(key=lambda r: r.name)
     return requirements
 
 
@@ -204,5 +261,4 @@
             continue
         requirements += from_requirements_txt(filepath)
 
-    requirements.sort(key=lambda r: r.name)
-    return requirements
\ No newline at end of file
+    return requirements
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/requirements-detector-0.1.1/requirements_detector/formatters.py 
new/requirements-detector-0.4/requirements_detector/formatters.py
--- old/requirements-detector-0.1.1/requirements_detector/formatters.py 
2013-10-17 11:04:16.000000000 +0200
+++ new/requirements-detector-0.4/requirements_detector/formatters.py   
2014-08-21 19:28:36.000000000 +0200
@@ -4,7 +4,7 @@
 
 def requirements_file(requirements_list):
     for requirement in requirements_list:
-        sys.stdout.write(str(requirement))
+        sys.stdout.write(requirement.pip_format())
         sys.stdout.write('\n')
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/requirements-detector-0.1.1/requirements_detector/requirement.py 
new/requirements-detector-0.4/requirements_detector/requirement.py
--- old/requirements-detector-0.1.1/requirements_detector/requirement.py        
2013-10-19 16:33:02.000000000 +0200
+++ new/requirements-detector-0.4/requirements_detector/requirement.py  
2015-03-23 23:11:24.000000000 +0100
@@ -10,9 +10,14 @@
 """
 import os
 import re
-import urlparse
 from pkg_resources import Requirement
 
+try:
+    import urlparse
+except ImportError:
+    # python3
+    from urllib import parse as urlparse
+
 
 def _is_filepath(req):
     # this is (probably) a file
@@ -48,7 +53,7 @@
 
 class DetectedRequirement(object):
 
-    def __init__(self, name=None, url=None, requirement=None):
+    def __init__(self, name=None, url=None, requirement=None, 
location_defined=None):
         if requirement is not None:
             self.name = requirement.key
             self.requirement = requirement
@@ -59,6 +64,20 @@
             self.version_specs = []
             self.url = url
             self.requirement = None
+        self.location_defined = location_defined
+
+    def _format_specs(self):
+        return ','.join(['%s%s' % (comp, version) for comp, version in 
self.version_specs])
+
+    def pip_format(self):
+        if self.url:
+            if self.name:
+                return '%s#egg=%s' % (self.url, self.name)
+            return self.url
+        if self.name:
+            if self.version_specs:
+                return "%s%s" % (self.name, self._format_specs())
+            return self.name
 
     def __str__(self):
         rep = self.name or 'Unknown'
@@ -69,14 +88,20 @@
             rep = '%s (%s)' % (rep, self.url)
         return rep
 
+    def __hash__(self):
+        return hash(str(self.name) + str(self.url) + str(self.version_specs))
+
     def __repr__(self):
         return 'DetectedRequirement:%s' % str(self)
 
     def __eq__(self, other):
         return self.name == other.name and self.url == other.url and 
self.version_specs == other.version_specs
 
+    def __gt__(self, other):
+        return (self.name or "") > (other.name or "")
+
     @staticmethod
-    def parse(line):
+    def parse(line, location_defined=None):
         # the options for a Pip requirements file are:
         #
         # 1) <dependency_name>
@@ -96,14 +121,22 @@
         # if it is a VCS URL, then we want to strip off the protocol as 
urlparse
         # might not handle it correctly
         vcs_scheme = None
-        if '+' in url.scheme:
-            vcs_scheme = url.scheme
+        if '+' in url.scheme or url.scheme in ('git',):
+            if url.scheme == 'git':
+                vcs_scheme = 'git+git'
+            else:
+                vcs_scheme = url.scheme
             url = urlparse.urlparse(re.sub(r'^%s://' % re.escape(url.scheme), 
'', line))
 
         if vcs_scheme is None and url.scheme == '' and not _is_filepath(line):
             # if we are here, it is a simple dependency
-            req = Requirement.parse(line)
-            return DetectedRequirement(requirement=req)
+            try:
+                req = Requirement.parse(line)
+            except ValueError:
+                # this happens if the line is invalid
+                return None
+            else:
+                return DetectedRequirement(requirement=req, 
location_defined=location_defined)
 
         # otherwise, this is some kind of URL
         name = _parse_egg_name(url.fragment)
@@ -112,4 +145,4 @@
         if vcs_scheme:
             url = '%s://%s' % (vcs_scheme, url)
 
-        return DetectedRequirement(name=name, url=url)
\ No newline at end of file
+        return DetectedRequirement(name=name, url=url, 
location_defined=location_defined)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/requirements-detector-0.1.1/requirements_detector.egg-info/PKG-INFO 
new/requirements-detector-0.4/requirements_detector.egg-info/PKG-INFO
--- old/requirements-detector-0.1.1/requirements_detector.egg-info/PKG-INFO     
2013-10-26 17:50:56.000000000 +0200
+++ new/requirements-detector-0.4/requirements_detector.egg-info/PKG-INFO       
2015-03-24 07:41:47.000000000 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.0
+Metadata-Version: 1.1
 Name: requirements-detector
-Version: 0.1.1
+Version: 0.4
 Summary: Python tool to find and list requirements of a Python project
 Home-page: https://github.com/landscapeio/requirements-detector
 Author: landscape.io
@@ -9,3 +9,12 @@
 Description: UNKNOWN
 Keywords: python requirements detector
 Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Developers
+Classifier: Operating System :: Unix
+Classifier: Topic :: Software Development :: Quality Assurance
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.3
+Classifier: License :: OSI Approved :: GNU General Public License v2 or later 
(GPLv2+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/requirements-detector-0.1.1/requirements_detector.egg-info/requires.txt 
new/requirements-detector-0.4/requirements_detector.egg-info/requires.txt
--- old/requirements-detector-0.1.1/requirements_detector.egg-info/requires.txt 
2013-10-26 17:50:56.000000000 +0200
+++ new/requirements-detector-0.4/requirements_detector.egg-info/requires.txt   
2015-03-24 07:41:47.000000000 +0100
@@ -1 +1 @@
-astroid>=1.0.0
\ No newline at end of file
+astroid>=1.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/requirements-detector-0.1.1/setup.py 
new/requirements-detector-0.4/setup.py
--- old/requirements-detector-0.1.1/setup.py    2013-10-26 17:50:46.000000000 
+0200
+++ new/requirements-detector-0.4/setup.py      2015-03-23 23:11:11.000000000 
+0100
@@ -3,11 +3,24 @@
 from setuptools import find_packages
 
 
-_version = "0.1.1"
+_version = "0.4"
 _packages = find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"])
 
 _short_description = "Python tool to find and list requirements of a Python 
project"
 
+_CLASSIFIERS = (
+    'Development Status :: 5 - Production/Stable',
+    'Environment :: Console',
+    'Intended Audience :: Developers',
+    'Operating System :: Unix',
+    'Topic :: Software Development :: Quality Assurance',
+    'Programming Language :: Python :: 2.6',
+    'Programming Language :: Python :: 2.7',
+    'Programming Language :: Python :: 3.3',
+    'License :: OSI Approved :: '
+    'GNU General Public License v2 or later (GPLv2+)',
+)
+
 
 setup(
     name='requirements-detector',
@@ -21,4 +34,5 @@
     packages=_packages,
     license='MIT',
     keywords='python requirements detector',
+    classifiers=_CLASSIFIERS,
 )


Reply via email to