Skip to content

Commit 47b881f

Browse files
authored
Merge pull request #1 from pyupio/master
Latest master
2 parents 08d63e2 + b0e830d commit 47b881f

14 files changed

Lines changed: 1138 additions & 780 deletions

README.rst

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Dependency Parser
88

99
.. image:: https://img.shields.io/travis/pyupio/dparse.svg
1010
:target: https://travis-ci.org/pyupio/dparse
11-
11+
1212
.. image:: https://codecov.io/gh/pyupio/dparse/branch/master/graph/badge.svg
1313
:target: https://codecov.io/gh/pyupio/dparse
1414

@@ -61,7 +61,7 @@ To install dparse, run:
6161

6262
.. code-block:: console
6363
64-
$ pip install -e git+https://github.com/pyupio/dparse.git
64+
$ pip install dparse
6565
6666
*****
6767
Usage
@@ -72,18 +72,58 @@ To use dparse in a Python project::
7272
from dparse import parse, filetypes
7373

7474
content = """
75-
-e common/lib/calc
76-
South==1.0.1 --hash==abcdefghijklmno
75+
South==1.0.1 --hash=sha256:abcdefghijklmno
7776
pycrypto>=2.6
78-
git+https://github.com/pmitros/pyfs.git@96e1922348bfe6d99201b9512a9ed946c87b7e0b
79-
distribute>=0.6.28, <0.7
80-
# bogus comment
81-
-e .
82-
pdfminer==20140328
83-
-r production/requirements.txt
84-
--requirement test.txt
8577
"""
8678

87-
df = parse(content, filetype=filetypes.requirements_txt)
79+
df = parse(content, file_type=filetypes.requirements_txt)
8880

8981
print(df.json())
82+
83+
84+
85+
86+
{
87+
"file_type": "requirements.txt",
88+
"content": "\nSouth==1.0.1 --hash=sha256:abcdefghijklmno\npycrypto>=2.6\n",
89+
"path": null,
90+
"sha": null,
91+
"dependencies": [
92+
{
93+
"name": "South",
94+
"specs": [
95+
[
96+
"==",
97+
"1.0.1"
98+
]
99+
],
100+
"line": "South==1.0.1 --hash=sha256:abcdefghijklmno",
101+
"source": "pypi",
102+
"meta": {},
103+
"line_numbers": null,
104+
"index_server": null,
105+
"hashes": [
106+
"--hash=sha256:abcdefghijklmno"
107+
],
108+
"dependency_type": "requirements.txt",
109+
"extras": []
110+
},
111+
{
112+
"name": "pycrypto",
113+
"specs": [
114+
[
115+
">=",
116+
"2.6"
117+
]
118+
],
119+
"line": "pycrypto>=2.6",
120+
"source": "pypi",
121+
"meta": {},
122+
"line_numbers": null,
123+
"index_server": null,
124+
"hashes": [],
125+
"dependency_type": "requirements.txt",
126+
"extras": []
127+
}
128+
]
129+
}

codecov.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ignore:
2+
- "setup.py"

dparse/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
2+
from __future__ import unicode_literals, absolute_import
33
"""Top-level package for Dependency Parser."""
44

55
__author__ = """Jannis Gebauer"""

