From 9950debe9cacbe2c19b37425dc6d246ea1e60f34 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 1 Nov 2015 04:49:38 +0100 Subject: [PATCH 01/16] [songs.chordpro] Add a new directive `{tag: ...}` --- patacrep/songs/chordpro/__init__.py | 6 ++++++ patacrep/songs/chordpro/ast.py | 1 + patacrep/songs/chordpro/data/chordpro/song_header | 10 +++++++--- patacrep/songs/chordpro/data/latex/song | 2 +- test/test_chordpro/tags.sgc | 5 +++++ test/test_chordpro/tags.source | 4 ++++ test/test_chordpro/tags.tex | 10 ++++++++++ 7 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 test/test_chordpro/tags.sgc create mode 100644 test/test_chordpro/tags.source create mode 100644 test/test_chordpro/tags.tex diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index c46a0880..b2b328eb 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -3,6 +3,7 @@ from jinja2 import Environment, FileSystemLoader, contextfunction, ChoiceLoader import jinja2 import logging +import operator import os from pkg_resources import resource_filename @@ -14,6 +15,10 @@ from patacrep.latex import lang2babel LOGGER = logging.getLogger(__name__) +def sort_directive_argument(directives): + """Sort directives by their argument.""" + return sorted(directives, key=operator.attrgetter("argument")) + class ChordproSong(Song): """Chordpro song parser""" # pylint: disable=abstract-method @@ -54,6 +59,7 @@ class ChordproSong(Song): jinjaenv.filters['search_image'] = self.search_image jinjaenv.filters['search_partition'] = self.search_partition jinjaenv.filters['lang2babel'] = lang2babel + jinjaenv.filters['sortargs'] = sort_directive_argument try: return Renderer( diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 9213ed37..4fe49001 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -194,6 +194,7 @@ class Song(AST): "artist": "add_author", "key": "add_key", "define": "add_cumulative", + "tag": "add_cumulative", } def __init__(self, filename): diff --git a/patacrep/songs/chordpro/data/chordpro/song_header b/patacrep/songs/chordpro/data/chordpro/song_header index 2ffb1d30..60583433 100644 --- a/patacrep/songs/chordpro/data/chordpro/song_header +++ b/patacrep/songs/chordpro/data/chordpro/song_header @@ -14,16 +14,20 @@ (*- for author in authors -*) {artist: (( author[1] )) (( author[0] ))} -(* endfor *) +(* endfor -*) -(*- for key in ['album', 'copyright', 'tag'] *) +(*- for key in ['album', 'copyright'] *) (* if key in metadata -*) {(( key )): (( metadata[key] ))} (* endif *) (* endfor *) (* if 'cov' in metadata -*) {(( 'cov' )): (( metadata['cov'].argument|search_image ))} -(* endif *) +(* endif -*) + +(* for tag in metadata.get("tag", [])|sortargs -*) + {tag: (( tag.argument ))} +(* endfor -*) (*- for key in metadata.morekeys -*) {key: (( key.keyword )): (( key.argument ))} diff --git a/patacrep/songs/chordpro/data/latex/song b/patacrep/songs/chordpro/data/latex/song index 6f026c79..57714de1 100644 --- a/patacrep/songs/chordpro/data/latex/song +++ b/patacrep/songs/chordpro/data/latex/song @@ -22,7 +22,7 @@ (* endif *) (* endfor *) }, - (* for key in ['album', 'copyright', 'tag'] *) + (* for key in ['album', 'copyright'] *) (* if key in metadata *) (( key ))={(( metadata[key] ))}, (* endif *) diff --git a/test/test_chordpro/tags.sgc b/test/test_chordpro/tags.sgc new file mode 100644 index 00000000..555948c9 --- /dev/null +++ b/test/test_chordpro/tags.sgc @@ -0,0 +1,5 @@ +{lang: en} +{title: Tag test} +{tag: a third tag} +{tag: another} +{tag: one tag} diff --git a/test/test_chordpro/tags.source b/test/test_chordpro/tags.source new file mode 100644 index 00000000..5408dae0 --- /dev/null +++ b/test/test_chordpro/tags.source @@ -0,0 +1,4 @@ +{title: Tag test} +{tag: one tag} +{tag: another} +{tag: a third tag} diff --git a/test/test_chordpro/tags.tex b/test/test_chordpro/tags.tex new file mode 100644 index 00000000..e27a462a --- /dev/null +++ b/test/test_chordpro/tags.tex @@ -0,0 +1,10 @@ +\selectlanguage{english} + +\beginsong{Tag test}[ + by={ + }, +] + + + +\endsong From 5bc7973cafccc2c31de866751f7c064bf703217a Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 1 Nov 2015 05:07:04 +0100 Subject: [PATCH 02/16] [songs.chordpro] Warn when using unknown directives --- patacrep/songs/chordpro/ast.py | 26 +++++++++++++++++++++ test/test_chordpro/invalid_directive.sgc | 1 + test/test_chordpro/invalid_directive.source | 2 ++ test/test_chordpro/invalid_directive.tex | 10 ++++++++ 4 files changed, 39 insertions(+) create mode 100644 test/test_chordpro/invalid_directive.sgc create mode 100644 test/test_chordpro/invalid_directive.source create mode 100644 test/test_chordpro/invalid_directive.tex diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 9213ed37..87ce2a34 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -11,6 +11,27 @@ def _indent(string): """Return and indented version of argument.""" return "\n".join([" {}".format(line) for line in string.split('\n')]) +#: Available directives, that is, directives that we know how to deal with +AVAILABLE_DIRECTIVES = [ + "album", + "artist", + "capo", + "comment", + "copyright", + "columns", + "cov", + "define", + "guitar_comment", + "image", + "key", + "lang", + "newline", + "partition", + "subtitle", + "tag", + "title", + ] + #: List of properties that are to be displayed in the flow of the song (not as #: metadata at the beginning or end of song. INLINE_DIRECTIVES = { @@ -207,6 +228,7 @@ class Song(AST): def add(self, data): """Add an element to the song""" + # pylint: disable=too-many-branches if isinstance(data, Error): pass elif data is None: @@ -221,6 +243,8 @@ class Song(AST): self.content[0].prepend(data.strip()) elif isinstance(data, Directive) and data.inline: # Add a directive in the content of the song. + # It is useless to check if directive is in AVAILABLE_DIRECTIVES, + # since it is in INLINE_DIRECTIVES. self.content.append(data) elif data.inline: # Add an object in the content of the song. @@ -228,6 +252,8 @@ class Song(AST): elif isinstance(data, Directive): # Add a metadata directive. Some of them are added using special # methods listed in ``METADATA_ADD``. + if data.keyword not in AVAILABLE_DIRECTIVES: + LOGGER.warning("Ignoring unknown directive '{}'.".format(data.keyword)) if data.keyword in self.METADATA_ADD: getattr(self, self.METADATA_ADD[data.keyword])(data) else: diff --git a/test/test_chordpro/invalid_directive.sgc b/test/test_chordpro/invalid_directive.sgc new file mode 100644 index 00000000..768ee9ee --- /dev/null +++ b/test/test_chordpro/invalid_directive.sgc @@ -0,0 +1 @@ +{lang: en} diff --git a/test/test_chordpro/invalid_directive.source b/test/test_chordpro/invalid_directive.source new file mode 100644 index 00000000..4f582c43 --- /dev/null +++ b/test/test_chordpro/invalid_directive.source @@ -0,0 +1,2 @@ +{foo: bar} +{bar} diff --git a/test/test_chordpro/invalid_directive.tex b/test/test_chordpro/invalid_directive.tex new file mode 100644 index 00000000..bd99a922 --- /dev/null +++ b/test/test_chordpro/invalid_directive.tex @@ -0,0 +1,10 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + + +\endsong From 3cab46e897a670f1f242edb0152aec54b9d78e72 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 1 Nov 2015 05:16:16 +0100 Subject: [PATCH 03/16] Use full names for cover and language --- examples/songs/chevaliers_de_la_table_ronde.sg | 2 +- examples/songs/example-en.sg | 2 +- examples/songs/example-fr.sg | 2 +- examples/songs/greensleeves.sg | 2 +- examples/songs/vent_frais.sg | 2 +- patacrep/data/latex/patacrep.sty | 2 +- patacrep/songs/chordpro/__init__.py | 2 +- patacrep/songs/chordpro/ast.py | 6 +++--- patacrep/songs/chordpro/data/chordpro/song_header | 4 ++-- patacrep/songs/chordpro/data/latex/song | 12 ++++++------ test/test_chordpro/greensleeves.sgc | 2 +- test/test_chordpro/greensleeves.tex | 2 +- test/test_chordpro/metadata.sgc | 2 +- test/test_chordpro/metadata.tex | 2 +- test/test_compilation/datadir.tex.control | 8 ++++---- .../datadir_datadir/songs/datadir.sg | 2 +- .../datadir_datadir/songs/datadir2.sg | 2 +- .../datadir_datadir/songs/relative.sg | 2 +- .../datadir_datadir/songs/subdir/subdir.sg | 2 +- 19 files changed, 30 insertions(+), 30 deletions(-) diff --git a/examples/songs/chevaliers_de_la_table_ronde.sg b/examples/songs/chevaliers_de_la_table_ronde.sg index 77dfa869..81a725ef 100644 --- a/examples/songs/chevaliers_de_la_table_ronde.sg +++ b/examples/songs/chevaliers_de_la_table_ronde.sg @@ -1,7 +1,7 @@ \selectlanguage{french} \songcolumns{2} \beginsong{Chevaliers de la table ronde} - [by={Traditionnel},cov={traditionnel},album={France}] + [by={Traditionnel},cover={traditionnel},album={France}] \cover \gtab{C}{X32010} diff --git a/examples/songs/example-en.sg b/examples/songs/example-en.sg index 7009cc68..971507a6 100644 --- a/examples/songs/example-en.sg +++ b/examples/songs/example-en.sg @@ -24,7 +24,7 @@ % traditionnel : the file "8-bit-lagerfeuer.jpg" that corresponds to the album art % 8 bit lagerfeuer : the album whose song is extracted from \beginsong{Sad robot} - [by={Pornophonique},cov={traditionnel},album={8 bit lagerfeuer}] + [by={Pornophonique},cover={traditionnel},album={8 bit lagerfeuer}] % inserts the album art (8-bit-lagerfeuer.jpg) \cover diff --git a/examples/songs/example-fr.sg b/examples/songs/example-fr.sg index c9264096..a0d68b58 100644 --- a/examples/songs/example-fr.sg +++ b/examples/songs/example-fr.sg @@ -26,7 +26,7 @@ % traditionnel : le fichier "8-bit-lagerfeuer.jpg" correspondant à la pochette de l'album % 8 bit lagerfeuer : le nom de l'album dont la chanson est extraite \beginsong{Sad robot} - [by={Pornophonique},cov={traditionnel},album={8 bit lagerfeuer}] + [by={Pornophonique},cover={traditionnel},album={8 bit lagerfeuer}] % insère la pochette de l'album (8-bit-lagerfeuer.jpg) \cover diff --git a/examples/songs/greensleeves.sg b/examples/songs/greensleeves.sg index 469fab99..2d9f3c19 100644 --- a/examples/songs/greensleeves.sg +++ b/examples/songs/greensleeves.sg @@ -1,7 +1,7 @@ \selectlanguage{english} \songcolumns{2} \beginsong{Greensleeves} - [by={Traditionnel},cov={traditionnel},album={Angleterre}] + [by={Traditionnel},cover={traditionnel},album={Angleterre}] \cover \gtab{Am}{X02210} diff --git a/examples/songs/vent_frais.sg b/examples/songs/vent_frais.sg index 36584ad7..662a9ea2 100644 --- a/examples/songs/vent_frais.sg +++ b/examples/songs/vent_frais.sg @@ -1,7 +1,7 @@ \selectlanguage{french} \songcolumns{2} \beginsong{Vent frais} - [by={Traditionnel},cov={traditionnel},album={France}] + [by={Traditionnel},cover={traditionnel},album={France}] \cover \gtab{Dm}{XX0231} diff --git a/patacrep/data/latex/patacrep.sty b/patacrep/data/latex/patacrep.sty index d3735739..9368d118 100644 --- a/patacrep/data/latex/patacrep.sty +++ b/patacrep/data/latex/patacrep.sty @@ -139,7 +139,7 @@ \setlength{\coverspace}{0.1cm} \newcommand{\songcover}{} \newcommand{\songalbum}{} -\newsongkey{cov}{\let\songcover\@empty}{\def\songcover{#1}} +\newsongkey{cover}{\let\songcover\@empty}{\def\songcover{#1}} \newsongkey{album}{\let\songalbum\@empty}{\def\songalbum{#1}} \newsongkey{url}{\let\songurl\@empty}{\def\songurl{#1}} \newsongkey{original}{\let\songoriginal\@empty}{\def\songoriginal{#1}} diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index c46a0880..5095c4da 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -26,7 +26,7 @@ class ChordproSong(Song): song = parse_song(song.read(), self.fullpath) self.authors = song.authors self.titles = song.titles - self.lang = song.get_data_argument('lang', self.config['lang']) + self.lang = song.get_data_argument('language', self.config['lang']) self.data = song.meta self.cached = { 'song': song, diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 87ce2a34..0bfc4013 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -24,7 +24,7 @@ AVAILABLE_DIRECTIVES = [ "guitar_comment", "image", "key", - "lang", + "language", "newline", "partition", "subtitle", @@ -51,8 +51,8 @@ DIRECTIVE_SHORTCUTS = { "by": "artist", "c": "comment", "gc": "guitar_comment", - "cover": "cov", - "language": "lang", + "cov": "cover", + "lang": "language", } def directive_name(text): diff --git a/patacrep/songs/chordpro/data/chordpro/song_header b/patacrep/songs/chordpro/data/chordpro/song_header index 2ffb1d30..cefca9de 100644 --- a/patacrep/songs/chordpro/data/chordpro/song_header +++ b/patacrep/songs/chordpro/data/chordpro/song_header @@ -21,8 +21,8 @@ {(( key )): (( metadata[key] ))} (* endif *) (* endfor *) -(* if 'cov' in metadata -*) - {(( 'cov' )): (( metadata['cov'].argument|search_image ))} +(* if 'cover' in metadata -*) + {(( 'cover' )): (( metadata['cover'].argument|search_image ))} (* endif *) (*- for key in metadata.morekeys -*) diff --git a/patacrep/songs/chordpro/data/latex/song b/patacrep/songs/chordpro/data/latex/song index 6f026c79..1e2ceaf8 100644 --- a/patacrep/songs/chordpro/data/latex/song +++ b/patacrep/songs/chordpro/data/latex/song @@ -27,11 +27,11 @@ (( key ))={(( metadata[key] ))}, (* endif *) (* endfor *) - (* if 'cov' in metadata *) - (* block cov *) - (* set cov = metadata["cov"].argument|search_image *) - (* if cov *) - cov={(( cov ))}, + (* if 'cover' in metadata *) + (* block cover *) + (* set cover = metadata["cover"].argument|search_image *) + (* if cover *) + cover={(( cover ))}, (* endif *) (* endblock *) (* endif *) @@ -40,7 +40,7 @@ (* endfor *) ] -(* if (metadata.cov is defined) *) +(* if (metadata.cover is defined) *) \cover (* endif *) diff --git a/test/test_chordpro/greensleeves.sgc b/test/test_chordpro/greensleeves.sgc index 7ff25a58..aec06809 100644 --- a/test/test_chordpro/greensleeves.sgc +++ b/test/test_chordpro/greensleeves.sgc @@ -5,7 +5,7 @@ {title: Un sous titre} {artist: Traditionnel} {album: Angleterre} -{cov: traditionnel} +{cover: traditionnel} {partition: greensleeves.ly} diff --git a/test/test_chordpro/greensleeves.tex b/test/test_chordpro/greensleeves.tex index f582b0c8..c4bc461d 100644 --- a/test/test_chordpro/greensleeves.tex +++ b/test/test_chordpro/greensleeves.tex @@ -7,7 +7,7 @@ Un sous titre}[ by={ Traditionnel }, album={Angleterre}, - cov={img/traditionnel}, + cover={img/traditionnel}, ] \cover diff --git a/test/test_chordpro/metadata.sgc b/test/test_chordpro/metadata.sgc index 22c59f59..322a591b 100644 --- a/test/test_chordpro/metadata.sgc +++ b/test/test_chordpro/metadata.sgc @@ -10,7 +10,7 @@ {artist: Texte de Jean Richepin, chanté par Georges Brassens} {album: Album} {copyright: Copyright} -{cov: metadata_cover} +{cover: metadata_cover} {key: foo: Foo} {comment: Comment} diff --git a/test/test_chordpro/metadata.tex b/test/test_chordpro/metadata.tex index d2a2273a..0be273f1 100644 --- a/test/test_chordpro/metadata.tex +++ b/test/test_chordpro/metadata.tex @@ -11,7 +11,7 @@ Subtitle5}[ Texte de Jean Richepin, chanté par Georges Brassens }, album={Album}, copyright={Copyright}, - cov={img/test/test_chordpro/metadata_cover}, + cover={img/test/test_chordpro/metadata_cover}, foo={Foo}, ] diff --git a/test/test_compilation/datadir.tex.control b/test/test_compilation/datadir.tex.control index 4f6c8521..a003cd42 100644 --- a/test/test_compilation/datadir.tex.control +++ b/test/test_compilation/datadir.tex.control @@ -103,7 +103,7 @@ guitar, Chordpro}[ by={ }, - cov={img/datadir.png}, + cover={img/datadir.png}, ] \cover @@ -130,7 +130,7 @@ Chordpro}[ Chordpro}[ by={ }, - cov={img/datadir2.png}, + cover={img/datadir2.png}, ] \cover @@ -157,7 +157,7 @@ Chordpro}[ Chordpro}[ by={ }, - cov={@TEST_FOLDER@/datadir_datadir/songs/./relative.png}, + cover={@TEST_FOLDER@/datadir_datadir/songs/./relative.png}, ] \cover @@ -184,7 +184,7 @@ Chordpro}[ Chordpro}[ by={ }, - cov={@TEST_FOLDER@/datadir_datadir/songs/./subdir/subdir.png}, + cover={@TEST_FOLDER@/datadir_datadir/songs/./subdir/subdir.png}, ] \cover diff --git a/test/test_compilation/datadir_datadir/songs/datadir.sg b/test/test_compilation/datadir_datadir/songs/datadir.sg index 933e208b..eb937410 100644 --- a/test/test_compilation/datadir_datadir/songs/datadir.sg +++ b/test/test_compilation/datadir_datadir/songs/datadir.sg @@ -1,5 +1,5 @@ \beginsong{Image included from datadir\\\LaTeX} - [cov={img/datadir}] + [cover={img/datadir}] \cover diff --git a/test/test_compilation/datadir_datadir/songs/datadir2.sg b/test/test_compilation/datadir_datadir/songs/datadir2.sg index 6a805725..f37f351f 100644 --- a/test/test_compilation/datadir_datadir/songs/datadir2.sg +++ b/test/test_compilation/datadir_datadir/songs/datadir2.sg @@ -1,5 +1,5 @@ \beginsong{Image included from a different datadir\\\LaTeX} - [cov={img/datadir2}] + [cover={img/datadir2}] \cover diff --git a/test/test_compilation/datadir_datadir/songs/relative.sg b/test/test_compilation/datadir_datadir/songs/relative.sg index 681b4086..3fc326f0 100644 --- a/test/test_compilation/datadir_datadir/songs/relative.sg +++ b/test/test_compilation/datadir_datadir/songs/relative.sg @@ -1,5 +1,5 @@ \beginsong{Image included from song directory\\\LaTeX} - [cov={relative}] + [cover={relative}] \cover diff --git a/test/test_compilation/datadir_datadir/songs/subdir/subdir.sg b/test/test_compilation/datadir_datadir/songs/subdir/subdir.sg index f86b47b4..b2199460 100644 --- a/test/test_compilation/datadir_datadir/songs/subdir/subdir.sg +++ b/test/test_compilation/datadir_datadir/songs/subdir/subdir.sg @@ -1,5 +1,5 @@ \beginsong{Image included from a nested song directory\\\LaTeX} - [cov={subdir}] + [cover={subdir}] \cover From 2dc3b67e2b9c3177ab599a378cd0fd6511041b9a Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Fri, 30 Oct 2015 13:14:27 +0100 Subject: [PATCH 04/16] Change the package_data location --- patacrep/__init__.py | 7 ++++++- .../ast_templates/chordpro}/chordpro/content_chord | 0 .../ast_templates/chordpro}/chordpro/content_chordlist | 0 .../ast_templates/chordpro}/chordpro/content_comment | 0 .../ast_templates/chordpro}/chordpro/content_define | 0 .../ast_templates/chordpro}/chordpro/content_endofline | 0 .../ast_templates/chordpro}/chordpro/content_error | 0 .../chordpro}/chordpro/content_guitar_comment | 0 .../ast_templates/chordpro}/chordpro/content_image | 0 .../ast_templates/chordpro}/chordpro/content_line | 0 .../ast_templates/chordpro}/chordpro/content_newline | 0 .../ast_templates/chordpro}/chordpro/content_partition | 0 .../ast_templates/chordpro}/chordpro/content_space | 0 .../ast_templates/chordpro}/chordpro/content_tablature | 0 .../ast_templates/chordpro}/chordpro/content_verse | 0 .../ast_templates/chordpro}/chordpro/content_word | 0 .../data => data/ast_templates/chordpro}/chordpro/song | 0 .../ast_templates/chordpro}/chordpro/song_body | 0 .../ast_templates/chordpro}/chordpro/song_header | 0 .../ast_templates/chordpro}/html/content_chord | 0 .../ast_templates/chordpro}/html/content_chordlist | 0 .../ast_templates/chordpro}/html/content_comment | 0 .../ast_templates/chordpro}/html/content_define | 0 .../ast_templates/chordpro}/html/content_define_list | 0 .../ast_templates/chordpro}/html/content_endofline | 0 .../ast_templates/chordpro}/html/content_error | 0 .../ast_templates/chordpro}/html/content_guitar_comment | 0 .../ast_templates/chordpro}/html/content_image | 0 .../data => data/ast_templates/chordpro}/html/content_line | 0 .../ast_templates/chordpro}/html/content_metadata_cover | 0 .../ast_templates/chordpro}/html/content_newline | 0 .../ast_templates/chordpro}/html/content_partition | 0 .../ast_templates/chordpro}/html/content_space | 0 .../ast_templates/chordpro}/html/content_tablature | 0 .../ast_templates/chordpro}/html/content_verse | 0 .../data => data/ast_templates/chordpro}/html/content_word | 0 .../data => data/ast_templates/chordpro}/html/song | 0 .../data => data/ast_templates/chordpro}/html/song_body | 0 .../data => data/ast_templates/chordpro}/html/song_header | 0 .../ast_templates/chordpro}/latex/content_chord | 0 .../ast_templates/chordpro}/latex/content_chordlist | 0 .../ast_templates/chordpro}/latex/content_comment | 0 .../ast_templates/chordpro}/latex/content_define | 0 .../ast_templates/chordpro}/latex/content_endofline | 0 .../ast_templates/chordpro}/latex/content_error | 0 .../ast_templates/chordpro}/latex/content_guitar_comment | 0 .../ast_templates/chordpro}/latex/content_image | 0 .../ast_templates/chordpro}/latex/content_line | 0 .../ast_templates/chordpro}/latex/content_newline | 0 .../ast_templates/chordpro}/latex/content_partition | 0 .../ast_templates/chordpro}/latex/content_space | 0 .../ast_templates/chordpro}/latex/content_tablature | 0 .../ast_templates/chordpro}/latex/content_verse | 0 .../ast_templates/chordpro}/latex/content_word | 0 .../data => data/ast_templates/chordpro}/latex/song | 0 .../data => data/ast_templates/chordpro}/latex/song_body | 0 patacrep/songs/chordpro/__init__.py | 5 ++--- setup.py | 7 ++++++- 58 files changed, 14 insertions(+), 5 deletions(-) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_chord (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_chordlist (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_comment (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_define (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_endofline (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_error (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_guitar_comment (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_image (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_line (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_newline (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_partition (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_space (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_tablature (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_verse (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/content_word (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/song (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/song_body (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/chordpro/song_header (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_chord (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_chordlist (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_comment (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_define (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_define_list (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_endofline (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_error (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_guitar_comment (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_image (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_line (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_metadata_cover (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_newline (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_partition (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_space (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_tablature (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_verse (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/content_word (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/song (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/song_body (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/html/song_header (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_chord (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_chordlist (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_comment (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_define (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_endofline (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_error (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_guitar_comment (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_image (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_line (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_newline (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_partition (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_space (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_tablature (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_verse (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/content_word (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/song (100%) rename patacrep/{songs/chordpro/data => data/ast_templates/chordpro}/latex/song_body (100%) diff --git a/patacrep/__init__.py b/patacrep/__init__.py index e63b5123..13e74a66 100644 --- a/patacrep/__init__.py +++ b/patacrep/__init__.py @@ -16,4 +16,9 @@ __version__ = '.'.join([str(number) for number in __TUPLE_VERSION__]) # Directory containing shared data (default templates, custom LaTeX packages, # etc.) -__DATADIR__ = os.path.abspath(resource_filename(__name__, 'data')) +_ROOT = os.path.abspath(resource_filename(__name__, 'data')) +def pkg_datapath(path=''): + """Return the package data path""" + return os.path.join(_ROOT, path) + +__DATADIR__ = os.path.abspath(pkg_datapath()) diff --git a/patacrep/songs/chordpro/data/chordpro/content_chord b/patacrep/data/ast_templates/chordpro/chordpro/content_chord similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_chord rename to patacrep/data/ast_templates/chordpro/chordpro/content_chord diff --git a/patacrep/songs/chordpro/data/chordpro/content_chordlist b/patacrep/data/ast_templates/chordpro/chordpro/content_chordlist similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_chordlist rename to patacrep/data/ast_templates/chordpro/chordpro/content_chordlist diff --git a/patacrep/songs/chordpro/data/chordpro/content_comment b/patacrep/data/ast_templates/chordpro/chordpro/content_comment similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_comment rename to patacrep/data/ast_templates/chordpro/chordpro/content_comment diff --git a/patacrep/songs/chordpro/data/chordpro/content_define b/patacrep/data/ast_templates/chordpro/chordpro/content_define similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_define rename to patacrep/data/ast_templates/chordpro/chordpro/content_define diff --git a/patacrep/songs/chordpro/data/chordpro/content_endofline b/patacrep/data/ast_templates/chordpro/chordpro/content_endofline similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_endofline rename to patacrep/data/ast_templates/chordpro/chordpro/content_endofline diff --git a/patacrep/songs/chordpro/data/chordpro/content_error b/patacrep/data/ast_templates/chordpro/chordpro/content_error similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_error rename to patacrep/data/ast_templates/chordpro/chordpro/content_error diff --git a/patacrep/songs/chordpro/data/chordpro/content_guitar_comment b/patacrep/data/ast_templates/chordpro/chordpro/content_guitar_comment similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_guitar_comment rename to patacrep/data/ast_templates/chordpro/chordpro/content_guitar_comment diff --git a/patacrep/songs/chordpro/data/chordpro/content_image b/patacrep/data/ast_templates/chordpro/chordpro/content_image similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_image rename to patacrep/data/ast_templates/chordpro/chordpro/content_image diff --git a/patacrep/songs/chordpro/data/chordpro/content_line b/patacrep/data/ast_templates/chordpro/chordpro/content_line similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_line rename to patacrep/data/ast_templates/chordpro/chordpro/content_line diff --git a/patacrep/songs/chordpro/data/chordpro/content_newline b/patacrep/data/ast_templates/chordpro/chordpro/content_newline similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_newline rename to patacrep/data/ast_templates/chordpro/chordpro/content_newline diff --git a/patacrep/songs/chordpro/data/chordpro/content_partition b/patacrep/data/ast_templates/chordpro/chordpro/content_partition similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_partition rename to patacrep/data/ast_templates/chordpro/chordpro/content_partition diff --git a/patacrep/songs/chordpro/data/chordpro/content_space b/patacrep/data/ast_templates/chordpro/chordpro/content_space similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_space rename to patacrep/data/ast_templates/chordpro/chordpro/content_space diff --git a/patacrep/songs/chordpro/data/chordpro/content_tablature b/patacrep/data/ast_templates/chordpro/chordpro/content_tablature similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_tablature rename to patacrep/data/ast_templates/chordpro/chordpro/content_tablature diff --git a/patacrep/songs/chordpro/data/chordpro/content_verse b/patacrep/data/ast_templates/chordpro/chordpro/content_verse similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_verse rename to patacrep/data/ast_templates/chordpro/chordpro/content_verse diff --git a/patacrep/songs/chordpro/data/chordpro/content_word b/patacrep/data/ast_templates/chordpro/chordpro/content_word similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/content_word rename to patacrep/data/ast_templates/chordpro/chordpro/content_word diff --git a/patacrep/songs/chordpro/data/chordpro/song b/patacrep/data/ast_templates/chordpro/chordpro/song similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/song rename to patacrep/data/ast_templates/chordpro/chordpro/song diff --git a/patacrep/songs/chordpro/data/chordpro/song_body b/patacrep/data/ast_templates/chordpro/chordpro/song_body similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/song_body rename to patacrep/data/ast_templates/chordpro/chordpro/song_body diff --git a/patacrep/songs/chordpro/data/chordpro/song_header b/patacrep/data/ast_templates/chordpro/chordpro/song_header similarity index 100% rename from patacrep/songs/chordpro/data/chordpro/song_header rename to patacrep/data/ast_templates/chordpro/chordpro/song_header diff --git a/patacrep/songs/chordpro/data/html/content_chord b/patacrep/data/ast_templates/chordpro/html/content_chord similarity index 100% rename from patacrep/songs/chordpro/data/html/content_chord rename to patacrep/data/ast_templates/chordpro/html/content_chord diff --git a/patacrep/songs/chordpro/data/html/content_chordlist b/patacrep/data/ast_templates/chordpro/html/content_chordlist similarity index 100% rename from patacrep/songs/chordpro/data/html/content_chordlist rename to patacrep/data/ast_templates/chordpro/html/content_chordlist diff --git a/patacrep/songs/chordpro/data/html/content_comment b/patacrep/data/ast_templates/chordpro/html/content_comment similarity index 100% rename from patacrep/songs/chordpro/data/html/content_comment rename to patacrep/data/ast_templates/chordpro/html/content_comment diff --git a/patacrep/songs/chordpro/data/html/content_define b/patacrep/data/ast_templates/chordpro/html/content_define similarity index 100% rename from patacrep/songs/chordpro/data/html/content_define rename to patacrep/data/ast_templates/chordpro/html/content_define diff --git a/patacrep/songs/chordpro/data/html/content_define_list b/patacrep/data/ast_templates/chordpro/html/content_define_list similarity index 100% rename from patacrep/songs/chordpro/data/html/content_define_list rename to patacrep/data/ast_templates/chordpro/html/content_define_list diff --git a/patacrep/songs/chordpro/data/html/content_endofline b/patacrep/data/ast_templates/chordpro/html/content_endofline similarity index 100% rename from patacrep/songs/chordpro/data/html/content_endofline rename to patacrep/data/ast_templates/chordpro/html/content_endofline diff --git a/patacrep/songs/chordpro/data/html/content_error b/patacrep/data/ast_templates/chordpro/html/content_error similarity index 100% rename from patacrep/songs/chordpro/data/html/content_error rename to patacrep/data/ast_templates/chordpro/html/content_error diff --git a/patacrep/songs/chordpro/data/html/content_guitar_comment b/patacrep/data/ast_templates/chordpro/html/content_guitar_comment similarity index 100% rename from patacrep/songs/chordpro/data/html/content_guitar_comment rename to patacrep/data/ast_templates/chordpro/html/content_guitar_comment diff --git a/patacrep/songs/chordpro/data/html/content_image b/patacrep/data/ast_templates/chordpro/html/content_image similarity index 100% rename from patacrep/songs/chordpro/data/html/content_image rename to patacrep/data/ast_templates/chordpro/html/content_image diff --git a/patacrep/songs/chordpro/data/html/content_line b/patacrep/data/ast_templates/chordpro/html/content_line similarity index 100% rename from patacrep/songs/chordpro/data/html/content_line rename to patacrep/data/ast_templates/chordpro/html/content_line diff --git a/patacrep/songs/chordpro/data/html/content_metadata_cover b/patacrep/data/ast_templates/chordpro/html/content_metadata_cover similarity index 100% rename from patacrep/songs/chordpro/data/html/content_metadata_cover rename to patacrep/data/ast_templates/chordpro/html/content_metadata_cover diff --git a/patacrep/songs/chordpro/data/html/content_newline b/patacrep/data/ast_templates/chordpro/html/content_newline similarity index 100% rename from patacrep/songs/chordpro/data/html/content_newline rename to patacrep/data/ast_templates/chordpro/html/content_newline diff --git a/patacrep/songs/chordpro/data/html/content_partition b/patacrep/data/ast_templates/chordpro/html/content_partition similarity index 100% rename from patacrep/songs/chordpro/data/html/content_partition rename to patacrep/data/ast_templates/chordpro/html/content_partition diff --git a/patacrep/songs/chordpro/data/html/content_space b/patacrep/data/ast_templates/chordpro/html/content_space similarity index 100% rename from patacrep/songs/chordpro/data/html/content_space rename to patacrep/data/ast_templates/chordpro/html/content_space diff --git a/patacrep/songs/chordpro/data/html/content_tablature b/patacrep/data/ast_templates/chordpro/html/content_tablature similarity index 100% rename from patacrep/songs/chordpro/data/html/content_tablature rename to patacrep/data/ast_templates/chordpro/html/content_tablature diff --git a/patacrep/songs/chordpro/data/html/content_verse b/patacrep/data/ast_templates/chordpro/html/content_verse similarity index 100% rename from patacrep/songs/chordpro/data/html/content_verse rename to patacrep/data/ast_templates/chordpro/html/content_verse diff --git a/patacrep/songs/chordpro/data/html/content_word b/patacrep/data/ast_templates/chordpro/html/content_word similarity index 100% rename from patacrep/songs/chordpro/data/html/content_word rename to patacrep/data/ast_templates/chordpro/html/content_word diff --git a/patacrep/songs/chordpro/data/html/song b/patacrep/data/ast_templates/chordpro/html/song similarity index 100% rename from patacrep/songs/chordpro/data/html/song rename to patacrep/data/ast_templates/chordpro/html/song diff --git a/patacrep/songs/chordpro/data/html/song_body b/patacrep/data/ast_templates/chordpro/html/song_body similarity index 100% rename from patacrep/songs/chordpro/data/html/song_body rename to patacrep/data/ast_templates/chordpro/html/song_body diff --git a/patacrep/songs/chordpro/data/html/song_header b/patacrep/data/ast_templates/chordpro/html/song_header similarity index 100% rename from patacrep/songs/chordpro/data/html/song_header rename to patacrep/data/ast_templates/chordpro/html/song_header diff --git a/patacrep/songs/chordpro/data/latex/content_chord b/patacrep/data/ast_templates/chordpro/latex/content_chord similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_chord rename to patacrep/data/ast_templates/chordpro/latex/content_chord diff --git a/patacrep/songs/chordpro/data/latex/content_chordlist b/patacrep/data/ast_templates/chordpro/latex/content_chordlist similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_chordlist rename to patacrep/data/ast_templates/chordpro/latex/content_chordlist diff --git a/patacrep/songs/chordpro/data/latex/content_comment b/patacrep/data/ast_templates/chordpro/latex/content_comment similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_comment rename to patacrep/data/ast_templates/chordpro/latex/content_comment diff --git a/patacrep/songs/chordpro/data/latex/content_define b/patacrep/data/ast_templates/chordpro/latex/content_define similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_define rename to patacrep/data/ast_templates/chordpro/latex/content_define diff --git a/patacrep/songs/chordpro/data/latex/content_endofline b/patacrep/data/ast_templates/chordpro/latex/content_endofline similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_endofline rename to patacrep/data/ast_templates/chordpro/latex/content_endofline diff --git a/patacrep/songs/chordpro/data/latex/content_error b/patacrep/data/ast_templates/chordpro/latex/content_error similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_error rename to patacrep/data/ast_templates/chordpro/latex/content_error diff --git a/patacrep/songs/chordpro/data/latex/content_guitar_comment b/patacrep/data/ast_templates/chordpro/latex/content_guitar_comment similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_guitar_comment rename to patacrep/data/ast_templates/chordpro/latex/content_guitar_comment diff --git a/patacrep/songs/chordpro/data/latex/content_image b/patacrep/data/ast_templates/chordpro/latex/content_image similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_image rename to patacrep/data/ast_templates/chordpro/latex/content_image diff --git a/patacrep/songs/chordpro/data/latex/content_line b/patacrep/data/ast_templates/chordpro/latex/content_line similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_line rename to patacrep/data/ast_templates/chordpro/latex/content_line diff --git a/patacrep/songs/chordpro/data/latex/content_newline b/patacrep/data/ast_templates/chordpro/latex/content_newline similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_newline rename to patacrep/data/ast_templates/chordpro/latex/content_newline diff --git a/patacrep/songs/chordpro/data/latex/content_partition b/patacrep/data/ast_templates/chordpro/latex/content_partition similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_partition rename to patacrep/data/ast_templates/chordpro/latex/content_partition diff --git a/patacrep/songs/chordpro/data/latex/content_space b/patacrep/data/ast_templates/chordpro/latex/content_space similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_space rename to patacrep/data/ast_templates/chordpro/latex/content_space diff --git a/patacrep/songs/chordpro/data/latex/content_tablature b/patacrep/data/ast_templates/chordpro/latex/content_tablature similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_tablature rename to patacrep/data/ast_templates/chordpro/latex/content_tablature diff --git a/patacrep/songs/chordpro/data/latex/content_verse b/patacrep/data/ast_templates/chordpro/latex/content_verse similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_verse rename to patacrep/data/ast_templates/chordpro/latex/content_verse diff --git a/patacrep/songs/chordpro/data/latex/content_word b/patacrep/data/ast_templates/chordpro/latex/content_word similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_word rename to patacrep/data/ast_templates/chordpro/latex/content_word diff --git a/patacrep/songs/chordpro/data/latex/song b/patacrep/data/ast_templates/chordpro/latex/song similarity index 100% rename from patacrep/songs/chordpro/data/latex/song rename to patacrep/data/ast_templates/chordpro/latex/song diff --git a/patacrep/songs/chordpro/data/latex/song_body b/patacrep/data/ast_templates/chordpro/latex/song_body similarity index 100% rename from patacrep/songs/chordpro/data/latex/song_body rename to patacrep/data/ast_templates/chordpro/latex/song_body diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index 45e2e987..fd035e30 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -5,9 +5,8 @@ import jinja2 import logging import operator import os -from pkg_resources import resource_filename -from patacrep import encoding, files +from patacrep import encoding, files, pkg_datapath from patacrep.songs import Song from patacrep.songs.chordpro.syntax import parse_song from patacrep.templates import Renderer @@ -53,7 +52,7 @@ class ChordproSong(Song): self.get_datadirs(os.path.join("templates", self.output_language)) ), FileSystemLoader( - os.path.join(resource_filename(__name__, 'data'), self.output_language) + os.path.join(pkg_datapath('ast_templates'), 'chordpro', self.output_language) ), ])) jinjaenv.filters['search_image'] = self.search_image diff --git a/setup.py b/setup.py index 4cfaeda0..023201eb 100755 --- a/setup.py +++ b/setup.py @@ -21,7 +21,12 @@ setup( "unidecode", "jinja2", "chardet", "ply", ], setup_requires=["hgtools"], - include_package_data=True, + package_data={'patacrep': [ + 'data/ast_templates/*/*/*', + 'data/img/*', + 'data/latex/*', + 'data/templates/*', + ]}, entry_points={ 'console_scripts': [ "songbook = patacrep.songbook.__main__:main", From 91e10566b9f09ace78156acc70f2c9afbf035eb1 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Fri, 30 Oct 2015 13:15:34 +0100 Subject: [PATCH 05/16] Report if the latex executable is not found --- patacrep/build.py | 17 ++++++++++++++++- patacrep/errors.py | 12 +++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/patacrep/build.py b/patacrep/build.py index 00be667e..d260d45b 100644 --- a/patacrep/build.py +++ b/patacrep/build.py @@ -217,9 +217,24 @@ class SongbookBuilder(object): LOGGER.info("Building '{}.pdf'…".format(self.basename)) self._run_once(self._set_latex) + compiler = "lualatex" + + # test if the LaTeX compiler is accessible + try: + process = Popen( + [compiler, "--version"], + stdin=PIPE, + stdout=PIPE, + stderr=PIPE, + env=os.environ, + universal_newlines=True, + ) + except Exception as error: + raise errors.ExecutableNotFound(compiler) + try: process = Popen( - ["lualatex"] + self._lualatex_options + [self.basename], + [compiler] + self._lualatex_options + [self.basename], stdin=PIPE, stdout=PIPE, stderr=PIPE, diff --git a/patacrep/errors.py b/patacrep/errors.py index 5ec9fd9b..d1d3a74f 100644 --- a/patacrep/errors.py +++ b/patacrep/errors.py @@ -31,6 +31,16 @@ class TemplateError(SongbookError): else: return self.message +class ExecutableNotFound(SongbookError): + """Couldn't find a LaTeX executable.""" + + def __init__(self, executable): + super(ExecutableNotFound, self).__init__( + ( + """Could not find the following executable: {executable}""" + ).format(executable=executable) + ) + class StepError(SongbookError): """Error during execution of one compilation step.""" @@ -47,7 +57,7 @@ class LatexCompilationError(StepError): def __init__(self, basename): super(LatexCompilationError, self).__init__( ( - """Error while pdfLaTeX compilation of "{basename}.tex" """ + """Error while LaTeX compilation of "{basename}.tex" """ """(see {basename}.log for more information).""" ).format(basename=basename) ) From a4d1091e3005664ad7cfc460bb4e34a72b41b106 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Fri, 30 Oct 2015 13:17:49 +0100 Subject: [PATCH 06/16] Use path2posix on LaTeX path --- patacrep/content/song.py | 2 +- .../ast_templates/chordpro/latex/content_image | 2 +- .../chordpro/latex/content_partition | 4 ++-- patacrep/data/ast_templates/chordpro/latex/song | 2 +- patacrep/songs/chordpro/__init__.py | 2 ++ test/test_compilation/test_compilation.py | 15 +++++++++------ 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/patacrep/content/song.py b/patacrep/content/song.py index 71473aa8..4f9ab809 100755 --- a/patacrep/content/song.py +++ b/patacrep/content/song.py @@ -42,7 +42,7 @@ class SongRenderer(Content): {song} """).format( separator="%"*80, - path=self.song.subpath, + path=files.path2posix(self.song.subpath), song=self.song.render(output=context['filename']), ) diff --git a/patacrep/data/ast_templates/chordpro/latex/content_image b/patacrep/data/ast_templates/chordpro/latex/content_image index ac97404b..a567730d 100644 --- a/patacrep/data/ast_templates/chordpro/latex/content_image +++ b/patacrep/data/ast_templates/chordpro/latex/content_image @@ -1,5 +1,5 @@ (* block image *) -(* set image = content.argument|search_image *) +(* set image = content.argument|search_image|path2posix *) (* if image *) \image{(( image ))} (*- endif *) diff --git a/patacrep/data/ast_templates/chordpro/latex/content_partition b/patacrep/data/ast_templates/chordpro/latex/content_partition index a3c35a3e..6942492a 100644 --- a/patacrep/data/ast_templates/chordpro/latex/content_partition +++ b/patacrep/data/ast_templates/chordpro/latex/content_partition @@ -1,6 +1,6 @@ (* block partition *) -(* set partition = content.argument|search_partition *) +(* set partition = content.argument|search_partition|path2posix *) (* if partition *) -\lilypond{ ((- content.argument|search_partition -)) } +\lilypond{ ((- partition -)) } (*- endif -*) (*- endblock -*) diff --git a/patacrep/data/ast_templates/chordpro/latex/song b/patacrep/data/ast_templates/chordpro/latex/song index 2fe34c48..e8016107 100644 --- a/patacrep/data/ast_templates/chordpro/latex/song +++ b/patacrep/data/ast_templates/chordpro/latex/song @@ -29,7 +29,7 @@ (* endfor *) (* if 'cover' in metadata *) (* block cover *) - (* set cover = metadata["cover"].argument|search_image *) + (* set cover = metadata["cover"].argument|search_image|path2posix *) (* if cover *) cover={(( cover ))}, (* endif *) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index fd035e30..46f0f37c 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -11,6 +11,7 @@ from patacrep.songs import Song from patacrep.songs.chordpro.syntax import parse_song from patacrep.templates import Renderer from patacrep.latex import lang2babel +from patacrep.files import path2posix LOGGER = logging.getLogger(__name__) @@ -59,6 +60,7 @@ class ChordproSong(Song): jinjaenv.filters['search_partition'] = self.search_partition jinjaenv.filters['lang2babel'] = lang2babel jinjaenv.filters['sortargs'] = sort_directive_argument + jinjaenv.filters['path2posix'] = path2posix try: return Renderer( diff --git a/test/test_compilation/test_compilation.py b/test/test_compilation/test_compilation.py index dc07107a..d8aee822 100644 --- a/test/test_compilation/test_compilation.py +++ b/test/test_compilation/test_compilation.py @@ -9,6 +9,7 @@ import subprocess import unittest from patacrep.encoding import open_read +from patacrep.files import path2posix from .. import dynamic # pylint: disable=unused-import @@ -67,16 +68,18 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): expected = expectfile.read().strip() expected = expected.replace( "@TEST_FOLDER@", - os.path.dirname(__file__), + path2posix(os.path.dirname(__file__)), ) expected = expected.replace( "@DATA_FOLDER@", - subprocess.check_output( - ["python", "-c", 'import patacrep, pkg_resources; print(pkg_resources.resource_filename(patacrep.__name__, "data"))'], # pylint: disable=line-too-long - universal_newlines=True, - cwd=os.path.dirname(songbook), - ).strip(), + path2posix( + subprocess.check_output( + ["python", "-c", 'import patacrep, pkg_resources; print(pkg_resources.resource_filename(patacrep.__name__, "data"))'], # pylint: disable=line-too-long + universal_newlines=True, + cwd=os.path.dirname(songbook), + ).strip() + ), ) self.assertMultiLineEqual( From 0c7e60ad8ddf68dbd8725a1e7da0f7855f9e723e Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Fri, 30 Oct 2015 13:18:12 +0100 Subject: [PATCH 07/16] Use sys.executable instead of 'python' --- test/test_compilation/test_compilation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_compilation/test_compilation.py b/test/test_compilation/test_compilation.py index d8aee822..efb6ebe4 100644 --- a/test/test_compilation/test_compilation.py +++ b/test/test_compilation/test_compilation.py @@ -5,6 +5,7 @@ import glob import logging import os +import sys import subprocess import unittest @@ -75,7 +76,7 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): "@DATA_FOLDER@", path2posix( subprocess.check_output( - ["python", "-c", 'import patacrep, pkg_resources; print(pkg_resources.resource_filename(patacrep.__name__, "data"))'], # pylint: disable=line-too-long + [sys.executable, "-c", 'import patacrep, pkg_resources; print(pkg_resources.resource_filename(patacrep.__name__, "data"))'], # pylint: disable=line-too-long universal_newlines=True, cwd=os.path.dirname(songbook), ).strip() @@ -111,7 +112,7 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): @staticmethod def compile_songbook(songbook, steps=None): """Compile songbook, and return the command return code.""" - command = ['python', '-m', 'patacrep.songbook', songbook, '-v'] + command = [sys.executable, '-m', 'patacrep.songbook', songbook, '-v'] if steps: command.extend(['--steps', steps]) From 48b49abccfad9fd3520d3b21031e96dd5d63bf14 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Fri, 30 Oct 2015 13:18:51 +0100 Subject: [PATCH 08/16] Add windows tests on AppVeyor --- .appveyor.yml | 47 +++++++++++++++++++++++ patacrep/songbook/__init__.py | 0 test/test_compilation/test_compilation.py | 4 +- tox.ini | 2 +- 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 .appveyor.yml create mode 100644 patacrep/songbook/__init__.py diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 00000000..5f929665 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,47 @@ +environment: + matrix: + - PYTHON: "C:\\Python34" + PYTHON_VERSION: "3.4.x" # currently 3.4.3 + PYTHON_ARCH: "32" + +install: + # Download setup scripts and unzip + - ps: "wget https://github.com/cloudify-cosmo/appveyor-utils/archive/master.zip -OutFile ./master.zip" + - "7z e master.zip */appveyor/* -oappveyor" + + # Install Python (from the official .msi of http://python.org) and pip when + # not already installed. + - "powershell ./appveyor/install.ps1" + + # Prepend newly installed Python to the PATH of this build (this cannot be + # done from inside the powershell script as it would require to restart + # the parent CMD process). + - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" + + # Check that we have the expected version and architecture for Python + - "python --version" + - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" + + # Install miktex portable + - ps: "wget http://mirrors.ctan.org/systems/win32/miktex/setup/miktex-portable-2.9.5719.exe -OutFile ./miktex-portable.exe" + - "7z x miktex-portable.exe * -aot -omiktex > nul" + + #- cmd: dir .\miktex\miktex\bin + + - cmd: set PATH=%PATH%;C:\projects\patacrep\miktex\miktex\bin + #- cmd: echo %PATH% + + #- cmd: C:\projects\patacrep\miktex\miktex\bin\lualatex.exe --version + - cmd: lualatex.exe --version + +build: false # Not a C# project, build stuff at the test step instead. + +before_test: + - "pip install tox" + +test_script: + - "tox" + +# Cache Miktex zip install +cache: +- C:\projects\patacrep\miktex-portable.exe -> .appveyor.yml diff --git a/patacrep/songbook/__init__.py b/patacrep/songbook/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/test_compilation/test_compilation.py b/test/test_compilation/test_compilation.py index efb6ebe4..3b14088b 100644 --- a/test/test_compilation/test_compilation.py +++ b/test/test_compilation/test_compilation.py @@ -96,8 +96,8 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): @classmethod def _create_compilation_test(cls, base): """Return a function testing that `base.tex` is correctly compiled.""" - @unittest.skipIf('TRAVIS' in os.environ, - "Travis does not support lualatex compilation yet") + @unittest.skipIf('TRAVIS' in os.environ or 'APPVEYOR' in os.environ, + "Travis and AppVeyor do not support lualatex compilation yet") def test_compilation(self): """Test that `base` is rendered to pdf.""" # Check compilation diff --git a/tox.ini b/tox.ini index 1b6a3337..99c71416 100644 --- a/tox.ini +++ b/tox.ini @@ -7,7 +7,7 @@ envlist = py34, lint [testenv] commands = {envpython} setup.py test -passenv = TRAVIS +passenv = TRAVIS APPVEYOR deps = [testenv:lint] From 92b7185a7fa59ef86a9f21273f02636af594d355 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 30 Oct 2015 20:57:07 +0100 Subject: [PATCH 09/16] Minor improvements --- patacrep/__init__.py | 4 ++-- patacrep/build.py | 9 ++++----- patacrep/songs/chordpro/__init__.py | 2 +- test/test_compilation/test_compilation.py | 4 ++-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/patacrep/__init__.py b/patacrep/__init__.py index 13e74a66..5effb2c4 100644 --- a/patacrep/__init__.py +++ b/patacrep/__init__.py @@ -17,8 +17,8 @@ __version__ = '.'.join([str(number) for number in __TUPLE_VERSION__]) # etc.) _ROOT = os.path.abspath(resource_filename(__name__, 'data')) -def pkg_datapath(path=''): +def pkg_datapath(*path): """Return the package data path""" - return os.path.join(_ROOT, path) + return os.path.join(_ROOT, *path) __DATADIR__ = os.path.abspath(pkg_datapath()) diff --git a/patacrep/build.py b/patacrep/build.py index d260d45b..766a82d9 100644 --- a/patacrep/build.py +++ b/patacrep/build.py @@ -6,7 +6,7 @@ import glob import logging import threading import os.path -from subprocess import Popen, PIPE, call +from subprocess import Popen, PIPE, call, check_call from patacrep import __DATADIR__, authors, content, errors, files from patacrep.index import process_sxd @@ -219,26 +219,25 @@ class SongbookBuilder(object): compiler = "lualatex" - # test if the LaTeX compiler is accessible + # Test if the LaTeX compiler is accessible try: - process = Popen( + check_call( [compiler, "--version"], stdin=PIPE, stdout=PIPE, stderr=PIPE, - env=os.environ, universal_newlines=True, ) except Exception as error: raise errors.ExecutableNotFound(compiler) + # Perform compilation try: process = Popen( [compiler] + self._lualatex_options + [self.basename], stdin=PIPE, stdout=PIPE, stderr=PIPE, - env=os.environ, universal_newlines=True, ) except Exception as error: diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index 46f0f37c..513977f6 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -53,7 +53,7 @@ class ChordproSong(Song): self.get_datadirs(os.path.join("templates", self.output_language)) ), FileSystemLoader( - os.path.join(pkg_datapath('ast_templates'), 'chordpro', self.output_language) + pkg_datapath('ast_templates', 'chordpro', self.output_language) ), ])) jinjaenv.filters['search_image'] = self.search_image diff --git a/test/test_compilation/test_compilation.py b/test/test_compilation/test_compilation.py index 3b14088b..6b74969b 100644 --- a/test/test_compilation/test_compilation.py +++ b/test/test_compilation/test_compilation.py @@ -76,7 +76,7 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): "@DATA_FOLDER@", path2posix( subprocess.check_output( - [sys.executable, "-c", 'import patacrep, pkg_resources; print(pkg_resources.resource_filename(patacrep.__name__, "data"))'], # pylint: disable=line-too-long + [sys.executable, "-c", 'import patacrep; print(patacrep.__DATADIR__)'], # pylint: disable=line-too-long universal_newlines=True, cwd=os.path.dirname(songbook), ).strip() @@ -117,7 +117,7 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): command.extend(['--steps', steps]) try: - subprocess.check_output( + subprocess.check_call( command, stderr=subprocess.STDOUT, universal_newlines=True, From 41bdc0f0b982e2aebfcc99af1d7a0daf95f75e30 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sun, 1 Nov 2015 21:33:54 +0100 Subject: [PATCH 10/16] Fix AppVeyor caching --- .appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 5f929665..c607ae2a 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -23,7 +23,7 @@ install: - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" # Install miktex portable - - ps: "wget http://mirrors.ctan.org/systems/win32/miktex/setup/miktex-portable-2.9.5719.exe -OutFile ./miktex-portable.exe" + - ps: "If (!(Test-Path miktex-portable.exe)){wget http://mirrors.ctan.org/systems/win32/miktex/setup/miktex-portable-2.9.5719.exe -OutFile ./miktex-portable.exe}" - "7z x miktex-portable.exe * -aot -omiktex > nul" #- cmd: dir .\miktex\miktex\bin @@ -44,4 +44,4 @@ test_script: # Cache Miktex zip install cache: -- C:\projects\patacrep\miktex-portable.exe -> .appveyor.yml +- C:\projects\patacrep\miktex-portable.exe \ No newline at end of file From 79fa3673c6bb0eed76e8fb8f869ed02a06a768bd Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sun, 1 Nov 2015 21:38:05 +0100 Subject: [PATCH 11/16] Fix AppVeyor lualatex comilation --- .appveyor.yml | 8 ++++++-- test/test_compilation/test_compilation.py | 4 ++-- texlive_packages.txt | 13 +++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 texlive_packages.txt diff --git a/.appveyor.yml b/.appveyor.yml index c607ae2a..470021c9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -30,9 +30,13 @@ install: - cmd: set PATH=%PATH%;C:\projects\patacrep\miktex\miktex\bin #- cmd: echo %PATH% + #- cmd: lualatex.exe --version - #- cmd: C:\projects\patacrep\miktex\miktex\bin\lualatex.exe --version - - cmd: lualatex.exe --version + # Update fonts + - cmd: luaotfload-tool.exe --update + + # Manually install required texlive packages + - cmd: mpm.exe --install-some texlive_packages.txt build: false # Not a C# project, build stuff at the test step instead. diff --git a/test/test_compilation/test_compilation.py b/test/test_compilation/test_compilation.py index 6b74969b..240acaf9 100644 --- a/test/test_compilation/test_compilation.py +++ b/test/test_compilation/test_compilation.py @@ -96,8 +96,8 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): @classmethod def _create_compilation_test(cls, base): """Return a function testing that `base.tex` is correctly compiled.""" - @unittest.skipIf('TRAVIS' in os.environ or 'APPVEYOR' in os.environ, - "Travis and AppVeyor do not support lualatex compilation yet") + @unittest.skipIf('TRAVIS' in os.environ, + "Travis does not support lualatex compilation yet") def test_compilation(self): """Test that `base` is rendered to pdf.""" # Check compilation diff --git a/texlive_packages.txt b/texlive_packages.txt new file mode 100644 index 00000000..dac17205 --- /dev/null +++ b/texlive_packages.txt @@ -0,0 +1,13 @@ +babel-english +fancybox +framed +import +l3kernel +l3packages +mptopdf +ms +pgf +tipa +url +xcolor +xstring \ No newline at end of file From e73206cb0df4b953cf1c3e2296f88cb7498ac29a Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sun, 1 Nov 2015 22:04:39 +0100 Subject: [PATCH 12/16] Add missing babel TeX packages --- texlive_packages.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/texlive_packages.txt b/texlive_packages.txt index dac17205..116eac79 100644 --- a/texlive_packages.txt +++ b/texlive_packages.txt @@ -1,4 +1,9 @@ babel-english +ba­bel-es­peranto +babel-french +babel-german +babel-latin +babel-spanish fancybox framed import From 459b06ec7b398602153d9987a67399de7a56d3ab Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sun, 1 Nov 2015 22:23:20 +0100 Subject: [PATCH 13/16] Fix hidden chars --- texlive_packages.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/texlive_packages.txt b/texlive_packages.txt index 116eac79..9320ca2e 100644 --- a/texlive_packages.txt +++ b/texlive_packages.txt @@ -1,5 +1,5 @@ babel-english -ba­bel-es­peranto +babel-esperanto babel-french babel-german babel-latin From 55d06898524a07a61bc069fbdbd9aded7efe4880 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Mon, 2 Nov 2015 12:52:32 +0100 Subject: [PATCH 14/16] Only the Continuous Integration is verbose --- test/test_compilation/test_compilation.py | 6 +++++- tox.ini | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/test_compilation/test_compilation.py b/test/test_compilation/test_compilation.py index 240acaf9..11067c55 100644 --- a/test/test_compilation/test_compilation.py +++ b/test/test_compilation/test_compilation.py @@ -112,10 +112,14 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): @staticmethod def compile_songbook(songbook, steps=None): """Compile songbook, and return the command return code.""" - command = [sys.executable, '-m', 'patacrep.songbook', songbook, '-v'] + command = [sys.executable, '-m', 'patacrep.songbook', songbook] if steps: command.extend(['--steps', steps]) + # Continuous Integration will be verbose + if 'CI' in os.environ: + command.append('-v') + try: subprocess.check_call( command, diff --git a/tox.ini b/tox.ini index 99c71416..10fb9b9b 100644 --- a/tox.ini +++ b/tox.ini @@ -7,7 +7,7 @@ envlist = py34, lint [testenv] commands = {envpython} setup.py test -passenv = TRAVIS APPVEYOR +passenv = TRAVIS APPVEYOR CI deps = [testenv:lint] From 971a7a511486e56143f00f3dd22d8cbe680acb40 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Mon, 2 Nov 2015 12:55:19 +0100 Subject: [PATCH 15/16] _ROOT variable is useless --- patacrep/__init__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/patacrep/__init__.py b/patacrep/__init__.py index 5effb2c4..60e4cd6a 100644 --- a/patacrep/__init__.py +++ b/patacrep/__init__.py @@ -16,9 +16,7 @@ __version__ = '.'.join([str(number) for number in __TUPLE_VERSION__]) # Directory containing shared data (default templates, custom LaTeX packages, # etc.) -_ROOT = os.path.abspath(resource_filename(__name__, 'data')) +__DATADIR__ = os.path.abspath(resource_filename(__name__, 'data')) def pkg_datapath(*path): """Return the package data path""" - return os.path.join(_ROOT, *path) - -__DATADIR__ = os.path.abspath(pkg_datapath()) + return os.path.join(__DATADIR__, *path) From f650d154e13c8e8135f26a270145aee94bf599c0 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Mon, 2 Nov 2015 13:50:38 +0100 Subject: [PATCH 16/16] Clean appveyor.yml comments --- .appveyor.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 470021c9..913363b9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -22,15 +22,14 @@ install: - "python --version" - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" - # Install miktex portable + # Download miktex portable (if not cached) - ps: "If (!(Test-Path miktex-portable.exe)){wget http://mirrors.ctan.org/systems/win32/miktex/setup/miktex-portable-2.9.5719.exe -OutFile ./miktex-portable.exe}" - - "7z x miktex-portable.exe * -aot -omiktex > nul" - #- cmd: dir .\miktex\miktex\bin + # Unzip miktex portable + - "7z x miktex-portable.exe * -aot -omiktex > nul" + # Let the binaries be directly callable - cmd: set PATH=%PATH%;C:\projects\patacrep\miktex\miktex\bin - #- cmd: echo %PATH% - #- cmd: lualatex.exe --version # Update fonts - cmd: luaotfload-tool.exe --update @@ -46,6 +45,6 @@ before_test: test_script: - "tox" -# Cache Miktex zip install +# Cache Miktex Portable file cache: - C:\projects\patacrep\miktex-portable.exe \ No newline at end of file