commonnexus 1.9.0__tar.gz → 1.9.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. {commonnexus-1.9.0 → commonnexus-1.9.1}/PKG-INFO +10 -9
  2. {commonnexus-1.9.0 → commonnexus-1.9.1}/README.md +9 -8
  3. {commonnexus-1.9.0 → commonnexus-1.9.1}/setup.cfg +1 -1
  4. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/__init__.py +1 -1
  5. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/nexus.py +15 -2
  6. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus.egg-info/PKG-INFO +10 -9
  7. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_nexus.py +15 -0
  8. {commonnexus-1.9.0 → commonnexus-1.9.1}/LICENSE +0 -0
  9. {commonnexus-1.9.0 → commonnexus-1.9.1}/pyproject.toml +0 -0
  10. {commonnexus-1.9.0 → commonnexus-1.9.1}/setup.py +0 -0
  11. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/__main__.py +0 -0
  12. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/__init__.py +0 -0
  13. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/assumptions.py +0 -0
  14. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/base.py +0 -0
  15. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/characters.py +0 -0
  16. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/codons.py +0 -0
  17. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/distances.py +0 -0
  18. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/notes.py +0 -0
  19. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/sets.py +0 -0
  20. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/taxa.py +0 -0
  21. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/trees.py +0 -0
  22. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/blocks/unaligned.py +0 -0
  23. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/cli_util.py +0 -0
  24. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/command.py +0 -0
  25. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/commands/__init__.py +0 -0
  26. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/commands/characters.py +0 -0
  27. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/commands/combine.py +0 -0
  28. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/commands/help.py +0 -0
  29. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/commands/normalise.py +0 -0
  30. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/commands/split.py +0 -0
  31. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/commands/taxa.py +0 -0
  32. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/commands/trees.py +0 -0
  33. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/tokenizer.py +0 -0
  34. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/tools/__init__.py +0 -0
  35. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/tools/combine.py +0 -0
  36. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/tools/matrix.py +0 -0
  37. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/tools/normalise.py +0 -0
  38. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus/util.py +0 -0
  39. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus.egg-info/SOURCES.txt +0 -0
  40. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus.egg-info/dependency_links.txt +0 -0
  41. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus.egg-info/entry_points.txt +0 -0
  42. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus.egg-info/not-zip-safe +0 -0
  43. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus.egg-info/requires.txt +0 -0
  44. {commonnexus-1.9.0 → commonnexus-1.9.1}/src/commonnexus.egg-info/top_level.txt +0 -0
  45. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_blocks_base.py +0 -0
  46. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_blocks_characters.py +0 -0
  47. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_blocks_distances.py +0 -0
  48. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_blocks_notes.py +0 -0
  49. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_blocks_sets.py +0 -0
  50. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_blocks_taxa.py +0 -0
  51. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_blocks_trees.py +0 -0
  52. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_cli.py +0 -0
  53. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_command.py +0 -0
  54. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_dendropy_examples.py +0 -0
  55. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_regressions.py +0 -0
  56. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_tokenizer.py +0 -0
  57. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_tools_combine.py +0 -0
  58. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_tools_matrix.py +0 -0
  59. {commonnexus-1.9.0 → commonnexus-1.9.1}/tests/test_tools_normalise.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: commonnexus
3
- Version: 1.9.0
3
+ Version: 1.9.1
4
4
  Summary: A nexus (phylogenetics) file reader and writer (.nex, .trees)
5
5
  Home-page: https://github.com/dlce-eva/commonnexus
6
6
  Author: Robert Forkel
@@ -83,14 +83,15 @@ and writing NEXUS
83
83
  >>> print(Nexus.from_blocks(Data.from_data(nex.CHARACTERS.get_matrix())))
84
84
  #NEXUS
85
85
  BEGIN DATA;
