File: test_dsl.py

package info (click to toggle)
pybel 0.15.5-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 16,496 kB
  • sloc: python: 29,392; javascript: 246; makefile: 226; sh: 20
file content (278 lines) | stat: -rw-r--r-- 10,151 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# -*- coding: utf-8 -*-

"""Tests for the internal DSL."""

import unittest

import pybel.constants as pc
from pybel import BELGraph
from pybel.constants import NAME
from pybel.dsl import (
    Abundance,
    ComplexAbundance,
    CompositeAbundance,
    EnumeratedFusionRange,
    Fragment,
    Gene,
    GeneFusion,
    ListAbundanceEmptyException,
    MissingFusionRange,
    Protein,
    Reaction,
    ReactionEmptyException,
)
from pybel.language import Entity
from pybel.testing.utils import n
from pybel.tokens import parse_result_to_dsl
from pybel.utils import ensure_quotes


class TestDSL(unittest.TestCase):
    """Tests for the internal DSL."""

    def test_add_robust_node(self):
        """Test adding a node with both a name and identifier."""
        graph = BELGraph()
        namespace, name, identifier = n(), n(), n()
        node = Protein(namespace=namespace, name=name, identifier=identifier)

        graph.add_node_from_data(node)
        self.assertIn(node, graph)

    def test_add_identified_node(self):
        """Test what happens when a node with only an identifier is added to a graph."""
        graph = BELGraph()
        namespace, identifier = n(), n()
        node = Protein(namespace=namespace, identifier=identifier)
        self.assertNotIn(NAME, node)

        graph.add_node_from_data(node)
        self.assertIn(node, graph)

    def test_add_named_node(self):
        """Test adding a named node to a BEL graph."""
        graph = BELGraph()
        namespace, name = n(), n()
        node = Protein(namespace=namespace, name=name)

        graph.add_node_from_data(node)
        self.assertIn(node, graph)

    def test_missing_information(self):
        """Test that entity and abundance functions raise on missing name/identifier."""
        with self.assertRaises(ValueError):
            Entity(namespace="test")

        with self.assertRaises(ValueError):
            Protein(namespace="test")

        with self.assertRaises(ValueError):
            Protein(namespace="")

        with self.assertRaises(TypeError):
            Protein(namespace="uniprot", name=1234)

        with self.assertRaises(TypeError):
            Protein(namespace="uniprot", identifier=1234)

        with self.assertRaises(ValueError):
            Protein(namespace="uniprot", name="")

        with self.assertRaises(ValueError):
            Protein(namespace="uniprot", identifier="")

        with self.assertRaises(ValueError):
            Protein(namespace="uniprot", identifier="12345", name="")

        with self.assertRaises(ValueError):
            Protein(namespace="uniprot", identifier="", name="123")

    def test_abundance_as_bel_dash_unquoted(self):
        """Test converting an abundance to BEL with a name that needs quotation."""
        namespace, name = "HGNC", "YFG-1"
        node = Abundance(namespace=namespace, name=name)
        self.assertEqual("a(HGNC:YFG-1)", node.as_bel())

    def test_abundance_as_no_quotes(self):
        """Test converting an abundance that doesn't need quotes, but looks crazy."""
        namespace, name = "a-c", "d.e.f"
        node = Abundance(namespace=namespace, name=name)
        self.assertEqual("a(a-c:d.e.f)", node.as_bel())

    def test_abundance_as_bel_quoted(self):
        """Test converting an abundance to BEL with a name that needs quotation."""
        namespace, name = "HGNC", "YFG~1"
        node = Abundance(namespace=namespace, name=name)
        self.assertEqual('a(HGNC:"YFG~1")', node.as_bel())

    def test_abundance_as_bel(self):
        """Test converting an abundance to BEL with a name that does not need quotation."""
        namespace, name = "HGNC", "YFG"
        node = Abundance(namespace=namespace, name=name)
        self.assertEqual("a(HGNC:YFG)", node.as_bel())

    def test_str_has_identifier(self):
        namespace, identifier = n(), n()
        node = Abundance(namespace=namespace, identifier=identifier)
        self.assertEqual(
            "a({namespace}:{identifier})".format(namespace=namespace, identifier=ensure_quotes(identifier)),
            node.as_bel(),
        )

    def test_str_has_both(self):
        namespace, identifier = n(), n()
        node = Abundance(namespace=namespace, identifier=identifier)
        self.assertEqual(
            "a({namespace}:{identifier})".format(namespace=namespace, identifier=ensure_quotes(identifier)),
            node.as_bel(),
        )

    def test_as_tuple(self):
        namespace, name = n(), n()
        node = Abundance(namespace=namespace, name=name)
        self.assertEqual(hash(node), hash(node.as_bel()))

    def test_empty_complex(self):
        """Test that an empty complex causes a failure."""
        with self.assertRaises(ValueError):
            ComplexAbundance(members=[])

    def test_empty_composite(self):
        """Test that an empty complex causes a failure."""
        with self.assertRaises(ValueError):
            CompositeAbundance(members=[])

    def test_complex_with_name(self):
        """Test what happens with a named complex.

        .. code-block::

            complex(SCOMP:"9-1-1 Complex") hasComponent p(HGNC:HUS1)
            complex(SCOMP:"9-1-1 Complex") hasComponent p(HGNC:RAD1)
            complex(SCOMP:"9-1-1 Complex") hasComponent p(HGNC:RAD9A)

        """
        hus1 = Protein(namespace="HGNC", name="HUS1")
        rad1 = Protein(namespace="HGNC", name="RAD1")
        rad9a = Protein(namespace="HGNC", name="RAD9A")
        members = [hus1, rad1, rad9a]

        nine_one_one = ComplexAbundance(members=members, namespace="SCOMP", name="9-1-1 Complex")

        graph = BELGraph()

        graph.add_node_from_data(nine_one_one)
        self.assertIn(nine_one_one, graph)
        self.assertIn(hus1, graph)
        self.assertIn(rad1, graph)
        self.assertIn(rad9a, graph)

    def test_GeneFusion(self):
        """Test serialization of a gene fusion to BEL with a explicit fusion ranges."""
        dsl = GeneFusion(
            Gene("HGNC", "TMPRSS2"),
            Gene("HGNC", "ERG"),
            EnumeratedFusionRange("c", 1, 79),
            EnumeratedFusionRange("c", 312, 5034),
        )
        self.assertEqual('g(fus(HGNC:TMPRSS2, "c.1_79", HGNC:ERG, "c.312_5034"))', dsl.as_bel())

    def test_gene_fusion_missing_implicit(self):
        """Test serialization of a gene fusion to BEL with a implicit missing fusion ranges."""
        dsl = GeneFusion(
            Gene("HGNC", "TMPRSS2"),
            Gene("HGNC", "ERG"),
        )
        self.assertEqual('g(fus(HGNC:TMPRSS2, "?", HGNC:ERG, "?"))', dsl.as_bel())

    def test_gene_fusion_missing_explicit(self):
        """Test serialization of a gene fusion to BEL with an explicit missing fusion ranges."""
        dsl = GeneFusion(
            Gene("HGNC", "TMPRSS2"),
            Gene("HGNC", "ERG"),
            MissingFusionRange(),
            MissingFusionRange(),
        )
        self.assertEqual('g(fus(HGNC:TMPRSS2, "?", HGNC:ERG, "?"))', dsl.as_bel())


