summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--.travis.yml103
-rw-r--r--Makefile17
-rwxr-xr-xbin/build-dist39
-rw-r--r--makefile3
-rw-r--r--reorder.inx16
-rw-r--r--reorder.py39
-rw-r--r--requirements.txt1
-rw-r--r--stub.py30
9 files changed, 181 insertions, 74 deletions
diff --git a/.gitignore b/.gitignore
index 9f526dcb..c0a09e7a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,7 @@
.*.swp
-*.pyc \ No newline at end of file
+*.pyc
+*.spec
+*.zip
+*.tar.gz
+dist/
+build/
diff --git a/.travis.yml b/.travis.yml
index 2a6e9669..4e8ddd04 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,21 +1,94 @@
language: python
-cache: pip
-python:
- - 2.7
- - 3.6
+virtualenv:
+ # We need this for PyGObject.
+ system_site_packages: true
matrix:
- allow_failures:
- - python: 3.6
+ include:
+ # always lint on every commit
+ - python: 2.7
+ env: LINT=true
+ sudo: false
+
+ # only bother to build if we're going to deploy a release
+ - python: 2.7
+ sudo: required
+ env: BUILD=true
+ if: tag is present
+cache: pip
install:
- # - pip install -r requirements.txt
- - pip install flake8 # pytest # add another testing frameworks later
+ - |
+ if [ -n "$BUILD" ]; then
+ # For some bizarre reason, this build has been failing due to the
+ # key for the mongodb repo expiring. Maybe Travis includes the
+ # mongodb repo by default...?
+ sudo rm /etc/apt/sources.list.d/mongodb*.list
+
+ # Need inkscape >=0.92 for inkex.py and friends
+ sudo add-apt-repository --yes ppa:inkscape.dev/stable
+ sudo apt-get update
+ sudo apt-get install inkscape
+
+ # for shapely
+ sudo apt-get install libgeos-dev
+
+ # for wxPython
+ sudo apt-get install glib-networking
+
+ # This is the same as the pypi module PyGObject. We can't just do
+ # "pip install PyGObject" because it depends on a version of
+ # libgirepository1.0-dev that doesn't exist in Trusty.
+ sudo apt-get install python-gi python-gi-cairo libgirepository1.0-dev
+
+ # wxPython doen't publish linux wheels in pypi
+ wget https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-14.04/wxPython-4.0.0b2-cp27-cp27mu-linux_x86_64.whl
+ pip install wxPython-4.0.0b2-cp27-cp27mu-linux_x86_64.whl
+
+ # We can't use the shapely wheel because it includes the geos
+ # library but with a weird file name. Details:
+ # https://github.com/pyinstaller/pyinstaller/blob/61b1c75c2b0469b32d114298a63bf60b8d597e37/PyInstaller/hooks/hook-shapely.py#L34
+ pip install --no-binary shapely -r requirements.txt
+
+ pip install pyinstaller
+ else
+ pip install flake8
+ fi
before_script:
- # stop the build if there are Python syntax errors or undefined names
- - flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
- # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
- - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
+ - "echo LINT: $LINT BUILD: $BUILD"
script:
- - true # pytest --capture=sys # add other tests here
+ - |
+ if [ -n "$LINT" ]; then
+ flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
+ flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
+ elif [ -n "$BUILD" ]; then
+ make dist
+ else
+ true
+ fi
notifications:
- on_success: change
- on_failure: change # `always` will be the setting once code changes slow down
+ on_success: never
+ on_failure: never
+deploy:
+ - provider: releases
+ api_key:
+ secure: pYORXHcn0hPcMIo6+brVE+wYce272H4COp1iXmPvBUz64MAX0Bdm5UX6cTAvzwNd9Hhi2nnWebaoS5AiPelbZgQoZJXsy4whrp7+ZrkQZkhGcqsSqXN6j5k5xdGeFX4k37T7eGkFyajTAdIWB3locHcikKN6N6PnyCPxGD/xuxiD1fJSVKGqBOptBYsqFtMddKy3aT0nmRG/2pMElq2Fcxozo+rR00j2/3npVoh2VTRt2L0S/DrX3zKT4vi2+AQ1MmKEAfF/YxCPybJGPe+wHz4egs0+PIJYb7pSZL8Ja81IS4v5cmmy/r2la815amyRyXwZXbJwBX8h9wPa7dwGStMvJdUidlqaXjKMsWba3QbD6YHOi0+UOFvWeubCDqXKhqxVAvZyCvXCx2WPlBfGWsJDHK/j2pU5Iul5Jz2Zsa3PLYA3UeGWVy081SZNuklNdccKGTokntFnR3pGM/jDN/JK7RkvuPM5qQqn3gludQnrdo/Kw0I77hAEDasgUyO8cweSfyqOXBN0dkbLjfBVRslRRRuC5fV9MIqFvLclaPfMlxsSTdDO4MGJRsF7VvFySBdh0xK7Rm+Vb9jYjCR3FV+b8TRsnY0eD2eFM+rmQt/OYdNIs6emVrTXCcAIzq4JoKZdFDIDDRsiztGSjIBB0+rSXmiUMtCiUo5GS/7zxGs=
+ file:
+ - '*.tar.gz'
+ file_glob: true
+ skip_cleanup: true
+ on:
+ tag: true
+ branch: master
+ condition: "$TRAVIS_TAG =~ ^v[0-9.]+$"
+ - provider: releases
+ api_key:
+ secure: pYORXHcn0hPcMIo6+brVE+wYce272H4COp1iXmPvBUz64MAX0Bdm5UX6cTAvzwNd9Hhi2nnWebaoS5AiPelbZgQoZJXsy4whrp7+ZrkQZkhGcqsSqXN6j5k5xdGeFX4k37T7eGkFyajTAdIWB3locHcikKN6N6PnyCPxGD/xuxiD1fJSVKGqBOptBYsqFtMddKy3aT0nmRG/2pMElq2Fcxozo+rR00j2/3npVoh2VTRt2L0S/DrX3zKT4vi2+AQ1MmKEAfF/YxCPybJGPe+wHz4egs0+PIJYb7pSZL8Ja81IS4v5cmmy/r2la815amyRyXwZXbJwBX8h9wPa7dwGStMvJdUidlqaXjKMsWba3QbD6YHOi0+UOFvWeubCDqXKhqxVAvZyCvXCx2WPlBfGWsJDHK/j2pU5Iul5Jz2Zsa3PLYA3UeGWVy081SZNuklNdccKGTokntFnR3pGM/jDN/JK7RkvuPM5qQqn3gludQnrdo/Kw0I77hAEDasgUyO8cweSfyqOXBN0dkbLjfBVRslRRRuC5fV9MIqFvLclaPfMlxsSTdDO4MGJRsF7VvFySBdh0xK7Rm+Vb9jYjCR3FV+b8TRsnY0eD2eFM+rmQt/OYdNIs6emVrTXCcAIzq4JoKZdFDIDDRsiztGSjIBB0+rSXmiUMtCiUo5GS/7zxGs=
+ file:
+ - '*.tar.gz'
+ file_glob: true
+ skip_cleanup: true
+ prerelease: true
+ name: "development build $TRAVIS_TAG"
+ on:
+ tag: true
+ all_branches: true
+ condition: '! "$TRAVIS_TAG" =~ ^v[0-9.]+$'
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..0803e30a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+EXTENSIONS:=embroider embroider_params embroider_simulate embroider_update
+
+# This gets the branch name or the name of the tag
+VERSION:=$(TRAVIS_TAG)
+OS:=$(shell uname)
+ARCH:=$(shell uname -m)
+
+dist: distclean
+ bin/build-dist $(EXTENSIONS)
+ cp *.inx dist
+ cd dist; tar zcf ../inkstitch-$(VERSION)-$(OS)-$(ARCH).tar.gz *
+
+ # This is only here for debugging the build.
+ tar zcf build.tar.gz build
+
+distclean:
+ rm -rf build dist *.spec *.tar.gz
diff --git a/bin/build-dist b/bin/build-dist
new file mode 100755
index 00000000..f3090178
--- /dev/null
+++ b/bin/build-dist
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+site_packages="$(python -c "import os; print(os.path.dirname(os.__file__) + '/site-packages')")"
+
+# pyinstaller misses these two
+pyinstaller_args+="--add-binary /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so:. "
+pyinstaller_args+="--add-binary /usr/lib/x86_64-linux-gnu/libproxy.so.1:. "
+
+# This one's tricky. ink/stitch doesn't actually _use_ gi.repository.Gtk,
+# but it does use GTK (through wxPython). pyinstaller has some special
+# logic to handle GTK apps that is engaged when you import
+# gi.repository.Gtk that pulls in things like themes, icons, etc. Without
+# that, the Params dialog is unthemed and barely usable. This hidden
+# import option is actually the only reason we had to install python-gi
+# above!
+pyinstaller_args+="--hidden-import gi.repository.Gtk "
+
+# This lets pyinstaller see inkex.py, etc.
+pyinstaller_args+="-p /usr/share/inkscape/extensions "
+
+mkdir -p dist/inkstitch/bin
+for extension in "$@"; do
+ # without the LD_LIBRARY_PATH, it seems that pyinstaller can't find all of
+ # wxpython's shared libraries
+ LD_LIBRARY_PATH="${site_packages}/wx" pyinstaller $pyinstaller_args ${extension}.py;
+
+ # By default, pyinstaller will treat each of ink/stitch's extensions
+ # separately. This means it packages a lot of the same shared libraries (like
+ # wxPython) multiple times. Turns out that we can just copy the contents of
+ # the directories pyinstaller creates into one and it works fine, eliminating
+ # the duplication. This significantly decreases the size of the inkstitch
+ # tarball/zip.
+ cp -a dist/${extension}/* dist/inkstitch/bin
+ rm -rf dist/${extension}
+
+ # Inkscape doesn't let us run native binaries as extensions(?!). Instead we
+ # add this stub script which executes the binaries that pyinstaller creates.
+ cp stub.py dist/${extension}.py
+done
diff --git a/makefile b/makefile
deleted file mode 100644
index 4c306e11..00000000
--- a/makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-embroider.tgz: makefile index.html embroider.py embroider.inx images/draft1.jpg images/draft2.jpg images/shirt.jpg PyEmb.py
- ln -fs embroider .
- tar czf $@ $^
diff --git a/reorder.inx b/reorder.inx
deleted file mode 100644
index 77bf59d7..00000000
--- a/reorder.inx
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
- <_name>Reorder</_name>
- <id>lexelby.embroider.reorder</id>
- <dependency type="executable" location="extensions">reorder.py</dependency>
- <dependency type="executable" location="extensions">inkex.py</dependency>
- <effect>
- <object-type>all</object-type>
- <effects-menu>
- <submenu _name="Embroidery"/>
- </effects-menu>
- </effect>
- <script>
- <command reldir="extensions" interpreter="python">reorder.py</command>
- </script>
-</inkscape-extension>
diff --git a/reorder.py b/reorder.py
deleted file mode 100644
index a30a0a47..00000000
--- a/reorder.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/python
-#
-# Remove selected objects from the document and readd them in the order they
-# were selected.
-
-import sys
-sys.path.append("/usr/share/inkscape/extensions")
-import os
-import inkex
-
-
-class Reorder(inkex.Effect):
-
- def get_selected_in_order(self):
- selected = []
-
- for i in self.options.ids:
- path = '//*[@id="%s"]' % i
- for node in self.document.xpath(path, namespaces=inkex.NSS):
- selected.append(node)
-
- return selected
-
- def effect(self):
- objects = self.get_selected_in_order()
-
- for obj in objects[1:]:
- obj.getparent().remove(obj)
-
- insert_parent = objects[0].getparent()
- insert_pos = insert_parent.index(objects[0])
-
- insert_parent.remove(objects[0])
-
- insert_parent[insert_pos:insert_pos] = objects
-
-if __name__ == '__main__':
- e = Reorder()
- e.affect()
diff --git a/requirements.txt b/requirements.txt
index c7132aa2..c029a9ed 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,3 +4,4 @@ networkx
shapely
lxml
appdirs
+numpy
diff --git a/stub.py b/stub.py
new file mode 100644
index 00000000..9fa33160
--- /dev/null
+++ b/stub.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+
+import sys
+import os
+
+# ink/stitch
+#
+# stub.py: pyinstaller execution stub
+#
+# pyinstaller packages the inkstitch extensions into nice tidy executables.
+# That's great, but Inkscape can't execute a plain binary as an extension(!).
+#
+# This Python script exists only to execute the actual extension binary. It
+# can be copied to, e.g., "embroider_params.py", in which case it will look
+# for a binary at inkstitch/bin/embroider_params.
+
+script_name = os.path.basename(__file__)
+
+if script_name.endswith('.py'):
+ binary_name = script_name[:-3]
+else:
+ # Probably not right, but we can at least try.
+ binary_name = script_name
+
+binary_path = os.path.join("inkstitch", "bin", binary_name)
+
+args = sys.argv[:]
+args[0] = binary_path
+
+os.execv(binary_path, args)