86
- DIMENSIONS NCHAR=10;
87
- FORMAT DATATYPE=STANDARD MISSING=? GAP=- SYMBOLS="01";
88
- MATRIX
89
- t1 1001010000
90
- t2 0101000100
91
- t3 0011101010
92
- t4 0001100001
93
- t5 0001100001;
86
+ DIMENSIONS NCHAR=10;
87
+ FORMAT DATATYPE=STANDARD MISSING=? GAP=- SYMBOLS="01";
88
+ MATRIX
89
+ t1 1001010000
90
+ t2 0101000100
91
+ t3 0011101010
92
+ t4 0001100001
93
+ t5 0001100001
94
+ ;
94
95
  END;
95
96
  ```
96
97
 
@@ -46,14 +46,15 @@ and writing NEXUS
46
46
  >>> print(Nexus.from_blocks(Data.from_data(nex.CHARACTERS.get_matrix())))
47
47
  #NEXUS
48
48
  BEGIN DATA;
49
- DIMENSIONS NCHAR=10;
50
- FORMAT DATATYPE=STANDARD MISSING=? GAP=- SYMBOLS="01";
51
- MATRIX
52
- t1 1001010000
53
- t2 0101000100
54
- t3 0011101010
55
- t4 0001100001
56
- t5 0001100001;
49
+ DIMENSIONS NCHAR=10;
50
+ FORMAT DATATYPE=STANDARD MISSING=? GAP=- SYMBOLS="01";
51
+ MATRIX
52
+ t1 1001010000
53
+ t2 0101000100
54
+ t3 0011101010
55
+ t4 0001100001
56
+ t5 0001100001
57
+ ;
57
58
  END;
58
59
  ```
59
60
 
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = commonnexus
3
- version = 1.9.0
3
+ version = 1.9.1
4
4
  author = Robert Forkel
5
5
  author_email = robert_forkel@eva.mpg.de
6
6
  description = A nexus (phylogenetics) file reader and writer (.nex, .trees)
@@ -1,4 +1,4 @@
1
1
  from .nexus import Nexus, Config # noqa: F401
2
2
  from commonnexus.blocks import Block # noqa: F401
3
3
 
4
- __version__ = '1.9.0'
4
+ __version__ = '1.9.1'
@@ -5,6 +5,7 @@ import collections
5
5
  import dataclasses
6
6
 
7
7
  from .tokenizer import TokenType, iter_tokens, get_name
8
+ from .util import log_or_raise
8
9
  from commonnexus.command import Command
9
10
  from commonnexus.blocks import Block
10
11
 
@@ -45,7 +46,7 @@ class Config:
45
46
 
46
47
  class Nexus(list):
47
48
  """
48
- A NEXUS object implemented as list of tokens with methods to access newick constituents.
49
+ A NEXUS object implemented as list of commands with methods to read and write blocks.
49
50
 
50
51
  From the spec:
51
52
 
@@ -95,6 +96,7 @@ class Nexus(list):
95
96
  """
96
97
  self.cfg = config or Config(**kw)
97
98
  self.trailing_whitespace = []
99
+ self.leading = []
98
100
  self.block_implementations = {}
99
101
  for cls in Block.__subclasses__():
100
102
  self.block_implementations[cls.__name__.upper()] = cls
@@ -120,7 +122,10 @@ class Nexus(list):
120
122
  if token.is_semicolon:
121
123
  commands.append(Command(tuple(tokens)))
122
124
  tokens = []
123
- self.trailing_whitespace = tokens
125
+ if commands:
126
+ self.trailing_whitespace = tokens
127
+ else:
128
+ self.leading = tokens
124
129
  s = commands
125
130
  list.__init__(self, s)
126
131
 
@@ -211,6 +216,7 @@ class Nexus(list):
211
216
  END;
