From b777df787427261bbbece75b1f0939d247e850c6 Mon Sep 17 00:00:00 2001 From: Joeri Exelmans Date: Fri, 3 Mar 2023 18:06:13 +0100 Subject: [PATCH] Update project layout --- .gitignore | 3 +- README.md | 34 +++++++++++-- default.nix | 12 +++++ pyproject.toml | 21 -------- setup.py | 16 ++++++ shell.nix | 15 ------ src/{xopp2py_oml => xopp2oml}/__init__.py | 0 src/xopp2oml/convert.py | 22 +++++++++ .../template.oml} | 46 +++++++++--------- .../oml_writer.py => xopp2oml/writer.py} | 2 +- src/xopp2py/main.py | 25 ---------- test/run_tests.py | 21 ++++++++ .../test_data}/SmallXournalFile.xopp | Bin .../test_data}/TwoHiddenLayers.xopp | Bin tests/test_xopp2py.py | 17 ------- 15 files changed, 127 insertions(+), 107 deletions(-) create mode 100644 default.nix delete mode 100644 pyproject.toml create mode 100644 setup.py delete mode 100644 shell.nix rename src/{xopp2py_oml => xopp2oml}/__init__.py (100%) create mode 100644 src/xopp2oml/convert.py rename src/{xopp2py_oml/oml_writer.template => xopp2oml/template.oml} (53%) rename src/{xopp2py_oml/oml_writer.py => xopp2oml/writer.py} (88%) delete mode 100644 src/xopp2py/main.py create mode 100644 test/run_tests.py rename {tests/data => test/test_data}/SmallXournalFile.xopp (100%) rename {tests/data => test/test_data}/TwoHiddenLayers.xopp (100%) delete mode 100644 tests/test_xopp2py.py diff --git a/.gitignore b/.gitignore index 9cb9928..ba0430d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -__pycache__/ -dist/ \ No newline at end of file +__pycache__/ \ No newline at end of file diff --git a/README.md b/README.md index f1ce98c..cfe9e8f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,33 @@ -# xopp2py +# Python interface to Xournal++ (.xopp) file format -Python interface to .xopp (Xournal++) files. +## Packages -The only dependency is Python 3. (developed with Python 3.10) \ No newline at end of file +This project contains the following packages, under `src`: + - xopp2py + - xopp2oml + +### xopp2py + +Python interface to .xopp (Xournal++) + +Dependencies: Python3 + +### xopp2oml + +XOPP to OML converter + +Dependencies: Python3, Jinja2, xopp2py + +#### Entry point: xopp2oml.convert + +Python script that takes as input as .xopp file and produces as output an .oml file. + + +## Running the tests + +The tests are not included in the packages themselves, but as a separate script. + +To run the tests, make sure the packages are installed, and run: +``` +python test/run_tests.py +``` diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..48f97dd --- /dev/null +++ b/default.nix @@ -0,0 +1,12 @@ +{ pkgs ? import {} }: + +pkgs.python3Packages.buildPythonPackage rec { + pname = "xopp2py"; + version = "1.0.0"; + + src = ./.; + + propagatedBuildInputs = [ + pkgs.python3Packages.jinja2 + ]; +} diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 5d1f426..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,21 +0,0 @@ -[project] -name = "xopp2py" -description = "A Python interface to the Xournal++ file format" -version = "1.0.0" -authors = [ - { name="Joeri Exelmans", email="joeri.exelmans@uantwerpen.be" }, -] -readme = "README.md" -requires-python = ">=3.10" -classifiers = [ - "Programming Language :: Python :: 3", - "Operating System :: OS Independent", -] - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[project.urls] -"Homepage" = "https://msdl.uantwerpen.be/git/jexelmans/xopp2py" -"Bug Tracker" = "https://msdl.uantwerpen.be/git/jexelmans/xopp2py/issues" diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2ad30a0 --- /dev/null +++ b/setup.py @@ -0,0 +1,16 @@ +from setuptools import setup, find_packages + +setup( + name='xopp2oml', + version='1.0.0', + + install_requires=[ + 'jinja2', + ], + + package_dir={"":"src"}, + packages=['xopp2py', 'xopp2oml'], + + include_package_data=True, + package_data={"xopp2oml": ["template.oml"]}, +) \ No newline at end of file diff --git a/shell.nix b/shell.nix deleted file mode 100644 index 2416a4a..0000000 --- a/shell.nix +++ /dev/null @@ -1,15 +0,0 @@ -# Generates a shell from where all the dependencies can be found. - -{ pkgs ? import {} }: - -let - SOURCE_DIR = builtins.toString ./src; -in - pkgs.mkShell { - buildInputs = [ - pkgs.python3 - pkgs.python3Packages.jinja2 - ]; - - PYTHONPATH = SOURCE_DIR; - } \ No newline at end of file diff --git a/src/xopp2py_oml/__init__.py b/src/xopp2oml/__init__.py similarity index 100% rename from src/xopp2py_oml/__init__.py rename to src/xopp2oml/__init__.py diff --git a/src/xopp2oml/convert.py b/src/xopp2oml/convert.py new file mode 100644 index 0000000..c58213b --- /dev/null +++ b/src/xopp2oml/convert.py @@ -0,0 +1,22 @@ +# Command-line tool that demonstrates how to use this library. + +if __name__ == "__main__": + import argparse + argparser = argparse.ArgumentParser( + description = "Python interface for Xournal++ (.xopp) files.") + argparser.add_argument('inputfile') + argparser.add_argument('-o', '--output', metavar='FILE', nargs=1, help="OML output file. If not specified, output will be printed to stdout.") + args = argparser.parse_args() # exits on error + + # Parse .xopp + from xopp2py import parser + asyntax = parser.parseFile(args.inputfile) + + # Generate OML + from xopp2oml import writer + if args.output == None: + import sys + writer.writeOML(asyntax, args.inputfile, "my_xopp", sys.stdout) + else: + with open(args.output[0], 'wt') as f: + writer.writeOML(asyntax, args.inputfile, "my_xopp", f) \ No newline at end of file diff --git a/src/xopp2py_oml/oml_writer.template b/src/xopp2oml/template.oml similarity index 53% rename from src/xopp2py_oml/oml_writer.template rename to src/xopp2oml/template.oml index ca636a5..afd77db 100644 --- a/src/xopp2py_oml/oml_writer.template +++ b/src/xopp2oml/template.oml @@ -1,9 +1,9 @@ {%- macro attributes(pageindex, page, layerindex, layer, elementindex, element) -%} {%- for key,value in element.attributes.items() %} - ci p{{pageindex}}l{{layerindex}}e{{elementindex}}a{{loop.index}} : xournalpp:XMLAttribute [ - xournalpp:hasKey "{{key}}" - xournalpp:hasValue "{{value}}" - xournalpp:ofLayerElement p{{pageindex}}l{{layerindex}}e{{elementindex}} + ci p{{pageindex}}l{{layerindex}}e{{elementindex}}a{{loop.index}} : xopp:XMLAttribute [ + xopp:hasKey "{{key}}" + xopp:hasValue "{{value}}" + xopp:ofLayerElement p{{pageindex}}l{{layerindex}}e{{elementindex}} object_diagram:inModel model ] {% endfor %} @@ -11,9 +11,9 @@ {%- macro elements(pageindex, page, layerindex, layer) -%} {% for el in layer.elements %} - ci p{{pageindex}}l{{layerindex}}e{{loop.index}} : xournalpp:{{el.__class__.__name__}} [ - xournalpp:hasText "{{el.text}}" - xournalpp:inLayer p{{pageindex}}l{{layerindex}} + ci p{{pageindex}}l{{layerindex}}e{{loop.index}} : xopp:{{el.__class__.__name__}} [ + xopp:hasText "{{el.text}}" + xopp:inLayer p{{pageindex}}l{{layerindex}} object_diagram:inModel model ] {{ attributes(pageindex, page, layerindex, layer, loop.index, el) -}} @@ -22,8 +22,8 @@ {%- macro layers(pageindex, page) -%} {% for layer in page.layers %} - ci p{{pageindex}}l{{loop.index}} : xournalpp:Layer [ - xournalpp:inPage p{{pageindex}} + ci p{{pageindex}}l{{loop.index}} : xopp:Layer [ + xopp:inPage p{{pageindex}} object_diagram:inModel model ] {{ elements(pageindex, page, loop.index, layer) -}} @@ -32,13 +32,13 @@ {%- macro pages(file) -%} {% for page in file.pages -%} - ci p{{loop.index}} : xournalpp:Page [ - xournalpp:hasWidth {{ page.width }} - xournalpp:hasHeight {{ page.height }} - xournalpp:hasBackgroundType "{{ page.background_type }}" - xournalpp:hasBackgroundColor "{{ page.background_color }}" - xournalpp:hasBackgroundStyle "{{ page.background_style }}" - xournalpp:inFile file + ci p{{loop.index}} : xopp:Page [ + xopp:hasWidth {{ page.width }} + xopp:hasHeight {{ page.height }} + xopp:hasBackgroundType "{{ page.background_type }}" + xopp:hasBackgroundColor "{{ page.background_color }}" + xopp:hasBackgroundStyle "{{ page.background_style }}" + xopp:inFile file object_diagram:inModel model ] {{ layers(loop.index, page) -}} @@ -49,17 +49,17 @@ // Generator: https://msdl.uantwerpen.be/git/jexelmans/xopp2py description as {{namespace}} { - uses as xournalpp + uses as xopp uses as object_diagram - ci model : xournalpp:Model [] + ci model : xopp:Model [] - ci file : xournalpp:File [ - xournalpp:hasCreator "{{ file.creator }}" - xournalpp:hasFileVersion {{ file.fileversion }} - xournalpp:hasTitle "{{ file.title }}" + ci file : xopp:File [ + xopp:hasCreator "{{ file.creator }}" + xopp:hasFileVersion {{ file.fileversion }} + xopp:hasTitle "{{ file.title }}" {%- if file.preview != None %} - xournalpp:hasPreview "{{ toBase64(file.preview).decode('utf-8') }}" + xopp:hasPreview "{{ toBase64(file.preview).decode('utf-8') }}" {%- endif %} object_diagram:inModel model ] diff --git a/src/xopp2py_oml/oml_writer.py b/src/xopp2oml/writer.py similarity index 88% rename from src/xopp2py_oml/oml_writer.py rename to src/xopp2oml/writer.py index d13ad1d..ad13c8f 100644 --- a/src/xopp2py_oml/oml_writer.py +++ b/src/xopp2oml/writer.py @@ -9,7 +9,7 @@ def writeOML(xournalFile: abstract_syntax.XournalFile, inputfile:str, namespace: environment = jinja2.Environment( loader=jinja2.FileSystemLoader(os.path.dirname(__file__))) - template = environment.get_template("oml_writer.template") + template = environment.get_template("template.oml") for piece in template.generate( file=xournalFile, toBase64=base64.b64encode, diff --git a/src/xopp2py/main.py b/src/xopp2py/main.py deleted file mode 100644 index f11d87c..0000000 --- a/src/xopp2py/main.py +++ /dev/null @@ -1,25 +0,0 @@ -# Command-line tool that demonstrates how to use this library. - -import argparse - -if __name__ == "__main__": - argparser = argparse.ArgumentParser( - description = "Python interface for Xournal++ (.xopp) files.") - argparser.add_argument('filename') - argparser.add_argument('--print-oml', action='store_true', help="Convert to OML and print") - argparser.add_argument('--write-oml', metavar='FILE', nargs=1, help="Convert to OML and write to file") - args = argparser.parse_args() # exits on error - - print(args) - - from xopp2py import parser - - asyntax = parser.parseFile(args.filename) - if args.print_oml: - from xopp2py_oml import oml_writer - import sys - oml_writer.writeOML(asyntax, args.filename, "my_xopp", sys.stdout) - elif args.write_oml != None: - from xopp2py_oml import oml_writer - with open(args.write_oml[0], 'wt') as f: - oml_writer.writeOML(asyntax, args.filename, "my_xopp", f) \ No newline at end of file diff --git a/test/run_tests.py b/test/run_tests.py new file mode 100644 index 0000000..ca6e3f0 --- /dev/null +++ b/test/run_tests.py @@ -0,0 +1,21 @@ +from xopp2py import parser, abstract_syntax +from xopp2oml import writer +import os + +if __name__ == "__main__": + DATADIR = os.path.join(os.path.dirname(__file__), "test_data") + + class DummyOutput: + def write(self, text: str): + pass + + def parse(filename): + asyntax = parser.parseFile(os.path.join(DATADIR, filename)) + writer.writeOML(asyntax, filename, "my_xopp", DummyOutput()) + + # Just see if these files parse without throwing an exception :) + parse("SmallXournalFile.xopp") + parse("TwoHiddenLayers.xopp") + + + print("Tests passed.") \ No newline at end of file diff --git a/tests/data/SmallXournalFile.xopp b/test/test_data/SmallXournalFile.xopp similarity index 100% rename from tests/data/SmallXournalFile.xopp rename to test/test_data/SmallXournalFile.xopp diff --git a/tests/data/TwoHiddenLayers.xopp b/test/test_data/TwoHiddenLayers.xopp similarity index 100% rename from tests/data/TwoHiddenLayers.xopp rename to test/test_data/TwoHiddenLayers.xopp diff --git a/tests/test_xopp2py.py b/tests/test_xopp2py.py deleted file mode 100644 index 6ba45ef..0000000 --- a/tests/test_xopp2py.py +++ /dev/null @@ -1,17 +0,0 @@ -from xopp2py import parser, abstract_syntax -from xopp2py_oml import oml_writer -import os - -DATADIR = os.path.join(os.path.dirname(__file__), "data") - -class DummyOutput: - def write(self, text: str): - pass - -def parse(filename): - asyntax = parser.parseFile(os.path.join(DATADIR, filename)) - oml_writer.writeOML(asyntax, filename, "my_xopp", DummyOutput()) - -# Just see if these files parse without throwing an exception :) -parse("SmallXournalFile.xopp") -parse("TwoHiddenLayers.xopp") \ No newline at end of file