We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Malformed METADATA when using optional git dependencies
<!--
  Hi there! Thank you for discovering and submitting an issue.

  Before you submit this; let's make sure of a few things.
  Please make sure the following boxes are ticked if they are correct.
  If not, please try and fulfill these first.
-->

<!-- Checked checkbox should look like this: [x] -->
- [x] I am on the [latest](https://github.com/sdispater/poetry/releases/latest) Poetry version.
- [x] I have searched the [issues](https://github.com/sdispater/poetry/issues) of this repo and believe that this is not a duplicate.
- [x] If an exception occurs when executing a command, I executed it again in debug mode (`-vvv` option).

<!--
  Once those are done, if you're able to fill in the following list with your information,
  it'd be very helpful to whoever handles the issue.
-->

- **Poetry version**: 0.12.16
- **Link of a [Gist](https://gist.github.com/) with the contents of your pyproject.toml file**: https://gist.github.com/tyrion/fb7b70d437951548f5ee1b5946b9386e

## Issue

Poetry generates a malformed `METADATA` file when there is an optional git dependency specified in `pyproject.toml` (see attached gist).

To reproduce you just need to place the files contained in the attached gist in a directory and run:
```
$ pip install .
[..]
pip._vendor.pkg_resources.RequirementParseError: Parse error at "'extra =='": Expected stringEnd
```

The responsible for this behaviour is the `poetry.masonry.api.prepare_metadata_for_build_wheel` function, which is called by pip.

The generated `METADATA` file looks something like this:
```
Metadata-Version: 2.1
[..]
Requires-Python: >=3.6
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Provides-Extra: stubs
Requires-Dist: numpy-stubs @ git+https://github.com/numpy/numpy-stubs.git@master; extra == "stubs"
```

You can verify that the last line is incorrect using `pkg_resources`:
```
>>> pkg_resources.Requirement.parse('numpy-stubs @ git+https://github.com/numpy/numpy-stubs.git@master; extra == "stubs"')
pkg_resources.RequirementParseError: Invalid requirement, parse error at "'extra =='"
```
Or in the exact same way pip does:
```
>>> from pip._vendor.packaging import requirements as req
>>> req.REQUIREMENT.parseString('numpy-stubs @ git+https://github.com/numpy/numpy-stubs.git@master; extra == "stubs"')
pip._vendor.pyparsing.ParseException: Expected stringEnd (at char 67), (line:1, col:68)
```

To fix the issue it is necessary to add a space before the ';':
```
>>> req.REQUIREMENT.parseString('numpy-stubs @ git+https://github.com/numpy/numpy-stubs.git@master ; extra == "stubs"')
(['numpy-stubs', 'git+https://github.com/numpy/numpy-stubs.git@master', <Marker('extra == "stubs"')>], {'name': ['numpy-stubs'], 'url': ['git+https://github.com/numpy/numpy-stubs.git@master'], 'marker': [<Marker('extra == "stubs"')>]})
```



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `poetry/packages/dependency.py`
Content:
```
1 import poetry.packages
2 
3 from poetry.semver import parse_constraint
4 from poetry.semver import Version
5 from poetry.semver import VersionConstraint
6 from poetry.semver import VersionRange
7 from poetry.semver import VersionUnion
8 from poetry.utils.helpers import canonicalize_name
9 from poetry.version.markers import AnyMarker
10 from poetry.version.markers import parse_marker
11 
12 from .constraints import parse_constraint as parse_generic_constraint
13 from .constraints.constraint import Constraint
14 from .constraints.multi_constraint import MultiConstraint
15 from .constraints.union_constraint import UnionConstraint
16 
17 
18 class Dependency(object):
19     def __init__(
20         self,
21         name,  # type: str
22         constraint,  # type: str
23         optional=False,  # type: bool
24         category="main",  # type: str
25         allows_prereleases=False,  # type: bool
26     ):
27         self._name = canonicalize_name(name)
28         self._pretty_name = name
29 
30         try:
31             if not isinstance(constraint, VersionConstraint):
32                 self._constraint = parse_constraint(constraint)
33             else:
34                 self._constraint = constraint
35         except ValueError:
36             self._constraint = parse_constraint("*")
37 
38         self._pretty_constraint = str(constraint)
39         self._optional = optional
40         self._category = category
41 
42         if isinstance(self._constraint, VersionRange) and self._constraint.min:
43             allows_prereleases = (
44                 allows_prereleases or self._constraint.min.is_prerelease()
45             )
46 
47         self._allows_prereleases = allows_prereleases
48 
49         self._python_versions = "*"
50         self._python_constraint = parse_constraint("*")
51         self._transitive_python_versions = None
52         self._transitive_python_constraint = None
53 
54         self._extras = []
55         self._in_extras = []
56 
57         self._activated = not self._optional
58 
59         self.is_root = False
60         self.marker = AnyMarker()
61 
62     @property
63     def name(self):
64         return self._name
65 
66     @property
67     def constraint(self):
68         return self._constraint
69 
70     @property
71     def pretty_constraint(self):
72         return self._pretty_constraint
73 
74     @property
75     def pretty_name(self):
76         return self._pretty_name
77 
78     @property
79     def category(self):
80         return self._category
81 
82     @property
83     def python_versions(self):
84         return self._python_versions
85 
86     @python_versions.setter
87     def python_versions(self, value):
88         self._python_versions = value
89         self._python_constraint = parse_constraint(value)
90         if not self._python_constraint.is_any():
91             self.marker = self.marker.intersect(
92                 parse_marker(
93                     self._create_nested_marker(
94                         "python_version", self._python_constraint
95                     )
96                 )
97             )
98 
99     @property
100     def transitive_python_versions(self):
101         if self._transitive_python_versions is None:
102             return self._python_versions
103 
104         return self._transitive_python_versions
105 
106     @transitive_python_versions.setter
107     def transitive_python_versions(self, value):
108         self._transitive_python_versions = value
109         self._transitive_python_constraint = parse_constraint(value)
110 
111     @property
112     def python_constraint(self):
113         return self._python_constraint
114 
115     @property
116     def transitive_python_constraint(self):
117         if self._transitive_python_constraint is None:
118             return self._python_constraint
119 
120         return self._transitive_python_constraint
121 
122     @property
123     def extras(self):  # type: () -> list
124         return self._extras
125 
126     @property
127     def in_extras(self):  # type: () -> list
128         return self._in_extras
129 
130     @property
131     def base_pep_508_name(self):  # type: () -> str
132         requirement = self.pretty_name
133 
134         if self.extras:
135             requirement += "[{}]".format(",".join(self.extras))
136 
137         if isinstance(self.constraint, VersionUnion):
138             requirement += " ({})".format(
139                 ",".join([str(c).replace(" ", "") for c in self.constraint.ranges])
140             )
141         elif isinstance(self.constraint, Version):
142             requirement += " (=={})".format(self.constraint.text)
143         elif not self.constraint.is_any():
144             requirement += " ({})".format(str(self.constraint).replace(" ", ""))
145 
146         return requirement
147 
148     def allows_prereleases(self):
149         return self._allows_prereleases
150 
151     def is_optional(self):
152         return self._optional
153 
154     def is_activated(self):
155         return self._activated
156 
157     def is_vcs(self):
158         return False
159 
160     def is_file(self):
161         return False
162 
163     def is_directory(self):
164         return False
165 
166     def accepts(self, package):  # type: (poetry.packages.Package) -> bool
167         """
168         Determines if the given package matches this dependency.
169         """
170         return (
171             self._name == package.name
172             and self._constraint.allows(package.version)
173             and (not package.is_prerelease() or self.allows_prereleases())
174         )
175 
176     def to_pep_508(self, with_extras=True):  # type: (bool) -> str
177         requirement = self.base_pep_508_name
178 
179         markers = []
180         if not self.marker.is_any():
181             marker = self.marker
182             if not with_extras:
183                 marker = marker.without_extras()
184 
185             if not marker.is_empty():
186                 markers.append(str(marker))
187         else:
188             # Python marker
189             if self.python_versions != "*":
190                 python_constraint = self.python_constraint
191 
192                 markers.append(
193                     self._create_nested_marker("python_version", python_constraint)
194                 )
195 
196         in_extras = " || ".join(self._in_extras)
197         if in_extras and with_extras:
198             markers.append(
199                 self._create_nested_marker("extra", parse_generic_constraint(in_extras))
200             )
201 
202         if markers:
203             if len(markers) > 1:
204                 markers = ["({})".format(m) for m in markers]
205                 requirement += "; {}".format(" and ".join(markers))
206             else:
207                 requirement += "; {}".format(markers[0])
208 
209         return requirement
210 
211     def _create_nested_marker(self, name, constraint):
212         if isinstance(constraint, (MultiConstraint, UnionConstraint)):
213             parts = []
214             for c in constraint.constraints:
215                 multi = False
216                 if isinstance(c, (MultiConstraint, UnionConstraint)):
217                     multi = True
218 
219                 parts.append((multi, self._create_nested_marker(name, c)))
220 
221             glue = " and "
222             if isinstance(constraint, UnionConstraint):
223                 parts = [
224                     "({})".format(part[1]) if part[0] else part[1] for part in parts
225                 ]
226                 glue = " or "
227             else:
228                 parts = [part[1] for part in parts]
229 
230             marker = glue.join(parts)
231         elif isinstance(constraint, Constraint):
232             marker = '{} {} "{}"'.format(name, constraint.operator, constraint.version)
233         elif isinstance(constraint, VersionUnion):
234             parts = []
235             for c in constraint.ranges:
236                 parts.append(self._create_nested_marker(name, c))
237 
238             glue = " or "
239             parts = ["({})".format(part) for part in parts]
240 
241             marker = glue.join(parts)
242         elif isinstance(constraint, Version):
243             marker = '{} == "{}"'.format(name, constraint.text)
244         else:
245             if constraint.min is not None:
246                 op = ">="
247                 if not constraint.include_min:
248                     op = ">"
249 
250                 version = constraint.min.text
251                 if constraint.max is not None:
252                     text = '{} {} "{}"'.format(name, op, version)
253 
254                     op = "<="
255                     if not constraint.include_max:
256                         op = "<"
257 
258                     version = constraint.max
259 
260                     text += ' and {} {} "{}"'.format(name, op, version)
261 
262                     return text
263             elif constraint.max is not None:
264                 op = "<="
265                 if not constraint.include_max:
266                     op = "<"
267 
268                 version = constraint.max
269             else:
270                 return ""
271 
272             marker = '{} {} "{}"'.format(name, op, version)
273 
274         return marker
275 
276     def activate(self):
277         """
278         Set the dependency as mandatory.
279         """
280         self._activated = True
281 
282     def deactivate(self):
283         """
284         Set the dependency as optional.
285         """
286         if not self._optional:
287             self._optional = True
288 
289         self._activated = False
290 
291     def with_constraint(self, constraint):
292         new = Dependency(
293             self.pretty_name,
294             constraint,
295             optional=self.is_optional(),
296             category=self.category,
297             allows_prereleases=self.allows_prereleases(),
298         )
299 
300         new.is_root = self.is_root
301         new.python_versions = self.python_versions
302 
303         for extra in self.extras:
304             new.extras.append(extra)
305 
306         for in_extra in self.in_extras:
307             new.in_extras.append(in_extra)
308 
309         return new
310 
311     def __eq__(self, other):
312         if not isinstance(other, Dependency):
313             return NotImplemented
314 
315         return self._name == other.name and self._constraint == other.constraint
316 
317     def __ne__(self, other):
318         return not self == other
319 
320     def __hash__(self):
321         return hash((self._name, self._pretty_constraint))
322 
323     def __str__(self):
324         if self.is_root:
325             return self._pretty_name
326 
327         return "{} ({})".format(self._pretty_name, self._pretty_constraint)
328 
329     def __repr__(self):
330         return "<{} {}>".format(self.__class__.__name__, str(self))
331
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/poetry/packages/dependency.py b/poetry/packages/dependency.py
--- a/poetry/packages/dependency.py
+++ b/poetry/packages/dependency.py
@@ -200,6 +200,9 @@
             )
 
         if markers:
+            if self.is_vcs():
+                requirement += " "
+
             if len(markers) > 1:
                 markers = ["({})".format(m) for m in markers]
                 requirement += "; {}".format(" and ".join(markers))

{"golden_diff": "diff --git a/poetry/packages/dependency.py b/poetry/packages/dependency.py\n--- a/poetry/packages/dependency.py\n+++ b/poetry/packages/dependency.py\n@@ -200,6 +200,9 @@\n             )\n \n         if markers:\n+            if self.is_vcs():\n+                requirement += \" \"\n+\n             if len(markers) > 1:\n                 markers = [\"({})\".format(m) for m in markers]\n                 requirement += \"; {}\".format(\" and \".join(markers))\n", "issue": "Malformed METADATA when using optional git dependencies\n<!--\r\n  Hi there! Thank you for discovering and submitting an issue.\r\n\r\n  Before you submit this; let's make sure of a few things.\r\n  Please make sure the following boxes are ticked if they are correct.\r\n  If not, please try and fulfill these first.\r\n-->\r\n\r\n<!-- Checked checkbox should look like this: [x] -->\r\n- [x] I am on the [latest](https://github.com/sdispater/poetry/releases/latest) Poetry version.\r\n- [x] I have searched the [issues](https://github.com/sdispater/poetry/issues) of this repo and believe that this is not a duplicate.\r\n- [x] If an exception occurs when executing a command, I executed it again in debug mode (`-vvv` option).\r\n\r\n<!--\r\n  Once those are done, if you're able to fill in the following list with your information,\r\n  it'd be very helpful to whoever handles the issue.\r\n-->\r\n\r\n- **Poetry version**: 0.12.16\r\n- **Link of a [Gist](https://gist.github.com/) with the contents of your pyproject.toml file**: https://gist.github.com/tyrion/fb7b70d437951548f5ee1b5946b9386e\r\n\r\n## Issue\r\n\r\nPoetry generates a malformed `METADATA` file when there is an optional git dependency specified in `pyproject.toml` (see attached gist).\r\n\r\nTo reproduce you just need to place the files contained in the attached gist in a directory and run:\r\n```\r\n$ pip install .\r\n[..]\r\npip._vendor.pkg_resources.RequirementParseError: Parse error at \"'extra =='\": Expected stringEnd\r\n```\r\n\r\nThe responsible for this behaviour is the `poetry.masonry.api.prepare_metadata_for_build_wheel` function, which is called by pip.\r\n\r\nThe generated `METADATA` file looks something like this:\r\n```\r\nMetadata-Version: 2.1\r\n[..]\r\nRequires-Python: >=3.6\r\nClassifier: Programming Language :: Python :: 3\r\nClassifier: Programming Language :: Python :: 3.6\r\nClassifier: Programming Language :: Python :: 3.7\r\nProvides-Extra: stubs\r\nRequires-Dist: numpy-stubs @ git+https://github.com/numpy/numpy-stubs.git@master; extra == \"stubs\"\r\n```\r\n\r\nYou can verify that the last line is incorrect using `pkg_resources`:\r\n```\r\n>>> pkg_resources.Requirement.parse('numpy-stubs @ git+https://github.com/numpy/numpy-stubs.git@master; extra == \"stubs\"')\r\npkg_resources.RequirementParseError: Invalid requirement, parse error at \"'extra =='\"\r\n```\r\nOr in the exact same way pip does:\r\n```\r\n>>> from pip._vendor.packaging import requirements as req\r\n>>> req.REQUIREMENT.parseString('numpy-stubs @ git+https://github.com/numpy/numpy-stubs.git@master; extra == \"stubs\"')\r\npip._vendor.pyparsing.ParseException: Expected stringEnd (at char 67), (line:1, col:68)\r\n```\r\n\r\nTo fix the issue it is necessary to add a space before the ';':\r\n```\r\n>>> req.REQUIREMENT.parseString('numpy-stubs @ git+https://github.com/numpy/numpy-stubs.git@master ; extra == \"stubs\"')\r\n(['numpy-stubs', 'git+https://github.com/numpy/numpy-stubs.git@master', <Marker('extra == \"stubs\"')>], {'name': ['numpy-stubs'], 'url': ['git+https://github.com/numpy/numpy-stubs.git@master'], 'marker': [<Marker('extra == \"stubs\"')>]})\r\n```\r\n\r\n\n", "before_files": [{"content": "import poetry.packages\n\nfrom poetry.semver import parse_constraint\nfrom poetry.semver import Version\nfrom poetry.semver import VersionConstraint\nfrom poetry.semver import VersionRange\nfrom poetry.semver import VersionUnion\nfrom poetry.utils.helpers import canonicalize_name\nfrom poetry.version.markers import AnyMarker\nfrom poetry.version.markers import parse_marker\n\nfrom .constraints import parse_constraint as parse_generic_constraint\nfrom .constraints.constraint import Constraint\nfrom .constraints.multi_constraint import MultiConstraint\nfrom .constraints.union_constraint import UnionConstraint\n\n\nclass Dependency(object):\n    def __init__(\n        self,\n        name,  # type: str\n        constraint,  # type: str\n        optional=False,  # type: bool\n        category=\"main\",  # type: str\n        allows_prereleases=False,  # type: bool\n    ):\n        self._name = canonicalize_name(name)\n        self._pretty_name = name\n\n        try:\n            if not isinstance(constraint, VersionConstraint):\n                self._constraint = parse_constraint(constraint)\n            else:\n                self._constraint = constraint\n        except ValueError:\n            self._constraint = parse_constraint(\"*\")\n\n        self._pretty_constraint = str(constraint)\n        self._optional = optional\n        self._category = category\n\n        if isinstance(self._constraint, VersionRange) and self._constraint.min:\n            allows_prereleases = (\n                allows_prereleases or self._constraint.min.is_prerelease()\n            )\n\n        self._allows_prereleases = allows_prereleases\n\n        self._python_versions = \"*\"\n        self._python_constraint = parse_constraint(\"*\")\n        self._transitive_python_versions = None\n        self._transitive_python_constraint = None\n\n        self._extras = []\n        self._in_extras = []\n\n        self._activated = not self._optional\n\n        self.is_root = False\n        self.marker = AnyMarker()\n\n    @property\n    def name(self):\n        return self._name\n\n    @property\n    def constraint(self):\n        return self._constraint\n\n    @property\n    def pretty_constraint(self):\n        return self._pretty_constraint\n\n    @property\n    def pretty_name(self):\n        return self._pretty_name\n\n    @property\n    def category(self):\n        return self._category\n\n    @property\n    def python_versions(self):\n        return self._python_versions\n\n    @python_versions.setter\n    def python_versions(self, value):\n        self._python_versions = value\n        self._python_constraint = parse_constraint(value)\n        if not self._python_constraint.is_any():\n            self.marker = self.marker.intersect(\n                parse_marker(\n                    self._create_nested_marker(\n                        \"python_version\", self._python_constraint\n                    )\n                )\n            )\n\n    @property\n    def transitive_python_versions(self):\n        if self._transitive_python_versions is None:\n            return self._python_versions\n\n        return self._transitive_python_versions\n\n    @transitive_python_versions.setter\n    def transitive_python_versions(self, value):\n        self._transitive_python_versions = value\n        self._transitive_python_constraint = parse_constraint(value)\n\n    @property\n    def python_constraint(self):\n        return self._python_constraint\n\n    @property\n    def transitive_python_constraint(self):\n        if self._transitive_python_constraint is None:\n            return self._python_constraint\n\n        return self._transitive_python_constraint\n\n    @property\n    def extras(self):  # type: () -> list\n        return self._extras\n\n    @property\n    def in_extras(self):  # type: () -> list\n        return self._in_extras\n\n    @property\n    def base_pep_508_name(self):  # type: () -> str\n        requirement = self.pretty_name\n\n        if self.extras:\n            requirement += \"[{}]\".format(\",\".join(self.extras))\n\n        if isinstance(self.constraint, VersionUnion):\n            requirement += \" ({})\".format(\n                \",\".join([str(c).replace(\" \", \"\") for c in self.constraint.ranges])\n            )\n        elif isinstance(self.constraint, Version):\n            requirement += \" (=={})\".format(self.constraint.text)\n        elif not self.constraint.is_any():\n            requirement += \" ({})\".format(str(self.constraint).replace(\" \", \"\"))\n\n        return requirement\n\n    def allows_prereleases(self):\n        return self._allows_prereleases\n\n    def is_optional(self):\n        return self._optional\n\n    def is_activated(self):\n        return self._activated\n\n    def is_vcs(self):\n        return False\n\n    def is_file(self):\n        return False\n\n    def is_directory(self):\n        return False\n\n    def accepts(self, package):  # type: (poetry.packages.Package) -> bool\n        \"\"\"\n        Determines if the given package matches this dependency.\n        \"\"\"\n        return (\n            self._name == package.name\n            and self._constraint.allows(package.version)\n            and (not package.is_prerelease() or self.allows_prereleases())\n        )\n\n    def to_pep_508(self, with_extras=True):  # type: (bool) -> str\n        requirement = self.base_pep_508_name\n\n        markers = []\n        if not self.marker.is_any():\n            marker = self.marker\n            if not with_extras:\n                marker = marker.without_extras()\n\n            if not marker.is_empty():\n                markers.append(str(marker))\n        else:\n            # Python marker\n            if self.python_versions != \"*\":\n                python_constraint = self.python_constraint\n\n                markers.append(\n                    self._create_nested_marker(\"python_version\", python_constraint)\n                )\n\n        in_extras = \" || \".join(self._in_extras)\n        if in_extras and with_extras:\n            markers.append(\n                self._create_nested_marker(\"extra\", parse_generic_constraint(in_extras))\n            )\n\n        if markers:\n            if len(markers) > 1:\n                markers = [\"({})\".format(m) for m in markers]\n                requirement += \"; {}\".format(\" and \".join(markers))\n            else:\n                requirement += \"; {}\".format(markers[0])\n\n        return requirement\n\n    def _create_nested_marker(self, name, constraint):\n        if isinstance(constraint, (MultiConstraint, UnionConstraint)):\n            parts = []\n            for c in constraint.constraints:\n                multi = False\n                if isinstance(c, (MultiConstraint, UnionConstraint)):\n                    multi = True\n\n                parts.append((multi, self._create_nested_marker(name, c)))\n\n            glue = \" and \"\n            if isinstance(constraint, UnionConstraint):\n                parts = [\n                    \"({})\".format(part[1]) if part[0] else part[1] for part in parts\n                ]\n                glue = \" or \"\n            else:\n                parts = [part[1] for part in parts]\n\n            marker = glue.join(parts)\n        elif isinstance(constraint, Constraint):\n            marker = '{} {} \"{}\"'.format(name, constraint.operator, constraint.version)\n        elif isinstance(constraint, VersionUnion):\n            parts = []\n            for c in constraint.ranges:\n                parts.append(self._create_nested_marker(name, c))\n\n            glue = \" or \"\n            parts = [\"({})\".format(part) for part in parts]\n\n            marker = glue.join(parts)\n        elif isinstance(constraint, Version):\n            marker = '{} == \"{}\"'.format(name, constraint.text)\n        else:\n            if constraint.min is not None:\n                op = \">=\"\n                if not constraint.include_min:\n                    op = \">\"\n\n                version = constraint.min.text\n                if constraint.max is not None:\n                    text = '{} {} \"{}\"'.format(name, op, version)\n\n                    op = \"<=\"\n                    if not constraint.include_max:\n                        op = \"<\"\n\n                    version = constraint.max\n\n                    text += ' and {} {} \"{}\"'.format(name, op, version)\n\n                    return text\n            elif constraint.max is not None:\n                op = \"<=\"\n                if not constraint.include_max:\n                    op = \"<\"\n\n                version = constraint.max\n            else:\n                return \"\"\n\n            marker = '{} {} \"{}\"'.format(name, op, version)\n\n        return marker\n\n    def activate(self):\n        \"\"\"\n        Set the dependency as mandatory.\n        \"\"\"\n        self._activated = True\n\n    def deactivate(self):\n        \"\"\"\n        Set the dependency as optional.\n        \"\"\"\n        if not self._optional:\n            self._optional = True\n\n        self._activated = False\n\n    def with_constraint(self, constraint):\n        new = Dependency(\n            self.pretty_name,\n            constraint,\n            optional=self.is_optional(),\n            category=self.category,\n            allows_prereleases=self.allows_prereleases(),\n        )\n\n        new.is_root = self.is_root\n        new.python_versions = self.python_versions\n\n        for extra in self.extras:\n            new.extras.append(extra)\n\n        for in_extra in self.in_extras:\n            new.in_extras.append(in_extra)\n\n        return new\n\n    def __eq__(self, other):\n        if not isinstance(other, Dependency):\n            return NotImplemented\n\n        return self._name == other.name and self._constraint == other.constraint\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __hash__(self):\n        return hash((self._name, self._pretty_constraint))\n\n    def __str__(self):\n        if self.is_root:\n            return self._pretty_name\n\n        return \"{} ({})\".format(self._pretty_name, self._pretty_constraint)\n\n    def __repr__(self):\n        return \"<{} {}>\".format(self.__class__.__name__, str(self))\n", "path": "poetry/packages/dependency.py"}], "after_files": [{"content": "import poetry.packages\n\nfrom poetry.semver import parse_constraint\nfrom poetry.semver import Version\nfrom poetry.semver import VersionConstraint\nfrom poetry.semver import VersionRange\nfrom poetry.semver import VersionUnion\nfrom poetry.utils.helpers import canonicalize_name\nfrom poetry.version.markers import AnyMarker\nfrom poetry.version.markers import parse_marker\n\nfrom .constraints import parse_constraint as parse_generic_constraint\nfrom .constraints.constraint import Constraint\nfrom .constraints.multi_constraint import MultiConstraint\nfrom .constraints.union_constraint import UnionConstraint\n\n\nclass Dependency(object):\n    def __init__(\n        self,\n        name,  # type: str\n        constraint,  # type: str\n        optional=False,  # type: bool\n        category=\"main\",  # type: str\n        allows_prereleases=False,  # type: bool\n    ):\n        self._name = canonicalize_name(name)\n        self._pretty_name = name\n\n        try:\n            if not isinstance(constraint, VersionConstraint):\n                self._constraint = parse_constraint(constraint)\n            else:\n                self._constraint = constraint\n        except ValueError:\n            self._constraint = parse_constraint(\"*\")\n\n        self._pretty_constraint = str(constraint)\n        self._optional = optional\n        self._category = category\n\n        if isinstance(self._constraint, VersionRange) and self._constraint.min:\n            allows_prereleases = (\n                allows_prereleases or self._constraint.min.is_prerelease()\n            )\n\n        self._allows_prereleases = allows_prereleases\n\n        self._python_versions = \"*\"\n        self._python_constraint = parse_constraint(\"*\")\n        self._transitive_python_versions = None\n        self._transitive_python_constraint = None\n\n        self._extras = []\n        self._in_extras = []\n\n        self._activated = not self._optional\n\n        self.is_root = False\n        self.marker = AnyMarker()\n\n    @property\n    def name(self):\n        return self._name\n\n    @property\n    def constraint(self):\n        return self._constraint\n\n    @property\n    def pretty_constraint(self):\n        return self._pretty_constraint\n\n    @property\n    def pretty_name(self):\n        return self._pretty_name\n\n    @property\n    def category(self):\n        return self._category\n\n    @property\n    def python_versions(self):\n        return self._python_versions\n\n    @python_versions.setter\n    def python_versions(self, value):\n        self._python_versions = value\n        self._python_constraint = parse_constraint(value)\n        if not self._python_constraint.is_any():\n            self.marker = self.marker.intersect(\n                parse_marker(\n                    self._create_nested_marker(\n                        \"python_version\", self._python_constraint\n                    )\n                )\n            )\n\n    @property\n    def transitive_python_versions(self):\n        if self._transitive_python_versions is None:\n            return self._python_versions\n\n        return self._transitive_python_versions\n\n    @transitive_python_versions.setter\n    def transitive_python_versions(self, value):\n        self._transitive_python_versions = value\n        self._transitive_python_constraint = parse_constraint(value)\n\n    @property\n    def python_constraint(self):\n        return self._python_constraint\n\n    @property\n    def transitive_python_constraint(self):\n        if self._transitive_python_constraint is None:\n            return self._python_constraint\n\n        return self._transitive_python_constraint\n\n    @property\n    def extras(self):  # type: () -> list\n        return self._extras\n\n    @property\n    def in_extras(self):  # type: () -> list\n        return self._in_extras\n\n    @property\n    def base_pep_508_name(self):  # type: () -> str\n        requirement = self.pretty_name\n\n        if self.extras:\n            requirement += \"[{}]\".format(\",\".join(self.extras))\n\n        if isinstance(self.constraint, VersionUnion):\n            requirement += \" ({})\".format(\n                \",\".join([str(c).replace(\" \", \"\") for c in self.constraint.ranges])\n            )\n        elif isinstance(self.constraint, Version):\n            requirement += \" (=={})\".format(self.constraint.text)\n        elif not self.constraint.is_any():\n            requirement += \" ({})\".format(str(self.constraint).replace(\" \", \"\"))\n\n        return requirement\n\n    def allows_prereleases(self):\n        return self._allows_prereleases\n\n    def is_optional(self):\n        return self._optional\n\n    def is_activated(self):\n        return self._activated\n\n    def is_vcs(self):\n        return False\n\n    def is_file(self):\n        return False\n\n    def is_directory(self):\n        return False\n\n    def accepts(self, package):  # type: (poetry.packages.Package) -> bool\n        \"\"\"\n        Determines if the given package matches this dependency.\n        \"\"\"\n        return (\n            self._name == package.name\n            and self._constraint.allows(package.version)\n            and (not package.is_prerelease() or self.allows_prereleases())\n        )\n\n    def to_pep_508(self, with_extras=True):  # type: (bool) -> str\n        requirement = self.base_pep_508_name\n\n        markers = []\n        if not self.marker.is_any():\n            marker = self.marker\n            if not with_extras:\n                marker = marker.without_extras()\n\n            if not marker.is_empty():\n                markers.append(str(marker))\n        else:\n            # Python marker\n            if self.python_versions != \"*\":\n                python_constraint = self.python_constraint\n\n                markers.append(\n                    self._create_nested_marker(\"python_version\", python_constraint)\n                )\n\n        in_extras = \" || \".join(self._in_extras)\n        if in_extras and with_extras:\n            markers.append(\n                self._create_nested_marker(\"extra\", parse_generic_constraint(in_extras))\n            )\n\n        if markers:\n            if self.is_vcs():\n                requirement += \" \"\n\n            if len(markers) > 1:\n                markers = [\"({})\".format(m) for m in markers]\n                requirement += \"; {}\".format(\" and \".join(markers))\n            else:\n                requirement += \"; {}\".format(markers[0])\n\n        return requirement\n\n    def _create_nested_marker(self, name, constraint):\n        if isinstance(constraint, (MultiConstraint, UnionConstraint)):\n            parts = []\n            for c in constraint.constraints:\n                multi = False\n                if isinstance(c, (MultiConstraint, UnionConstraint)):\n                    multi = True\n\n                parts.append((multi, self._create_nested_marker(name, c)))\n\n            glue = \" and \"\n            if isinstance(constraint, UnionConstraint):\n                parts = [\n                    \"({})\".format(part[1]) if part[0] else part[1] for part in parts\n                ]\n                glue = \" or \"\n            else:\n                parts = [part[1] for part in parts]\n\n            marker = glue.join(parts)\n        elif isinstance(constraint, Constraint):\n            marker = '{} {} \"{}\"'.format(name, constraint.operator, constraint.version)\n        elif isinstance(constraint, VersionUnion):\n            parts = []\n            for c in constraint.ranges:\n                parts.append(self._create_nested_marker(name, c))\n\n            glue = \" or \"\n            parts = [\"({})\".format(part) for part in parts]\n\n            marker = glue.join(parts)\n        elif isinstance(constraint, Version):\n            marker = '{} == \"{}\"'.format(name, constraint.text)\n        else:\n            if constraint.min is not None:\n                op = \">=\"\n                if not constraint.include_min:\n                    op = \">\"\n\n                version = constraint.min.text\n                if constraint.max is not None:\n                    text = '{} {} \"{}\"'.format(name, op, version)\n\n                    op = \"<=\"\n                    if not constraint.include_max:\n                        op = \"<\"\n\n                    version = constraint.max\n\n                    text += ' and {} {} \"{}\"'.format(name, op, version)\n\n                    return text\n            elif constraint.max is not None:\n                op = \"<=\"\n                if not constraint.include_max:\n                    op = \"<\"\n\n                version = constraint.max\n            else:\n                return \"\"\n\n            marker = '{} {} \"{}\"'.format(name, op, version)\n\n        return marker\n\n    def activate(self):\n        \"\"\"\n        Set the dependency as mandatory.\n        \"\"\"\n        self._activated = True\n\n    def deactivate(self):\n        \"\"\"\n        Set the dependency as optional.\n        \"\"\"\n        if not self._optional:\n            self._optional = True\n\n        self._activated = False\n\n    def with_constraint(self, constraint):\n        new = Dependency(\n            self.pretty_name,\n            constraint,\n            optional=self.is_optional(),\n            category=self.category,\n            allows_prereleases=self.allows_prereleases(),\n        )\n\n        new.is_root = self.is_root\n        new.python_versions = self.python_versions\n\n        for extra in self.extras:\n            new.extras.append(extra)\n\n        for in_extra in self.in_extras:\n            new.in_extras.append(in_extra)\n\n        return new\n\n    def __eq__(self, other):\n        if not isinstance(other, Dependency):\n            return NotImplemented\n\n        return self._name == other.name and self._constraint == other.constraint\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __hash__(self):\n        return hash((self._name, self._pretty_constraint))\n\n    def __str__(self):\n        if self.is_root:\n            return self._pretty_name\n\n        return \"{} ({})\".format(self._pretty_name, self._pretty_constraint)\n\n    def __repr__(self):\n        return \"<{} {}>\".format(self.__class__.__name__, str(self))\n", "path": "poetry/packages/dependency.py"}]}