212
217
  """
213
218
  return NEXUS \
219
+ + ''.join(str(t) for t in self.leading) \
214
220
  + ''.join(''.join(str(t) for t in cmd) for cmd in self) \
215
221
  + ''.join(str(t) for t in self.trailing_whitespace)
216
222
 
@@ -224,8 +230,10 @@ class Nexus(list):
224
230
  p.write_text(text, encoding=self.cfg.encoding)
225
231
 
226
232
  def iter_comments(self):
233
+ yield from (t for t in self.leading if t.type == TokenType.COMMENT)
227
234
  for cmd in self:
228
235
  yield from (t for t in cmd if t.type == TokenType.COMMENT)
236
+ yield from (t for t in self.trailing_whitespace if t.type == TokenType.COMMENT)
229
237
 
230
238
  @property
231
239
  def comments(self) -> typing.List[str]:
@@ -262,6 +270,8 @@ class Nexus(list):
262
270
 
263
271
  def validate(self, log=None):
264
272
  valid = True
273
+ if any(t.type not in {TokenType.WHITESPACE, TokenType.COMMENT} for t in self.leading):
274
+ log_or_raise('Invalid token in preamble', log=log)
265
275
  for block in self.iter_blocks():
266
276
  #
267
277
  # FIXME: we can do a lot of validation here! If block.__commands__ is a list, there is
@@ -269,6 +279,9 @@ class Nexus(list):
269
279
  # If Payload.__multivalued__ == False, only one command instance is allowed, ...
270
280
  #
271
281
  valid = valid and block.validate(log=log)
282
+ if any(t.type not in {TokenType.WHITESPACE, TokenType.COMMENT}
283
+ for t in self.trailing_whitespace):
284
+ log_or_raise('Invalid token in text after the last command', log=log)
272
285
  return valid
273
286
 
274
287
  def get_numbers(self, object_name, items):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: commonnexus
3
- Version: 1.9.0
3
+ Version: 1.9.1
4
4
  Summary: A nexus (phylogenetics) file reader and writer (.nex, .trees)
5
5
  Home-page: https://github.com/dlce-eva/commonnexus
6
6
  Author: Robert Forkel
@@ -83,14 +83,15 @@ and writing NEXUS
83
83
  >>> print(Nexus.from_blocks(Data.from_data(nex.CHARACTERS.get_matrix())))
84
84
  #NEXUS
85
85
  BEGIN DATA;
86
- DIMENSIONS NCHAR=10;
87
- FORMAT DATATYPE=STANDARD MISSING=? GAP=- SYMBOLS="01";
88
- MATRIX
89
- t1 1001010000
90
- t2 0101000100
91
- t3 0011101010
92
- t4 0001100001
93
- t5 0001100001;
86
+ DIMENSIONS NCHAR=10;
87
+ FORMAT DATATYPE=STANDARD MISSING=? GAP=- SYMBOLS="01";
88
+ MATRIX
89
+ t1 1001010000
90
+ t2 0101000100
91
+ t3 0011101010
92
+ t4 0001100001
93
+ t5 0001100001
94
+ ;
94
95
  END;
95
96
  ```
96
97
 
@@ -161,3 +161,18 @@ def test_Booleans_With_Values(fixture_dir):
161
161
  def test_Mesquite_multitaxa(fixture_dir):
162
162
  nex = Nexus.from_file(fixture_dir / 'multitaxa_mesquite.nex')
163
163
  assert [char.get_matrix() for char in nex.blocks['CHARACTERS']]
164
+
165
+
166
+ def test_comments():
167
+ nex = Nexus('#NEXUS\n[comment]')
168
+ assert nex.comments == ['comment']
169
+ nex.append_block(Block.from_commands([], name='b', comment='block comment'))
170
+ assert nex.comments == ['comment', 'block comment']
171
+
172
+ with pytest.raises(ValueError):
173
+ nex = Nexus('#NEXUS\n[comment]]')
174
+ nex.validate()
175
+
176
+ with pytest.raises(ValueError):
177
+ nex = Nexus('#NEXUS\nBEGIN b; end;[comment]]')
178
+ nex.validate()
File without changes
File without changes
File without changes