dparse/dependencies.py

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals, absolute_import
3+
4+
import json
5+
6+
from . import filetypes, errors
7+
8+
9+
class Dependency(object):
10+
"""
11+
12+
"""
13+
14+
def __init__(self, name, specs, line, source="pypi", meta={}, extras=None, line_numbers=None, index_server=None, hashes=(), dependency_type=None):
15+
"""
16+
17+
:param name:
18+
:param specs:
19+
:param line:
20+
:param source:
21+
:param extras:
22+
:param line_numbers:
23+
:param index_server:
24+
:param hashes:
25+
:param dependency_type:
26+
"""
27+
self.name = name
28+
self.key = name.lower().replace("_", "-")
29+
self.specs = specs
30+
self.line = line
31+
self.source = source
32+
self.meta = meta
33+
self.line_numbers = line_numbers
34+
self.index_server = index_server
35+
self.hashes = hashes
36+
self.dependency_type = dependency_type
37+
self.extras = extras
38+
39+
def __str__(self): # pragma: no cover
40+
"""
41+
42+
:return:
43+
"""
44+
return "Dependency({name}, {specs}, {line})".format(
45+
name=self.name,
46+
specs=self.specs,
47+
line=self.line
48+
)
49+
50+
def serialize(self):
51+
"""
52+
53+
:return:
54+
"""
55+
return {
56+
"name": self.name,
57+
"specs": self.specs,
58+
"line": self.line,
59+
"source": self.source,
60+
"meta": self.meta,
61+
"line_numbers": self.line_numbers,
62+
"index_server": self.index_server,
63+
"hashes": self.hashes,
64+
"dependency_type": self.dependency_type,
65+
"extras": self.extras
66+
}
67+
68+
@classmethod
69+
def deserialize(cls, d):
70+
"""
71+
72+
:param d:
73+
:return:
74+
"""
75+
return cls(**d)
76+
77+
@property
78+
def full_name(self):
79+
"""
80+
81+
:return:
82+
"""
83+
if self.extras:
84+
return "{}[{}]".format(self.name, ",".join(self.extras))
85+
return self.name
86+
87+
88+
class DependencyFile(object):
89+
"""
90+
91+
"""
92+
93+
def __init__(self, content, path=None, sha=None, file_type=None, marker=((), ()), parser=None):
94+
"""
95+
96+
:param content:
97+
:param path:
98+
:param sha:
99+
:param marker:
100+
:param file_type:
101+
:param parser:
102+
"""
103+
self.content = content
104+
self.file_type = file_type
105+
self.path = path
106+
self.sha = sha
107+
self.marker = marker
108+
109+
self.dependencies = []
110+
self.resolved_files = []
111+
self.is_valid = False
112+
self.file_marker, self.line_marker = marker
113+
114+
if parser:
115+
self.parser = parser
116+
else:
117+
from . import parser as parser_class
118+
if file_type is not None:
119+
if file_type == filetypes.requirements_txt:
120+
self.parser = parser_class.RequirementsTXTParser
121+
elif file_type == filetypes.tox_ini:
122+
self.parser = parser_class.ToxINIParser
123+
elif file_type == filetypes.conda_yml:
124+
self.parser = parser_class.CondaYMLParser
125+
elif path is not None:
126+
if path.endswith(".txt"):
127+
self.parser = parser_class.RequirementsTXTParser
128+
elif path.endswith(".yml"):
129+
self.parser = parser_class.CondaYMLParser
130+
elif path.endswith(".ini"):
131+
self.parser = parser_class.ToxINIParser
132+
133+
if not hasattr(self, "parser"):
134+
raise errors.UnknownDependencyFileError
135+
136+
self.parser = self.parser(self)
137+
138+
def serialize(self):
139+
"""
140+
141+
:return:
142+
"""
143+
return {
144+
"file_type": self.file_type,
145+
"content": self.content,
146+
"path": self.path,
147+
"sha": self.sha,
148+
"dependencies": [dep.serialize() for dep in self.dependencies]
149+
}
150+
151+
@classmethod
152+
def deserialize(cls, d):
153+
"""
154+
155+
:param d:
156+
:return:
157+
"""
158+
dependencies = [Dependency.deserialize(dep) for dep in d.pop("dependencies", [])]
159+
instance = cls(**d)
160+
instance.dependencies = dependencies
161+
return instance
162+
163+
def json(self): # pragma: no cover
164+
"""
165+
166+
:return:
167+
"""
168+
return json.dumps(self.serialize(), indent=2)
169+
170+
def parse(self):
171+
"""
172+
173+
:return:
174+
"""
175+
if self.parser.is_marked_file:
176+
self.is_valid = False
177+
return self
178+
self.parser.parse()
179+
180+
self.is_valid = len(self.dependencies) > 0 or len(self.resolved_files) > 0
181+
return self

dparse/errors.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals, absolute_import
3+
14
class UnknownDependencyFileError(Exception):
5+
"""
6+
7+
"""
28
pass

dparse/filetypes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals, absolute_import
3+
14
requirements_txt = "requirements.txt"
25
conda_yml = "conda.yml"
36
tox_ini = "tox.ini"

0 commit comments

Comments
 (0)