class TestCentralDogma(unittest.TestCase):
    """Test functions specific for :class:`CentralDogmaAbundance`s."""

    def test_get_parent(self):
        """Test the get_parent function in :class:`CentralDogmaAbundance`s."""
        ab42 = Protein(name="APP", namespace="HGNC", variants=[Fragment(start=672, stop=713)])
        app = ab42.get_parent()
        self.assertEqual("p(HGNC:APP)", app.as_bel())
        self.assertEqual('p(HGNC:APP, frag("672_713"))', ab42.as_bel())

    def test_with_variants(self):
        """Test the `with_variant` function in :class:`CentralDogmaAbundance`s."""
        app = Protein(name="APP", namespace="HGNC")
        ab42 = app.with_variants(Fragment(start=672, stop=713))
        self.assertEqual("p(HGNC:APP)", app.as_bel())
        self.assertEqual('p(HGNC:APP, frag("672_713"))', ab42.as_bel())

    def test_with_variants_list(self):
        """Test the `with_variant` function in :class:`CentralDogmaAbundance`s."""
        app = Protein(name="APP", namespace="HGNC")
        ab42 = app.with_variants([Fragment(start=672, stop=713)])
        self.assertEqual("p(HGNC:APP)", app.as_bel())
        self.assertEqual('p(HGNC:APP, frag("672_713"))', ab42.as_bel())

    def test_list_abundance_has_contents(self):
        """Test that the construction of list abundance doesn't have empty lists."""
        with self.assertRaises(ListAbundanceEmptyException):
            ComplexAbundance([])

        with self.assertRaises(ListAbundanceEmptyException):
            CompositeAbundance([])

    def test_reaction(self):
        """Add identified reaction."""
        graph = BELGraph()
        reaction = Reaction(
            namespace="rhea",
            identifier="44104",
            reactants=[
                Abundance(namespace="chebi", identifier="17478"),
                Abundance(namespace="chebi", identifier="15377"),
                Abundance(namespace="chebi", identifier="57540"),
            ],
            products=[
                Abundance(namespace="chebi", identifier="29067"),
                Abundance(namespace="chebi", identifier="15378"),
                Abundance(namespace="chebi", identifier="57945"),
            ],
        )
        graph.add_node_from_data(reaction)
        self.assertEqual(7, graph.number_of_nodes())
        self.assertEqual(6, graph.number_of_edges())

    def test_reaction_has_contents(self):
        """Test that the construction of reaction doesn't have empty lists."""
        with self.assertRaises(ReactionEmptyException):
            Reaction([], [])


class TestParse(unittest.TestCase):
    """Test that :func:`parse_result_to_dsl` works correctly."""

    def test_named_complex(self):
        x = ComplexAbundance(
            namespace="a",
            identifier="b",
            members=[
                Protein(namespace="c", identifier="d"),
                Protein(namespace="c", identifier="e"),
            ],
        )

        y = parse_result_to_dsl(dict(x))
        self.assertIsInstance(y, ComplexAbundance)
        self.assertIn(pc.MEMBERS, y)
        self.assertIn(pc.CONCEPT, y)


if __name__ == "__main__":
    unittest.main()