From 8fcb4af6f698ebfc32f9e50f4aa571deb27f1a09 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Tue, 18 Jul 2017 23:19:10 +1000 Subject: [PATCH 01/30] deployment notes (git-side) --- deployment.md | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/deployment.md b/deployment.md index fb7b164..da9d063 100644 --- a/deployment.md +++ b/deployment.md @@ -8,13 +8,15 @@ Method based on the articles: * https://hynek.me/articles/sharing-your-labor-of-love-pypi-quick-and-dirty/ -## Pre-requisites +## PyPi deployment + +### Pre-requisites ``` pip install -U "pip>=1.4" "setuptools>=0.9" "wheel>=0.21" twine ``` -## PyPi rc +### PyPi rc `cat ~/.pypirc` @@ -38,14 +40,14 @@ password=secret `chmod 600 ~/.pypirc` -## Building +### Building ``` rm -rf build/ python setup.py sdist bdist_wheel ``` -### Test Build (sdist) +#### Test Build (sdist) **Python 2.x** @@ -75,14 +77,14 @@ $WORKON_HOME/35-test/bin/python >>> pygcode.Line('g1 x2 y3 m3 s1000 f100').block.gcodes # or whatever ``` -### Test Build (wheel) +#### Test Build (wheel) similar to above, but the `pip` call references `pygcode-0.1.0-py2.py3-none-any.whl` instead make sure to `rmvirtualenv` to ensure `pygcode` is uninstalled from virtual environment -## Upload to PyPi Test server +### Upload to PyPi Test server `twine upload -r test dist/pygcode-0.1.0*` @@ -91,7 +93,7 @@ Then another round of testing, where `pip` call is: `$WORKON_HOME//bin/pip install -i https://testpypi.python.org/pypi pygcode` -## Upload to PyPy server +### Upload to PyPy server all good!? sweet :+1: time to upload to 'production' @@ -100,3 +102,14 @@ all good!? sweet :+1: time to upload to 'production' and final tests with simply: `$WORKON_HOME//bin/pip install pygcode` + +## Deployment in Git + +after merging to `master` + +``` +git tag 0.1.0 -m "Initial version" +git push --tags origin master +``` + +tadaaaaaa! From fafcd6eaba8f1a18e834330e95820f51a3bbfcdd Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Wed, 19 Jul 2017 13:53:53 +1000 Subject: [PATCH 02/30] fixed installation link --- README.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index fd5faa3..2aef061 100644 --- a/README.rst +++ b/README.rst @@ -10,14 +10,16 @@ for python. Installation ============ -Using `PyPi `__: +Install using ``pip`` ``pip install pygcode`` +or `download directly from PyPi `__ + + Usage ===== -Just brainstorming here... Writing GCode ------------- From 7c96a2974d02867b60564d2fd017fe9d659e1312 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Wed, 19 Jul 2017 13:54:08 +1000 Subject: [PATCH 03/30] fixed path relativity (after moving to 'src') --- scripts/pygcode-normalize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pygcode-normalize.py b/scripts/pygcode-normalize.py index adecfd4..34b7e1d 100755 --- a/scripts/pygcode-normalize.py +++ b/scripts/pygcode-normalize.py @@ -29,7 +29,7 @@ for pygcode_lib_type in ('installed_lib', 'relative_lib'): import sys, os, inspect # Add pygcode (relative to this test-path) to the system path _this_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) - sys.path.insert(0, os.path.join(_this_path, '..')) + sys.path.insert(0, os.path.join(_this_path, '..', 'src')) if pygcode_lib_type == 'installed_lib': continue # import was attempted before sys.path addition. retry import raise # otherwise the raised ImportError is a genuine problem From 0a129131ff9539442aaa7cfc30fb98659a3650ec Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Fri, 21 Jul 2017 18:29:18 +1000 Subject: [PATCH 04/30] renamed to shorten command --- scripts/{pygcode-normalize.py => pygcode-norm.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{pygcode-normalize.py => pygcode-norm.py} (100%) diff --git a/scripts/pygcode-normalize.py b/scripts/pygcode-norm.py similarity index 100% rename from scripts/pygcode-normalize.py rename to scripts/pygcode-norm.py From eba1f7214f76f0180cb5f441582caa6772f4297e Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Fri, 21 Jul 2017 21:03:58 +1000 Subject: [PATCH 05/30] move readme to deployment folder --- deployment.md => deployment/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename deployment.md => deployment/README.md (100%) diff --git a/deployment.md b/deployment/README.md similarity index 100% rename from deployment.md rename to deployment/README.md From 5be385e2677705cbbf8bedb2a080e2befe80d191 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Fri, 21 Jul 2017 21:04:22 +1000 Subject: [PATCH 06/30] removed py extension from normalize script --- scripts/{pygcode-norm.py => pygcode-norm} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{pygcode-norm.py => pygcode-norm} (100%) diff --git a/scripts/pygcode-norm.py b/scripts/pygcode-norm similarity index 100% rename from scripts/pygcode-norm.py rename to scripts/pygcode-norm From 1d288e940346c8b4a9a2137846b5374788e224a6 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sat, 22 Jul 2017 00:27:59 +1000 Subject: [PATCH 07/30] deployment more mature --- deployment/deploy.sh | 212 ++++++++++++++++++++++++++++++ src/pygcode.egg-info/PKG-INFO | 8 +- src/pygcode.egg-info/SOURCES.txt | 1 + src/pygcode.egg-info/requires.txt | 1 + src/pygcode/__init__.py | 2 +- tests/test_file.py | 24 ---- tests/testutils.py | 12 +- 7 files changed, 229 insertions(+), 31 deletions(-) create mode 100755 deployment/deploy.sh delete mode 100644 tests/test_file.py diff --git a/deployment/deploy.sh b/deployment/deploy.sh new file mode 100755 index 0000000..665630e --- /dev/null +++ b/deployment/deploy.sh @@ -0,0 +1,212 @@ +#!/usr/bin/env bash +source $(which virtualenvwrapper.sh) + +function pyver() { + # write python version to stdout + $1 -c 'import sys; print("{}.{}.{}".format(*sys.version_info))' +} + +function lib_ver() { + # Get library vesion number + pushd ../src > /dev/null + python -c 'import pygcode; print(pygcode.__version__)' + popd > /dev/null +} + +# ============ Local Parameters +LIB_NAME=pygcode +LIB_VER=$(lib_ver) + +# ============ Help Text +function show_help() { + [ "$@" ] && echo "$@" +cat << EOF +Usage: ./${0##*/} {build|test|and so on ...} + +This script is to maintain a consistent method of deployment and testing. + +Deployment target: ${LIB_NAME} ${LIB_VER} + +Arguments: + Setup: + setup: Installs packages & sets up environment (requires sudo) + + Compiling: + build: Execute setup to build packages (populates ../dist/) + creates both 'sdist' and 'wheel' distrobutions. + + Virtual Environments: + rmenv py# Remove virtual environment + remkenv py# Remove, then create re-create virtual environment + + Deploy: + deploy test Upload to PyPi test server + deploy prod Upload to PyPi (official) + + Install: + install sdist py# Install from local sdist + install wheel py# Install from local wheel + install pypitest py# Install from PyPi test server + install pypi py# Install from PyPi (official) + + Testing: + test dev py# Run tests on local dev in a virtual env + test installed py# Run tests on installed library in virtual env + + Help: + -h | --help display this help message + + py#: when referenced above means + 'py2' for Python $(pyver python2) + 'py3' for Python $(pyver python3) +EOF +} + +# ============ Commands +function setup() { + # Install pre-requisite tooling + sudo pip install -U "pip>=1.4" "setuptools>=0.9" "wheel>=0.21" twine +} + +function build() { + # Run setup.py to build sdist and wheel distrobutions + pushd .. + rm -rf build/ + python setup.py sdist bdist_wheel + popd +} + +function rmenv() { + # Remove virtual environment + set_venv_variables $1 + rmvirtualenv ${env_name} +} + +function remkenv() { + # Remove virtual environment, then re-create it from scratch + set_venv_variables $1 + rmvirtualenv ${env_name} + mkvirtualenv --python=${python_bin} ${env_name} +} + +function deploy() { + # Deploy compiled distributions to the test|prod server + _deployment_env=$1 + pushd .. + twine upload -r ${_deployment_env} dist/${LIB_NAME}-${LIB_VER}* + popd +} + +function install() { + # Install library from a variety of sources + _install_type=$1 + _env_key=$2 + + set_venv_variables ${_env_key} + workon ${env_name} + + case "${_install_type}" in + sdist) + # Install from locally compiled 'sdist' file + ${env_pip_bin} install ../dist/${LIB_NAME}-${LIB_VER}.tar.gz + ;; + wheel) + # Install from locally compiled 'wheel' file + ${env_pip_bin} install ../dist/${LIB_NAME}-${LIB_VER}-py2.py3-none-any.whl + ;; + pypitest) + # Install from PyPi test server + ${env_pip_bin} install -i https://testpypi.python.org/pypi ${LIB_NAME} + ;; + pypi) + # Install from official PyPi server + ${env_pip_bin} install ${LIB_NAME} + ;; + *) + echo invalid install type: \"${_install_type}\" >&2 + exit 1 + ;; + esac + + deactivate +} + +function test() { + # Run tests + + _test_scope=$1 + _env_key=$2 + + set_venv_variables ${_env_key} + + case "${_test_scope}" in + dev) + export PYGCODE_TESTSCOPE=local + ;; + installed) + export PYGCODE_TESTSCOPE=installed + ;; + *) + echo invalid test scope: \"${_test_scope}\" >&2 + exit 1 + ;; + esac + + pushd ../tests + workon ${env_name} + ${env_python_bin} -m unittest discover -s . -p 'test_*.py' --verbose + deactivate + popd +} + +# ============ Utilities +function set_venv_variables() { + # on successful exit, environment variables are set: + # env_name = virtual environment's name + # env_pip_bin = environment's pip binary + # env_python_bin = environment's python binary + # python_bin = python binary in host environment + _env_key=$1 + + env_name=${LIB_NAME}_${_env_key} + env_pip_bin=${WORKON_HOME}/${env_name}/bin/pip + env_python_bin=${WORKON_HOME}/${env_name}/bin/python + case "${_env_key}" in + py2) + python_bin=$(which python2) + ;; + py3) + python_bin=$(which python3) + ;; + *) + echo invalid environment key: \"${_env_key}\" >&2 + exit 1 + ;; + esac +} + +# ============ Option parsing +case "$1" in + # Show help on request + -h|--help) + show_help + exit 0 + ;; + + # Valid Commands + setup) setup ;; + build) build ;; + rmenv) rmenv $2 ;; + remkenv) remkenv $2 ;; + deploy) deploy $2 ;; + install) install $2 $3 ;; + test) test $2 $3 ;; + + # otherwise... show help + *) + show_help >&2 + exit 1 + ;; +esac + +echo ./${0##*/} completed successfully diff --git a/src/pygcode.egg-info/PKG-INFO b/src/pygcode.egg-info/PKG-INFO index ae6dded..c5d6f57 100644 --- a/src/pygcode.egg-info/PKG-INFO +++ b/src/pygcode.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pygcode -Version: 0.1.0 +Version: 0.1.1.dev0 Summary: Basic g-code parser, interpreter, and encoder library. Home-page: https://github.com/fragmuffin/pygcode Author: Peter Boin @@ -18,14 +18,16 @@ Description: ======= Installation ============ - Using `PyPi `__: + Install using ``pip`` ``pip install pygcode`` + or `download directly from PyPi `__ + + Usage ===== - Just brainstorming here... Writing GCode ------------- diff --git a/src/pygcode.egg-info/SOURCES.txt b/src/pygcode.egg-info/SOURCES.txt index 38deb60..548f5a9 100644 --- a/src/pygcode.egg-info/SOURCES.txt +++ b/src/pygcode.egg-info/SOURCES.txt @@ -1,6 +1,7 @@ README.rst setup.cfg setup.py +scripts/pygcode-norm src/pygcode/__init__.py src/pygcode/block.py src/pygcode/comment.py diff --git a/src/pygcode.egg-info/requires.txt b/src/pygcode.egg-info/requires.txt index baa8aa3..e0978f0 100644 --- a/src/pygcode.egg-info/requires.txt +++ b/src/pygcode.egg-info/requires.txt @@ -1,2 +1,3 @@ +argparse euclid3 six diff --git a/src/pygcode/__init__.py b/src/pygcode/__init__.py index 9737e03..8bf0a75 100644 --- a/src/pygcode/__init__.py +++ b/src/pygcode/__init__.py @@ -6,7 +6,7 @@ # 1.x - Development Status :: 5 - Production/Stable # .y - developments on that version (pre-release) # *.dev* - development release (intended purely to test deployment) -__version__ = "0.1.0" +__version__ = "0.1.1.dev0" __title__ = "pygcode" __description__ = "Basic g-code parser, interpreter, and encoder library." diff --git a/tests/test_file.py b/tests/test_file.py deleted file mode 100644 index e678b74..0000000 --- a/tests/test_file.py +++ /dev/null @@ -1,24 +0,0 @@ -import sys -import os -import inspect - -import unittest - -# Add relative pygcode to path -from testutils import add_pygcode_to_path, str_lines -add_pygcode_to_path() - -# Units under test -from pygcode.file import GCodeFile, GCodeParser - -class GCodeParserTest(unittest.TestCase): - FILENAME = 'test-files/vertical-slot.ngc' - - def test_parser(self): - parser = GCodeParser(self.FILENAME) - # count lines - line_count = 0 - for line in parser.iterlines(): - line_count += 1 - self.assertEqual(line_count, 26) - parser.close() diff --git a/tests/testutils.py b/tests/testutils.py index dcc494c..5046a63 100644 --- a/tests/testutils.py +++ b/tests/testutils.py @@ -5,14 +5,20 @@ import inspect import re + # Units Under Test _pygcode_in_path = False def add_pygcode_to_path(): global _pygcode_in_path if not _pygcode_in_path: - # Add pygcode (relative to this test-path) to the system path - _this_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) - sys.path.insert(0, os.path.join(_this_path, '..')) + if os.environ.get('PYGCODE_TESTSCOPE', 'local') == 'installed': + # Run tests on the `pip install` installed libray + pass # nothing to be done + else: + # Run tests explicitly on files in ../src (ignore any installed libs) + # Add pygcode (relative to this test-path) to the system path + _this_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + sys.path.insert(0, os.path.join(_this_path, '..', 'src')) _pygcode_in_path = True From 6f710f81abf473a910cd35d0c70ee95bf181dedf Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sat, 22 Jul 2017 00:28:52 +1000 Subject: [PATCH 08/30] pygcode-norm available in commandline upon installation --- setup.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.py b/setup.py index 90777a5..7c04491 100644 --- a/setup.py +++ b/setup.py @@ -26,9 +26,13 @@ CLASSIFIERS = [ "Topic :: Scientific/Engineering", ] INSTALL_REQUIRES = [ + 'argparse', # Python command-line parsing library 'euclid3', # 2D and 3D vector, matrix, quaternion and geometry module. 'six', # Python 2 and 3 compatibility utilities ] +SCRIPTS = [ + 'scripts/pygcode-norm', +] ################################################################### @@ -78,4 +82,5 @@ if __name__ == "__main__": zip_safe=False, classifiers=CLASSIFIERS, install_requires=INSTALL_REQUIRES, + scripts=SCRIPTS, ) From 9598d2bd153368fc2cf662a7c8f7321a1ec87968 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sat, 22 Jul 2017 00:47:49 +1000 Subject: [PATCH 09/30] changed to reflect new deploy.sh script --- deployment/README.md | 130 ++++++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 52 deletions(-) diff --git a/deployment/README.md b/deployment/README.md index da9d063..7c0e248 100644 --- a/deployment/README.md +++ b/deployment/README.md @@ -1,6 +1,11 @@ # Notes on deployment -How I deployed this package (mainly just notes for myself) +How I deploy this package. + +For anyone reading, this readme and all files in this folder are mainly just +notes for myself; they have little to do with pygcode itself. +However, if you're interested in deploying your own PyPi package, then hopefully +this can help. Method based on the articles: @@ -8,15 +13,13 @@ Method based on the articles: * https://hynek.me/articles/sharing-your-labor-of-love-pypi-quick-and-dirty/ -## PyPi deployment +# PyPi deployment -### Pre-requisites +## Install Required Tools -``` -pip install -U "pip>=1.4" "setuptools>=0.9" "wheel>=0.21" twine -``` +`./deploy.sh setup` -### PyPi rc +## PyPi rc `cat ~/.pypirc` @@ -40,76 +43,99 @@ password=secret `chmod 600 ~/.pypirc` -### Building +## Build and Test `sdist` and `wheel` +**Build** ``` -rm -rf build/ -python setup.py sdist bdist_wheel +./deploy.sh build ``` -#### Test Build (sdist) - -**Python 2.x** - +**Test `sdist`** ``` -rmvirtualenv 27-test -mkvirtualenv 27-test +# Python 2.x +./deploy.sh remkenv py2 +./deploy.sh install sdist py2 +./deploy.sh test installed py2 -$WORKON_HOME/27-test/bin/pip install dist/pygcode-0.1.0.tar.gz - -$WORKON_HOME/27-test/bin/python - ->>> import pygcode ->>> pygcode.Line('g1 x2 y3 m3 s1000 f100').block.gcodes # or whatever +# Python 3.x +./deploy.sh remkenv py3 +./deploy.sh install sdist py3 +./deploy.sh test installed py3 ``` -**Python 3.x** - +**Test `wheel`** ``` -rmvirtualenv 35-test -mkvirtualenv -p $(which python3) 35-test +# Python 2.x +./deploy.sh remkenv py2 +./deploy.sh install wheel py2 +./deploy.sh test installed py2 -$WORKON_HOME/35-test/bin/pip install dist/pygcode-0.1.0.tar.gz - -$WORKON_HOME/35-test/bin/python - ->>> import pygcode ->>> pygcode.Line('g1 x2 y3 m3 s1000 f100').block.gcodes # or whatever +# Python 3.x +./deploy.sh remkenv py3 +./deploy.sh install wheel py3 +./deploy.sh test installed py3 ``` -#### Test Build (wheel) -similar to above, but the `pip` call references `pygcode-0.1.0-py2.py3-none-any.whl` instead +## Upload to PyPi Test server -make sure to `rmvirtualenv` to ensure `pygcode` is uninstalled from virtual environment +``` +./deploy.sh test +``` + +**Test** +``` +# Python 2.x +./deploy.sh remkenv py2 +./deploy.sh install pypitest py2 +./deploy.sh test installed py2 + +# Python 3.x +./deploy.sh remkenv py3 +./deploy.sh install pypitest py3 +./deploy.sh test installed py3 +``` + +have a look at: +https://testpypi.python.org/pypi/pygcode +to make sure it's sane -### Upload to PyPi Test server - -`twine upload -r test dist/pygcode-0.1.0*` - -Then another round of testing, where `pip` call is: - -`$WORKON_HOME//bin/pip install -i https://testpypi.python.org/pypi pygcode` - - -### Upload to PyPy server +## Upload to PyPy server all good!? sweet :+1: time to upload to 'production' -`twine upload -r prod dist/pygcode-0.1.0*` +``` +./deploy.sh prod +``` -and final tests with simply: +**Test** +``` +# Python 2.x +./deploy.sh remkenv py2 +./deploy.sh install pypi py2 +./deploy.sh test installed py2 -`$WORKON_HOME//bin/pip install pygcode` +# Python 3.x +./deploy.sh remkenv py3 +./deploy.sh install pypi py3 +./deploy.sh test installed py3 +``` -## Deployment in Git +have a look at: +https://pypi.python.org/pypi/pygcode +to make sure it's sane -after merging to `master` + +# Deployment in Git + +merge deployed branch to `master` ``` -git tag 0.1.0 -m "Initial version" +git tag ${version} -m "" git push --tags origin master ``` -tadaaaaaa! +have a look at the [releases page](https://github.com/fragmuffin/pygcode/releases) and it should be there. + +tadaaaaaa!... go to sleep; it's probably late From 2709bb3612f5e1bedd38ee7a555a2b3af6cde030 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sat, 22 Jul 2017 00:55:47 +1000 Subject: [PATCH 10/30] avoid test command conflict --- deployment/deploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deployment/deploy.sh b/deployment/deploy.sh index 665630e..5200927 100755 --- a/deployment/deploy.sh +++ b/deployment/deploy.sh @@ -131,7 +131,7 @@ function install() { deactivate } -function test() { +function run_test() { # Run tests _test_scope=$1 @@ -200,7 +200,7 @@ case "$1" in remkenv) remkenv $2 ;; deploy) deploy $2 ;; install) install $2 $3 ;; - test) test $2 $3 ;; + test) run_test $2 $3 ;; # otherwise... show help *) From e513f55e53ca1fb983bcc5b2103a6fc366c8e8ef Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sat, 22 Jul 2017 01:07:18 +1000 Subject: [PATCH 11/30] grammatical typo --- src/pygcode/gcodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygcode/gcodes.py b/src/pygcode/gcodes.py index 4707aec..00465c4 100644 --- a/src/pygcode/gcodes.py +++ b/src/pygcode/gcodes.py @@ -96,7 +96,7 @@ MODAL_GROUP_MAP = { # Traditionally Non-grouped: # Although these GCodes set the machine's mode, there are no other GCodes to - # group with them. So although they're modal, they doesn't have a defined + # group with them. So although they're modal, they don't have a defined # modal group. # However, having a modal group assists with: # - validating gcode blocks for conflicting commands From 0ffd0c7bec655fac3863c5cc27ce4056c4381d36 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sat, 22 Jul 2017 01:10:09 +1000 Subject: [PATCH 12/30] removed outdated comment --- src/pygcode/machine.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/pygcode/machine.py b/src/pygcode/machine.py index 4f0e42b..7cf412d 100644 --- a/src/pygcode/machine.py +++ b/src/pygcode/machine.py @@ -221,15 +221,6 @@ class State(object): class Mode(object): """Machine's mode""" - # State is very forgiving: - # Anything possible in a machine's state may be changed & fetched. - # For example: x, y, z, a, b, c may all be set & requested. - # However, the machine for which this state is stored probably doesn't - # have all possible 6 axes. - # It is also possible to set an axis to an impossibly large distance. - # It is the responsibility of the Machine using this class to be - # discerning in these respects. - # Default Mode # for a Grbl controller this can be obtained with the `$G` command, eg: # > $G @@ -351,6 +342,8 @@ class Machine(object): if coord_sys_mode: self.state.cur_coord_sys = coord_sys_mode.coord_system_id + # TODO: convert coord systems between inches/mm, G20/G21 respectively + def modal_gcode(self, modal_params): if not modal_params: From dfc7e3e6b0f762e4b68cfc896e47f75c92d1b09e Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sat, 22 Jul 2017 01:14:58 +1000 Subject: [PATCH 13/30] added deploy.sh help --- deployment/README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/deployment/README.md b/deployment/README.md index 7c0e248..d6158a4 100644 --- a/deployment/README.md +++ b/deployment/README.md @@ -13,6 +13,50 @@ Method based on the articles: * https://hynek.me/articles/sharing-your-labor-of-love-pypi-quick-and-dirty/ +Deployment also heavily uses the `./deploy.sh` script in this folder. +At this time, running `./deploy.sh --help` displays: + +``` +Usage: ./deploy.sh {build|test|and so on ...} + +This script is to maintain a consistent method of deployment and testing. + +Deployment target: pygcode 0.1.1.dev0 + +Arguments: + Setup: + setup: Installs packages & sets up environment (requires sudo) + + Compiling: + build: Execute setup to build packages (populates ../dist/) + creates both 'sdist' and 'wheel' distrobutions. + + Virtual Environments: + rmenv py# Remove virtual environment + remkenv py# Remove, then create re-create virtual environment + + Deploy: + deploy test Upload to PyPi test server + deploy prod Upload to PyPi (official) + + Install: + install sdist py# Install from local sdist + install wheel py# Install from local wheel + install pypitest py# Install from PyPi test server + install pypi py# Install from PyPi (official) + + Testing: + test dev py# Run tests on local dev in a virtual env + test installed py# Run tests on installed library in virtual env + + Help: + -h | --help display this help message + + py#: when referenced above means + 'py2' for Python 2.7.12 + 'py3' for Python 3.5.2 +``` + # PyPi deployment ## Install Required Tools From b4b71daae895a1644043898dbd9a8de8a1b7c521 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Tue, 25 Jul 2017 01:47:41 +1000 Subject: [PATCH 14/30] changed name to GCodeCannedCycleReturn**Prev**Level --- src/pygcode/__init__.py | 6 +++--- src/pygcode/transform.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pygcode/__init__.py b/src/pygcode/__init__.py index 8bf0a75..c5ce90a 100644 --- a/src/pygcode/__init__.py +++ b/src/pygcode/__init__.py @@ -53,7 +53,7 @@ __all__ = [ 'GCodeCancelCannedCycle', 'GCodeCancelToolLengthOffset', 'GCodeCannedCycle', - 'GCodeCannedCycleReturnLevel', + 'GCodeCannedCycleReturnPrevLevel', 'GCodeCannedCycleReturnToR', 'GCodeCannedReturnMode', 'GCodeCoolant', @@ -199,7 +199,7 @@ from .gcodes import ( # G83 - GCodeDrillingCyclePeck: G83: Drilling Cycle, Peck # G76 - GCodeThreadingCycle: G76: Threading Cycle # - GCodeCannedReturnMode: - # G98 - GCodeCannedCycleReturnLevel: G98: Canned Cycle Return to the level set prior to cycle start + # G98 - GCodeCannedCycleReturnPrevLevel: G98: Canned Cycle Return to the level set prior to cycle start # G99 - GCodeCannedCycleReturnToR: G99: Canned Cycle Return to the level set by R # - GCodeCoolant: # M08 - GCodeCoolantFloodOn: M8: turn flood coolant on @@ -330,7 +330,7 @@ from .gcodes import ( GCodeCancelCannedCycle, GCodeCancelToolLengthOffset, GCodeCannedCycle, - GCodeCannedCycleReturnLevel, + GCodeCannedCycleReturnPrevLevel, GCodeCannedCycleReturnToR, GCodeCannedReturnMode, GCodeCoolant, diff --git a/src/pygcode/transform.py b/src/pygcode/transform.py index 10a415b..da8a3c0 100644 --- a/src/pygcode/transform.py +++ b/src/pygcode/transform.py @@ -7,7 +7,7 @@ from .gcodes import GCodeAbsoluteDistanceMode, GCodeIncrementalDistanceMode from .gcodes import GCodeAbsoluteArcDistanceMode, GCodeIncrementalArcDistanceMode from .gcodes import GCodeCannedCycle from .gcodes import GCodeDrillingCyclePeck, GCodeDrillingCycleDwell, GCodeDrillingCycleChipBreaking -from .gcodes import GCodeCannedReturnMode, GCodeCannedCycleReturnLevel, GCodeCannedCycleReturnToR +from .gcodes import GCodeCannedReturnMode, GCodeCannedCycleReturnPrevLevel, GCodeCannedCycleReturnToR from .gcodes import _gcodes_abs2rel from .machine import Position @@ -381,7 +381,7 @@ def linearize_arc(arc_gcode, start_pos, plane=None, method_class=None, DEFAULT_SCC_PLANE = GCodeSelectXYPlane DEFAULT_SCC_DISTMODE = GCodeAbsoluteDistanceMode -DEFAULT_SCC_RETRACTMODE = GCodeCannedCycleReturnLevel +DEFAULT_SCC_RETRACTMODE = GCodeCannedCycleReturnPrevLevel def simplify_canned_cycle(canned_gcode, start_pos, plane=None, dist_mode=None, retract_mode=None, From aef2728b0da351a8c7f059652f78a318a65311c4 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Tue, 25 Jul 2017 01:52:55 +1000 Subject: [PATCH 15/30] updated readme fixed canned drilling cycle machine processing bugs improved tests for linear movement --- README.rst | 10 +-- src/pygcode/gcodes.py | 34 ++++++-- tests/test_machine.py | 180 +++++++++++++++++++++++++++++++++--------- 3 files changed, 176 insertions(+), 48 deletions(-) diff --git a/README.rst b/README.rst index 2aef061..a649a90 100644 --- a/README.rst +++ b/README.rst @@ -111,15 +111,13 @@ To elaborate, here are some line examples G01 X1 Y2 F100 S1000 ; blah >>> print(line.block) G01 X1 Y2 F100 S1000 + >>> sorted(line.block.gcodes) + [, + , + ] >>> print(line.comment) ; blah - >>> line = Line('G0 x1 y2 (foo) f100 (bar) s1000') - >>> print(line) - G00 X1 Y2 F100 S1000 (foo. bar) - >>> print(line.comment) - (foo. bar) - Interpreting what a line of gcode does depends on the machine it's running on, and also that machine's state (or 'mode') diff --git a/src/pygcode/gcodes.py b/src/pygcode/gcodes.py index 00465c4..83f3735 100644 --- a/src/pygcode/gcodes.py +++ b/src/pygcode/gcodes.py @@ -218,15 +218,29 @@ class GCode(object): return copy(self.word_key) raise AssertionError("class %r has no default word" % self.__class__) - # Comparisons + # Equality + def __eq__(self, other): + return ( + (self.word == other.word) and + (self.params == other.params) + ) + + def __ne__(self, other): + return not self.__eq__(other) + + # Sort by execution order def __lt__(self, other): - """Sort by execution order""" return self.exec_order < other.exec_order + def __le__(self, other): + return self.exec_order <= other.exec_order + def __gt__(self, other): - """Sort by execution order""" return self.exec_order > other.exec_order + def __ge__(self, other): + return self.exec_order >= other.exec_order + # Parameters def add_parameter(self, word): """ @@ -483,10 +497,18 @@ class GCodeCannedCycle(GCode): if isinstance(machine.mode.canned_cycles_return, GCodeCannedCycleReturnToR): # canned return is to this.R, not this.Z (plane dependent) moveto_coords.update({ - machine.mode.plane_selection.normal_axis: this.R, + machine.mode.plane_selection.normal_axis: self.R, }) + else: # default: GCodeCannedCycleReturnPrevLevel + # Remove this.Z (plane dependent) value (ie: no machine movement on this axis) + moveto_coords.pop(machine.mode.plane_selection.normal_axis, None) - machine.move_to(**moveto_coords) + # Process action 'L' times + loop_count = self.L + if (loop_count is None) or (loop_count <= 0): + loop_count = 1 + for i in range(loop_count): + machine.move_to(**moveto_coords) class GCodeDrillingCycle(GCodeCannedCycle): @@ -929,7 +951,7 @@ class GCodeCannedReturnMode(GCode): exec_order = 220 -class GCodeCannedCycleReturnLevel(GCodeCannedReturnMode): +class GCodeCannedCycleReturnPrevLevel(GCodeCannedReturnMode): """G98: Canned Cycle Return to the level set prior to cycle start""" # "retract to the position that axis was in just before this series of one or more contiguous canned cycles was started" word_key = Word('G', 98) diff --git a/tests/test_machine.py b/tests/test_machine.py index 5f52aa6..17ccf07 100644 --- a/tests/test_machine.py +++ b/tests/test_machine.py @@ -8,6 +8,11 @@ add_pygcode_to_path() from pygcode.machine import Position, Machine from pygcode.line import Line from pygcode.exceptions import MachineInvalidAxis +from pygcode.gcodes import ( + GCodeAbsoluteDistanceMode, GCodeIncrementalDistanceMode, + GCodeAbsoluteArcDistanceMode, GCodeIncrementalArcDistanceMode, + GCodeCannedCycleReturnPrevLevel, GCodeCannedCycleReturnToR, +) class PositionTests(unittest.TestCase): @@ -81,43 +86,146 @@ class PositionTests(unittest.TestCase): self.assertEqual(p / 2, Position(axes='XYZ', X=1, Y=5)) - class MachineGCodeProcessingTests(unittest.TestCase): - def test_linear_movement(self): - m = Machine() - test_str = '''; move in a 10mm square - F100 M3 S1000 ; 0 - g1 x0 y10 ; 1 - g1 x10 y10 ; 2 - g1 x10 y0 ; 3 - g1 x0 y0 ; 4 - ''' - expected_pos = { - '0': m.Position(), - '1': m.Position(X=0, Y=10), - '2': m.Position(X=10, Y=10), - '3': m.Position(X=10, Y=0), - '4': m.Position(X=0, Y=0), - } - #print("\n%r\n%r" % (m.mode, m.state)) - for line_text in str_lines(test_str): - line = Line(line_text) + def assert_processed_lines(self, line_data, machine): + """ + Process lines & assert machine's position + :param line_data: list of tuples [('g1 x2', {'X':2}), ... ] + """ + for (i, (line_str, expected_pos)) in enumerate(line_data): + line = Line(line_str) if line.block: - #print("\n%s" % line.block) - m.process_block(line.block) - # Assert possition change correct - comment = line.comment.text - if comment in expected_pos: - self.assertEqual(m.pos, expected_pos[comment]) - #print("%r\n%r\npos=%r" % (m.mode, m.state, m.pos)) + machine.process_block(line.block) + # Assert possition change correct + if expected_pos is not None: + p1 = machine.pos + p2 = machine.Position(**expected_pos) + self.assertEqual(p1, p2, "index:%i '%s': %r != %r" % (i, line_str, p1, p2)) + # Rapid Movement + def test_rapid_abs(self): + m = Machine() + m.process_gcodes(GCodeAbsoluteDistanceMode()) + line_data = [ + ('', {}), # start @ 0,0,0 + ('g0 x0 y10', {'X':0, 'Y':10}), + (' x10 y10', {'X':10, 'Y':10}), + (' x10 y0', {'X':10, 'Y':0}), + (' x0 y0', {'X':0, 'Y':0}), + ] + self.assert_processed_lines(line_data, m) -#m = Machine() -# -#file = GCodeParser('part1.gcode') -#for line in file.iterlines(): -# for (i, gcode) in enumerate(line.block.gcode): -# if isinstance(gcode, GCodeArcMove): -# arc = gcode -# line_params = arc.line_segments(precision=0.0005) -# for + def test_rapid_inc(self): + m = Machine() + m.process_gcodes(GCodeIncrementalDistanceMode()) + line_data = [ + ('', {}), # start @ 0,0,0 + ('g0 y10', {'X':0, 'Y':10}), + (' x10', {'X':10, 'Y':10}), + (' y-10', {'X':10, 'Y':0}), + (' x-10', {'X':0, 'Y':0}), + ] + self.assert_processed_lines(line_data, m) + + # Linearly Interpolated Movement + def test_linear_abs(self): + m = Machine() + m.process_gcodes(GCodeAbsoluteDistanceMode()) + line_data = [ + ('g1 x0 y10', {'X':0, 'Y':10}), + (' x10 y10', {'X':10, 'Y':10}), + (' x10 y0', {'X':10, 'Y':0}), + (' x0 y0', {'X':0, 'Y':0}), + ] + self.assert_processed_lines(line_data, m) + + def test_linear_inc(self): + m = Machine() + m.process_gcodes(GCodeIncrementalDistanceMode()) + line_data = [ + ('g1 y10', {'X':0, 'Y':10}), + (' x10', {'X':10, 'Y':10}), + (' y-10', {'X':10, 'Y':0}), + (' x-10', {'X':0, 'Y':0}), + ] + self.assert_processed_lines(line_data, m) + + # Arc Movement + def test_arc_abs(self): + m = Machine() + m.process_gcodes( + GCodeAbsoluteDistanceMode(), + GCodeIncrementalArcDistanceMode(), + ) + line_data = [ + # Clockwise circle in 4 segments + ('g2 x0 y10 i5 j5', {'X':0, 'Y':10}), + (' x10 y10 i5 j-5', {'X':10, 'Y':10}), + (' x10 y0 i-5 j-5', {'X':10, 'Y':0}), + (' x0 y0 i-5 j5', {'X':0, 'Y':0}), + # Counter-clockwise circle in 4 segments + ('g3 x10 y0 i5 j5', {'X':10, 'Y':0}), + (' x10 y10 i-5 j5', {'X':10, 'Y':10}), + (' x0 y10 i-5 j-5', {'X':0, 'Y':10}), + (' x0 y0 i5 j-5', {'X':0, 'Y':0}), + ] + self.assert_processed_lines(line_data, m) + + def test_arc_inc(self): + m = Machine() + m.process_gcodes( + GCodeIncrementalDistanceMode(), + GCodeIncrementalArcDistanceMode(), + ) + line_data = [ + # Clockwise circle in 4 segments + ('g2 y10 i5 j5', {'X':0, 'Y':10}), + (' x10 i5 j-5', {'X':10, 'Y':10}), + (' y-10 i-5 j-5', {'X':10, 'Y':0}), + (' x-10 i-5 j5', {'X':0, 'Y':0}), + # Counter-clockwise circle in 4 segments + ('g3 x10 i5 j5', {'X':10, 'Y':0}), + (' y10 i-5 j5', {'X':10, 'Y':10}), + (' x-10 i-5 j-5', {'X':0, 'Y':10}), + (' y-10 i5 j-5', {'X':0, 'Y':0}), + ] + self.assert_processed_lines(line_data, m) + + # Canned Drilling Cycles + def test_canned_return2oldz(self): + m = Machine() + m.process_gcodes( + GCodeAbsoluteDistanceMode(), + GCodeCannedCycleReturnPrevLevel(), + ) + line_data = [ + ('g0 z5', {'Z':5}), + ('g81 x10 y20 z-2 r1', {'X':10, 'Y':20, 'Z':5}), + ] + self.assert_processed_lines(line_data, m) + + def test_canned_return2r(self): + m = Machine() + m.process_gcodes( + GCodeAbsoluteDistanceMode(), + GCodeCannedCycleReturnToR(), + ) + line_data = [ + ('g0 z5', {'Z':5}), + ('g81 x10 y20 z-2 r1', {'X':10, 'Y':20, 'Z':1}), + ] + self.assert_processed_lines(line_data, m) + + def test_canned_loops(self): + m = Machine() + m.process_gcodes( + GCodeAbsoluteDistanceMode(), + GCodeCannedCycleReturnPrevLevel(), + ) + line_data = [ + ('g0 z5', None), + ('g81 x10 y20 z-2 r1 l2', {'X':10, 'Y':20, 'Z':5}), + ('g91', None), # switch to incremental mode + ('g81 x10 y20 z-2 r1 l2', {'X':30, 'Y':60, 'Z':5}), + ] + self.assert_processed_lines(line_data, m) From 57455bc787a9532557937027a3b475c630b67217 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Tue, 25 Jul 2017 01:55:09 +1000 Subject: [PATCH 16/30] removed verbose test output --- deployment/deploy.sh | 2 +- tests/runtests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deployment/deploy.sh b/deployment/deploy.sh index 5200927..0a254aa 100755 --- a/deployment/deploy.sh +++ b/deployment/deploy.sh @@ -154,7 +154,7 @@ function run_test() { pushd ../tests workon ${env_name} - ${env_python_bin} -m unittest discover -s . -p 'test_*.py' --verbose + ${env_python_bin} -m unittest discover -s . -p 'test_*.py' deactivate popd } diff --git a/tests/runtests.sh b/tests/runtests.sh index 06ad089..a735a38 100755 --- a/tests/runtests.sh +++ b/tests/runtests.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -python -m unittest discover -s . -p 'test_*.py' --verbose +python -m unittest discover -s . -p 'test_*.py' From 817aeef93494442af31540c0864e695cf5fb4fe9 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Tue, 25 Jul 2017 23:59:12 +1000 Subject: [PATCH 17/30] fixed embarrassingly implemented arg types --- scripts/pygcode-norm | 82 +++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/scripts/pygcode-norm b/scripts/pygcode-norm index 34b7e1d..94ad14c 100755 --- a/scripts/pygcode-norm +++ b/scripts/pygcode-norm @@ -37,6 +37,43 @@ for pygcode_lib_type in ('installed_lib', 'relative_lib'): # =================== Command Line Arguments =================== +# --- Types +def arc_lin_method_type(value): + """ + :return: {Word('G2'): , ... } + """ + ARC_LIN_CLASS_MAP = { + 'i': ArcLinearizeInside, + 'o': ArcLinearizeOutside, + 'm': ArcLinearizeMid, + } + + value_dict = defaultdict(lambda: ArcLinearizeMid) + if value: + match = re.search(r'^(?P[iom])(,(?P[iom]))?$', value, re.IGNORECASE) + if not match: + raise argparse.ArgumentTypeError("invalid format '%s'" % value) + + value_dict = { + Word('g2'): ARC_LIN_CLASS_MAP[match.group('g2')], + Word('g3'): ARC_LIN_CLASS_MAP[match.group('g2')], + } + if match.group('g3'): + value_dict[Word('g3')] = ARC_LIN_CLASS_MAP[match.group('g3')] + + return value_dict + +def canned_codes_type(value): + """ + :return: [Word('G73'), Word('G89'), ... ] + """ + canned_code_words = set() + for word_str in re.split(r'\s*,\s*', value): + canned_code_words.add(Word(word_str)) + + return canned_code_words + + # --- Defaults DEFAULT_PRECISION = 0.005 # mm DEFAULT_MACHINE_MODE = 'G0 G54 G17 G21 G90 G94 M5 M9 T0 F0 S0' @@ -46,7 +83,7 @@ DEFAULT_CANNED_CODES = ','.join(str(w) for w in sorted(c.word_key for c in _subc # --- Create Parser parser = argparse.ArgumentParser(description='Normalize gcode for machine consistency using different CAM software') parser.add_argument( - 'infile', type=argparse.FileType('r'), nargs=1, + 'infile', type=argparse.FileType('r'), help="gcode file to normalize", ) @@ -75,7 +112,8 @@ group.add_argument( help="convert G2,G3 commands to a series of linear interpolations (G1 codes)", ) group.add_argument( - '--arc_lin_method', '-alm', dest='arc_lin_method', default=DEFAULT_ARC_LIN_METHOD, + '--arc_lin_method', '-alm', dest='arc_lin_method', + type=arc_lin_method_type, default=DEFAULT_ARC_LIN_METHOD, help="Method of linearizing arcs, i=inner, o=outer, m=mid. List 2 " "for ,, eg 'i,o'. 'i' is equivalent to 'i,i'. " "(default: '%s')" % DEFAULT_ARC_LIN_METHOD, @@ -94,7 +132,8 @@ group.add_argument( help="Expand canned cycles into basic linear movements, and pauses", ) group.add_argument( - '---canned_codes', '-cc', dest='canned_codes', default=DEFAULT_CANNED_CODES, + '--canned_codes', '-cc', dest='canned_codes', + type=canned_codes_type, default=DEFAULT_CANNED_CODES, help="List of canned gcodes to expand, (default is '%s')" % DEFAULT_CANNED_CODES, ) @@ -109,41 +148,6 @@ group.add_argument( args = parser.parse_args() -# --- Manually Parsing : Arc Linearizing Method -# args.arc_lin_method = {Word('G2'): , ... } -ARC_LIN_CLASS_MAP = { - 'i': ArcLinearizeInside, - 'o': ArcLinearizeOutside, - 'm': ArcLinearizeMid, -} - -arc_lin_method_regex = re.compile(r'^(?P[iom])(,(?P[iom]))?$', re.I) -if args.arc_lin_method: - match = arc_lin_method_regex.search(args.arc_lin_method) - if not match: - raise RuntimeError("parameter for --arc_lin_method is invalid: '%s'" % args.arc_lin_method) - - # changing args.arc_lin_method (because I'm a fiend) - args.arc_lin_method = {} - args.arc_lin_method[Word('g2')] = ARC_LIN_CLASS_MAP[match.group('g2')] - if match.group('g3'): - args.arc_lin_method[Word('g3')] = ARC_LIN_CLASS_MAP[match.group('g3')] - else: - args.arc_lin_method[Word('g3')] = args.arc_lin_method[Word('g2')] -else: - # FIXME: change default to ArcLinearizeMid (when it's working) - args.arc_lin_method = defaultdict(lambda: ArcLinearizeMid) # just to be sure - - -# --- Manually Parsing : Canned Codes -# args.canned_codes = [Word('G73'), Word('G89'), ... ] -canned_code_words = set() -for word_str in re.split(r'\s*,\s*', args.canned_codes): - canned_code_words.add(Word(word_str)) - -args.canned_codes = canned_code_words - - # =================== Create Virtual CNC Machine =================== class MyMode(Mode): default_mode = args.machine_mode @@ -185,7 +189,7 @@ def split_and_process(gcode_list, gcode_class, comment): # =================== Process File =================== -for line_str in args.infile[0].readlines(): +for line_str in args.infile.readlines(): line = Line(line_str) # Effective G-Codes: From 133fc30fa9fefc2f91816e21ff8ca549dc0d3250 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Wed, 26 Jul 2017 00:27:05 +1000 Subject: [PATCH 18/30] start of gcode crop script (wip) --- scripts/pygcode-crop | 193 ++++++++++++++++++++++++++++++++++ src/pygcode.egg-info/PKG-INFO | 10 +- 2 files changed, 197 insertions(+), 6 deletions(-) create mode 100755 scripts/pygcode-crop diff --git a/scripts/pygcode-crop b/scripts/pygcode-crop new file mode 100755 index 0000000..a5f79fc --- /dev/null +++ b/scripts/pygcode-crop @@ -0,0 +1,193 @@ +#!/usr/bin/env python + +# Script to remove commands of a gcode file before and after the given range. +# All gcodes before the given line will be replaced with equivalent rapid +# movements to get to the right position. Initial rapid movement will first move +# to the maximum Z value used in the removed portion, then move to XY, +# then move down to the correct Z. + +import argparse +import re +from copy import copy + +for pygcode_lib_type in ('installed_lib', 'relative_lib'): + try: + # pygcode + from pygcode import Machine, Mode + from pygcode import Line + + except ImportError: + import sys, os, inspect + # Add pygcode (relative to this test-path) to the system path + _this_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + sys.path.insert(0, os.path.join(_this_path, '..', 'src')) + if pygcode_lib_type == 'installed_lib': + continue # import was attempted before sys.path addition. retry import + raise # otherwise the raised ImportError is a genuine problem + break + + +# =================== Command Line Arguments =================== +# --- Types +def range_type(value): + """ + Return (is_first, is_last) such that is_first(n, pos) will return True if + the gcode's current line is the first to be cropped, and similarly for the + last line. + :param value: string given as argument + :return: (is_first, is_last) callables + """ + # All files are cropped from one line, to another, identifying these lines is + # done via the [first] and [last] cropping criteria. + # - Line numbers (parameters: n) + # - Machine position (parameters: x,y,z,a,b,c,u,v,w) + # Comparisons, all with + # - = (or ==) equal to + # - != not equal to + # - < less than + # - <= less than or equal to + # - > greater than + # - >= greater than or equal to + match = re.search(r'^(?P[^:]*):(?P[^:]*)$', value) + if not match: + raise argparse.ArgumentTypeError("'%s' range invalid format" % value) + + def _cmp(cmp_str): + """ + Convert strings like + 'x>10.3' + into a callable equivalent to: + lambda n, pos: pos.X > 10.3 + where: + n is the file's line number + pos is the machine's position (Position) instance + :param cmp_str: comparison string of the form: '' + :return: callable + """ + CMP_MAP = { + '=': lambda a, b: a == b, + '==': lambda a, b: a == b, + '!=': lambda a, b: a != b, + '<': lambda a, b: a < b, + '<=': lambda a, b: a <= b, + '>': lambda a, b: a > b, + '>=': lambda a, b: a >= b, + } + # split comparison into (param, cmp, value) + m = re.search( + r'''^\s* + ( + (?P[abcnuvwxyz])?\s* # parameter + (?P(==?|!=|<=?|>=?)) # comparison + )?\s* # parameter & comparison defaults to "n=" + (?P-?\d+(\.\d+)?)\s* + $''', + cmp_str, re.IGNORECASE | re.MULTILINE | re.VERBOSE + ) + if not m: + raise argparse.ArgumentTypeError("'%s' range comparison invalid" % cmp_str) + (param, cmp, val) = ( + (m.group('param') or 'N').upper(), # default to 'N' + m.group('cmp') or '=', # default to '=' + m.group('value') + ) + + # convert to lambda + if param == 'N': + if float(val) % 1: + raise argparse.ArgumentTypeError("'%s' line number must be an integer" % cmp_str) + return lambda n, pos: CMP_MAP[cmp](n, float(val)) + else: + return lambda n, pos: CMP_MAP[cmp](getattr(pos, param), float(val)) + + def _cmp_group(group_str, default): + """ + Split given group_str by ',' and return callable that will return True + only if all comparisons are true. + So if group_str is: + x>=10.4,z>1 + return will be a callable equivalent to: + lambda n, pos: (pos.X >= 10.4) and (pos.Z > 1) + (see _cmp for more detail) + :param group_str: string of _cmp valid strings delimited by ','s + :param default: default callable if group_str is falsey + :return: callable that returns True if all cmp's are true + """ + if not group_str: + return default + cmp_list = [] + for cmp_str in group_str.split(','): + cmp_list.append(_cmp(cmp_str)) + return lambda n, pos: all(x(n, pos) for x in cmp_list) + + + is_first = _cmp_group(match.group('first'), lambda n, pos: True) + is_last = _cmp_group(match.group('last'), lambda n, pos: False) + + return (is_first, is_last) + + +# --- Defaults + + +# --- Create Parser +parser = argparse.ArgumentParser(description='Crop a gcode file down to the') +parser.add_argument( + 'infile', type=argparse.FileType('r'), nargs=1, + help="gcode file to normalize", +) +parser.add_argument( + 'range', type=range_type, + help="file range to crop, format [first]:[last]", +) + + +# --- Parse Arguments +args = parser.parse_args() + + +# =================== Cropping File =================== + +# --- Machine +class NullMachine(Machine): + MODE_CLASS = type('NullMode', (Mode,), {'default_mode': ''}) + +machine = NullMachine() + +pre_crop = True +post_crop = False + +(is_first, is_last) = args.range + + +for (i, line_str) in enumerate(args.infile.readlines()): + line = Line(line_str) + + # TODO: remember machine's maximum values for each axis + # TODO: based on machine.abs_pos + + # remember machine's (relevant) state before processing + # TODO: create machine.__copy__ to copy position & state + old_machine = copy(machine) + machine.process_block(line.block) + + if pre_crop: + if is_first(i + 1, old_machine.pos): + # First line inside cropping range + pre_crop = False + + # TODO: print mode + print(old_machine.mode) + # TODO: position machine before first cropped line + # TODO: rapid move to Z (maximum Z) + # TODO: rapid move to X,Y + # TODO: rapid move to Z (machine.pos.Z) + + + if (pre_crop, post_crop) == (False, False): + + print(line) + + if is_last(i + 1, old_machine.pos): + # Last line in cropping range + post_crop = True diff --git a/src/pygcode.egg-info/PKG-INFO b/src/pygcode.egg-info/PKG-INFO index c5d6f57..1b92725 100644 --- a/src/pygcode.egg-info/PKG-INFO +++ b/src/pygcode.egg-info/PKG-INFO @@ -119,15 +119,13 @@ Description: ======= G01 X1 Y2 F100 S1000 ; blah >>> print(line.block) G01 X1 Y2 F100 S1000 + >>> sorted(line.block.gcodes) + [, + , + ] >>> print(line.comment) ; blah - >>> line = Line('G0 x1 y2 (foo) f100 (bar) s1000') - >>> print(line) - G00 X1 Y2 F100 S1000 (foo. bar) - >>> print(line.comment) - (foo. bar) - Interpreting what a line of gcode does depends on the machine it's running on, and also that machine's state (or 'mode') From 9c2fae672ce91e924e9f207d7908ebb2f102b823 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Thu, 27 Jul 2017 16:11:56 +1000 Subject: [PATCH 19/30] added normalization func' --- scripts/pygcode-norm | 133 +++++++++++++++++++++++++++++++++-------- src/pygcode/machine.py | 24 ++++---- 2 files changed, 121 insertions(+), 36 deletions(-) diff --git a/scripts/pygcode-norm b/scripts/pygcode-norm index 94ad14c..1c967da 100755 --- a/scripts/pygcode-norm +++ b/scripts/pygcode-norm @@ -23,7 +23,7 @@ for pygcode_lib_type in ('installed_lib', 'relative_lib'): from pygcode.transform import linearize_arc, simplify_canned_cycle from pygcode.transform import ArcLinearizeInside, ArcLinearizeOutside, ArcLinearizeMid from pygcode.gcodes import _subclasses - from pygcode.utils import omit_redundant_modes + from pygcode import utils except ImportError: import sys, os, inspect @@ -63,7 +63,7 @@ def arc_lin_method_type(value): return value_dict -def canned_codes_type(value): +def word_list_type(value): """ :return: [Word('G73'), Word('G89'), ... ] """ @@ -88,9 +88,15 @@ parser.add_argument( ) parser.add_argument( - '--precision', '-p', dest='precision', type=float, default=DEFAULT_PRECISION, - help="maximum positional error when generating gcodes (eg: arcs to lines) " - "(default: %g)" % DEFAULT_PRECISION, + '--singles', '-s', dest='singles', + action='store_const', const=True, default=False, + help="only output one command per gcode line", +) +parser.add_argument( + '--full', '-f', dest='full', + action='store_const', const=True, default=False, + help="output full commands, any modal parameters will be acompanied with " + "the fully qualified gcode command", ) # Machine @@ -104,7 +110,7 @@ group = parser.add_argument_group( "Arc Linearizing", "Converting arcs (G2/G3 codes) into linear interpolations (G1 codes) to " "aproximate the original arc. Indistinguishable from an original arc when " - "--precision is set low enough." + "--arc_precision is set low enough." ) group.add_argument( '--arc_linearize', '-al', dest='arc_linearize', @@ -119,6 +125,18 @@ group.add_argument( "(default: '%s')" % DEFAULT_ARC_LIN_METHOD, metavar='{i,o,m}[,{i,o,m}]', ) +group.add_argument( + '--arc_precision', '-alp', dest='arc_precision', type=float, default=DEFAULT_PRECISION, + help="maximum positional error when creating linear interpolation codes " + "(default: %g)" % DEFAULT_PRECISION, +) + +#parser.add_argument( +# '--arc_alignment', '-aa', dest='arc_alignment', type=str, choices=('XYZ','IJK','R'), +# default=None, +# help="enforce precision on arcs, if XYZ the destination is altered to match the radius" +# "if IJK or R then the arc'c centre point is moved to assure precision", +#) # Canned Cycles group = parser.add_argument_group( @@ -133,16 +151,37 @@ group.add_argument( ) group.add_argument( '--canned_codes', '-cc', dest='canned_codes', - type=canned_codes_type, default=DEFAULT_CANNED_CODES, + type=word_list_type, default=DEFAULT_CANNED_CODES, help="List of canned gcodes to expand, (default is '%s')" % DEFAULT_CANNED_CODES, ) -#parser.add_argument( -# '--arc_alignment', '-aa', dest='arc_alignment', type=str, choices=('XYZ','IJK','R'), -# default=None, -# help="enforce precision on arcs, if XYZ the destination is altered to match the radius" -# "if IJK or R then the arc'c centre point is moved to assure precision", -#) +# Removing non-functional content +group = parser.add_argument_group( + "Removing Content", + "options for the removal of content" +) +group.add_argument( + '--rm_comments', '-rc', dest='rm_comments', + action='store_const', const=True, default=False, + help="remove all comments (non-functional)", +) +group.add_argument( + '--rm_blanks', '-rb', dest='rm_blanks', + action='store_const', const=True, default=False, + help="remove all empty lines (non-functional)", +) +group.add_argument( + '--rm_whitespace', '-rws', dest='rm_whitespace', + action='store_const', const=True, default=False, + help="remove all whitespace from gcode blocks (non-functional)", +) +group.add_argument( + '--rm_gcodes', '-rmg', dest='rm_gcodes', + type=word_list_type, default=[], + help="remove gcode (and it's parameters) with words in the given list " + "(eg: M6,G43) (note: only works for modal params with --full)", +) + # --- Parse Arguments args = parser.parse_args() @@ -158,6 +197,46 @@ class MyMachine(Machine): machine = MyMachine() # =================== Utility Functions =================== +omit_redundant_modes = utils.omit_redundant_modes +if args.full: + omit_redundant_modes = lambda gcode_iter: gcode_iter # bypass + +def write(gcodes, modal_params=tuple(), comment=None): + """ + Write to output, while enforcing the flags: + args.singles + args.rm_comments + args.rm_blanks + args.rm_whitespace + :param obj: Line, Block, GCode or Comment instance + """ + assert not(args.full and modal_params), "with full specified, this should never be called with modal_params" + if args.singles and len(gcodes) > 1: + for g in sorted(gcodes): + write([g], comment=comment) + else: + # remove comments + if args.rm_comments: + comment = None + # remove particular gcodes + if args.rm_gcodes: + gcodes = [g for g in gcodes if g.word not in args.rm_gcodes] + + # Convert to string & write to file (or stdout) + block_str = ' '.join(str(x) for x in (list(gcodes) + list(modal_params))) + if args.rm_whitespace: + block_str = re.sub(r'\s', '', block_str) + + line_list = [] + if block_str: + line_list.append(block_str) + if comment: + line_list.append(str(comment)) + line_str = ' '.join(line_list) + if line_str or not args.rm_blanks: + print(line_str) + + def gcodes2str(gcodes): return ' '.join("%s" % g for g in gcodes) @@ -171,20 +250,21 @@ def split_and_process(gcode_list, gcode_class, comment): :param comment: Comment instance, or None """ (befores, (g,), afters) = split_gcodes(gcode_list, gcode_class) - # print & process those before gcode_class instance + # write & process those before gcode_class instance if befores: - print(gcodes2str(befores)) + write(befores) machine.process_gcodes(*befores) # yield, then process gcode_class instance yield g machine.process_gcodes(g) - # print & process those after gcode_class instance + # write & process those after gcode_class instance if afters: - print(gcodes2str(afters)) + write(afters) machine.process_gcodes(*afters) - # print comment (if given) + # write comment (if given) if comment: - print(str(line.comment)) + write([], comment=line.comment) + # =================== Process File =================== @@ -198,7 +278,7 @@ for line_str in args.infile.readlines(): if args.arc_linearize and any(isinstance(g, GCodeArcMove) for g in effective_gcodes): with split_and_process(effective_gcodes, GCodeArcMove, line.comment) as arc: - print(Comment("linearized arc: %r" % arc)) + write([], comment=Comment("linearized arc: %r" % arc)) linearize_params = { 'arc_gcode': arc, 'start_pos': machine.pos, @@ -206,15 +286,15 @@ for line_str in args.infile.readlines(): 'method_class': args.arc_lin_method[arc.word], 'dist_mode': machine.mode.distance, 'arc_dist_mode': machine.mode.arc_ijk_distance, - 'max_error': args.precision, + 'max_error': args.arc_precision, 'decimal_places': 3, } for linear_gcode in omit_redundant_modes(linearize_arc(**linearize_params)): - print(linear_gcode) + write([linear_gcode]) elif args.canned_expand and any((g.word in args.canned_codes) for g in effective_gcodes): with split_and_process(effective_gcodes, GCodeCannedCycle, line.comment) as canned: - print(Comment("expanded: %r" % canned)) + write([], comment=Comment("expanded: %r" % canned)) simplify_canned_params = { 'canned_gcode': canned, 'start_pos': machine.pos, @@ -223,8 +303,11 @@ for line_str in args.infile.readlines(): 'axes': machine.axes, } for simplified_gcode in omit_redundant_modes(simplify_canned_cycle(**simplify_canned_params)): - print(simplified_gcode) + write([simplified_gcode]) else: - print(str(line)) + if args.full: + write(effective_gcodes, comment=line.comment) + else: + write(line.block.gcodes, modal_params=line.block.modal_params, comment=line.comment) machine.process_block(line.block) diff --git a/src/pygcode/machine.py b/src/pygcode/machine.py index 7cf412d..42c2f15 100644 --- a/src/pygcode/machine.py +++ b/src/pygcode/machine.py @@ -87,7 +87,7 @@ class Position(object): return self._value == other._value else: x = copy(other) - x.set_unit(self._unit) + x.unit = self._unit return self._value == x._value def __ne__(self, other): @@ -125,13 +125,17 @@ class Position(object): __truediv__ = __div__ # Python 3 division # Conversion - def set_unit(self, unit): - if unit == self._unit: - return - factor = UNIT_MAP[self._unit]['conversion_factor'][unit] - for k in [k for (k, v) in self._value.items() if v is not None]: - self._value[k] *= factor - self._unit = unit + @property + def unit(self): + return self._unit + + @unit.setter + def unit(self, value): + if value != self._unit: + factor = UNIT_MAP[self._unit]['conversion_factor'][value] + for k in [k for (k, v) in self._value.items() if v is not None]: + self._value[k] *= factor + self._unit = value @property def words(self): @@ -202,8 +206,6 @@ class State(object): # Coordinate System selection: # - G54-G59: select coordinate system (offsets from machine coordinates set by G10 L2) - # TODO: Move this class into MachineState - @property def coord_sys(self): """Current equivalent coordinate system, including all """ @@ -328,7 +330,7 @@ class Machine(object): units_mode = getattr(self.mode, 'units', None) self.Position = type('Position', (Position,), { 'default_axes': self.axes, - 'default_unit': units_mode.unit_id if units_mode else UNIT_METRIC, + 'default_unit': units_mode.unit_id if units_mode else Position.default_unit, }) # Absolute machine position From 680eedbf0cdcec69eb3dd709ac67dcb09bb12c21 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Fri, 28 Jul 2017 23:07:15 +1000 Subject: [PATCH 20/30] added media --- media/arc-linearize-method-inside.png | Bin 0 -> 13185 bytes media/arc-linearize-method-mid.png | Bin 0 -> 12119 bytes media/arc-linearize-method-mixed.png | Bin 0 -> 12165 bytes media/arc-linearize-method-outside.png | Bin 0 -> 11022 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 media/arc-linearize-method-inside.png create mode 100644 media/arc-linearize-method-mid.png create mode 100644 media/arc-linearize-method-mixed.png create mode 100644 media/arc-linearize-method-outside.png diff --git a/media/arc-linearize-method-inside.png b/media/arc-linearize-method-inside.png new file mode 100644 index 0000000000000000000000000000000000000000..59535821a097ce8baa2e5ad5e7cfaacea0c591cd GIT binary patch literal 13185 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ⅆ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 literal 0 HcmV?d00001 diff --git a/media/arc-linearize-method-mixed.png b/media/arc-linearize-method-mixed.png new file mode 100644 index 0000000000000000000000000000000000000000..cc9c9be139fd6a7ae6626aa71d3377f86a072760 GIT binary patch literal 12165 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 literal 0 HcmV?d00001 diff --git a/media/arc-linearize-method-outside.png b/media/arc-linearize-method-outside.png new file mode 100644 index 0000000000000000000000000000000000000000..caa139d0d067315fb6e75563adb835cfbe1c0475 GIT binary patch literal 11022 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 Date: Fri, 28 Jul 2017 23:56:54 +1000 Subject: [PATCH 21/30] documentation moved to github wiki --- README.rst | 217 +------------------------------------------ scripts/pygcode-norm | 6 +- 2 files changed, 8 insertions(+), 215 deletions(-) diff --git a/README.rst b/README.rst index a649a90..dd94b32 100644 --- a/README.rst +++ b/README.rst @@ -7,6 +7,7 @@ GCODE Parser for Python Currently in development, ``pygcode`` is a low-level GCode interpreter for python. + Installation ============ @@ -17,217 +18,7 @@ Install using ``pip`` or `download directly from PyPi `__ -Usage -===== +Documentation +============= - -Writing GCode -------------- - -Writing gcode from python object instances to text - -:: - - >>> from pygcode import * - >>> gcodes = [ - ... GCodeRapidMove(Z=5), - ... GCodeStartSpindleCW(), - ... GCodeRapidMove(X=10, Y=20), - ... GCodeFeedRate(200), - ... GCodeLinearMove(Z=-1.5), - ... GCodeRapidMove(Z=5), - ... GCodeStopSpindle(), - ... ] - >>> print('\n'.join(str(g) for g in gcodes)) - - G00 Z5 - M03 - G00 X10 Y20 - F200 - G01 Z-1.5 - G00 Z5 - M05 - - -To plot along a lines of vectors, you could write... - -:: - - >>> from pygcode import * - >>> from euclid import Vector3 - - >>> vectors = [ - ... Vector3(0, 0, 0), - ... Vector3(10, 0, 0), - ... Vector3(10, 20, 0), - ... Vector3(10, 20, 3), - ... Vector3(0, 20, 3), - ... Vector3(0, 0, 3), - ... Vector3(0, 0, 0) - ... ] - - >>> to_coords = lambda v: {'X': v.x, 'Y': v.y, 'Z': v.z} - >>> for v in vectors: - ... print("%s" % GCodeLinearMove(**to_coords(v))) - - G01 X0 Y0 Z0 - G01 X10 Y0 Z0 - G01 X10 Y20 Z0 - G01 X10 Y20 Z3 - G01 X0 Y20 Z3 - G01 X0 Y0 Z3 - G01 X0 Y0 Z0 - - -Reading / Interpreting GCode ----------------------------- - -To read gcode from a file, utilise the ``Line`` class. -Each ``Line`` instance contains a ``Block`` and an optional ``Comment``. -The ``Block`` contains a list of gcodes you're after. - -:: - - from pygcode import Line - - with open('part.gcode', 'r') as fh: - for line_text in fh.readlines(): - line = Line(line_text) - - print(line) # will print the line (with cosmetic changes) - line.block.gcodes # is your list of gcodes - line.block.modal_params # are all parameters not assigned to a gcode, assumed to be motion modal parameters - if line.comment: - line.comment.text # your comment text - -To elaborate, here are some line examples - -:: - - >>> from pygcode import Line - - >>> line = Line('G01 x1 y2 f100 s1000 ; blah') - >>> print(line) - G01 X1 Y2 F100 S1000 ; blah - >>> print(line.block) - G01 X1 Y2 F100 S1000 - >>> sorted(line.block.gcodes) - [, - , - ] - >>> print(line.comment) - ; blah - - -Interpreting what a line of gcode does depends on the machine it's running on, -and also that machine's state (or 'mode') - -The simple line of a rapid move to ``x=10, y=10`` may be ``G00 X10 Y10``. -However, if the machine in question is in "Incremental Motion" mode ``G91`` then -the machine will only end up at ``x=10, y=10`` if it started at ``x=0, y=0`` - -So, GCode interpretation is done via a virtual machine: - -:: - - >>> from pygcode import Machine, GCodeRapidMove - - >>> m = Machine() - >>> m.pos - - >>> g = GCodeRapidMove(X=10, Y=20) - >>> m.process_gcodes(g) - >>> m.pos - - >>> m.process_gcodes(g) - >>> m.pos - # same position; machine in absolute mode - >>> m.mode.distance - # see - - >>> m.process_gcodes(GCodeIncrementalDistanceMode()) - >>> m.process_gcodes(g) # same gcode as above - >>> m.pos - - -all valid ``m.mode`` attributes can be found with ``from pygcode.gcodes import MODAL_GROUP_MAP; MODAL_GROUP_MAP.keys()`` - -Also note that the order codes are interpreted is important. -For example, the following code is WRONG - -:: - - from pygcode import Machine, Line - m = Machine() - line = Line('G0 x10 y10 G91') - m.process_gcodes(*line.block.gcodes) # WRONG! - -This will process the movement to ``x=10, y=10``, and **then** it will change the -distance mode to *Incremental*... there are 2 ways to do this correctly. - -- ``m.process_gcodes(*sorted(line.block.gcodes))``, or simply -- ``m.process_block(line.block)`` - -sorting a list of gcodes will sort them in execution order (as specified by -`LinuxCNC's order of execution `__). -``process_block`` does this automatically. - -If you need to process & change one type of gcode (usually a movement), -you must split a list of gcodes into those executed before, and after the one -in question. - -:: - - from pygcode import GCodeRapidMove, GCodeLinearMove - from pygcode import Machine, Line, split_gcodes - m = Machine() - line = Line('M0 G0 x10 y10 G91') - (befores, (g,), afters) = split_gcodes(line.block.gcodes, (GCodeRapidMove, GCodeLinearMove)) - m.process_gcodes(*sorted(befores)) - if g.X is not None: - g.X += 100 # shift linear movements (rapid or otherwise) - m.process_gcodes(g) - m.process_gcodes(*sorted(afters)) - - -For a more practical use of machines & interpreting gcode, have a look at -`pygcode-normalize.py `__ - -At the time of writing this, that script converts arcs to linear codes, and -expands drilling cycles to basic movements (so my -`GRBL `__ machine can understand them) - - -Development -=========== - -This library came from my own needs to interpret and convert erroneous -arcs to linear segments, and to expand canned drilling cycles, but also -as a means to *learn* GCode. - -As such there is no direct plan for further development, however I'm -interested in what you'd like to use it for, and cater for that. - -Generally, in terms of what to support, I'm following the lead of: - -- `GRBL `__ and -- `LinuxCNC `__ - -More support will come with increased interest. -So that is... if you don't like what it does, or how it's documented, make some -noise in the `issue section `__. -if you get in early, you may get some free labour out of me ;) - - -Supported G-Codes ------------------ - -All GCodes supported by `LinuxCNC `__ can be written, and -parsed by ``pygcode``. - -Few GCodes are accurately interpreted by a virtual CNC ``Machine`` instance. -Supported movements are currently; - -- linear movements -- arc movements -- canned drilling cycles +`Check out the wiki `__ for documentation. diff --git a/scripts/pygcode-norm b/scripts/pygcode-norm index 1c967da..d9bd32f 100755 --- a/scripts/pygcode-norm +++ b/scripts/pygcode-norm @@ -81,7 +81,9 @@ DEFAULT_ARC_LIN_METHOD = 'm' DEFAULT_CANNED_CODES = ','.join(str(w) for w in sorted(c.word_key for c in _subclasses(GCodeCannedCycle) if c.word_key)) # --- Create Parser -parser = argparse.ArgumentParser(description='Normalize gcode for machine consistency using different CAM software') +parser = argparse.ArgumentParser( + description="Normalize gcode for machine consistency when using different CAM software" +) parser.add_argument( 'infile', type=argparse.FileType('r'), help="gcode file to normalize", @@ -121,7 +123,7 @@ group.add_argument( '--arc_lin_method', '-alm', dest='arc_lin_method', type=arc_lin_method_type, default=DEFAULT_ARC_LIN_METHOD, help="Method of linearizing arcs, i=inner, o=outer, m=mid. List 2 " - "for ,, eg 'i,o'. 'i' is equivalent to 'i,i'. " + "for ,, eg 'i,o'. 'i' is equivalent to 'i,i'. " "(default: '%s')" % DEFAULT_ARC_LIN_METHOD, metavar='{i,o,m}[,{i,o,m}]', ) From a82becb61ddae2de0c458fc10efbb76f20bd5690 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sat, 29 Jul 2017 00:02:23 +1000 Subject: [PATCH 22/30] added media readme --- media/README.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 media/README.md diff --git a/media/README.md b/media/README.md new file mode 100644 index 0000000..6086cb4 --- /dev/null +++ b/media/README.md @@ -0,0 +1,6 @@ + +## `arc-linearize-method-*.png` + +Screenshots of arc linearizing methods for the `pygcode-norm` script. + +credit to _nraynaud_ for [this awesome online gcode interpreter](https://nraynaud.github.io/webgcode/) From 53de97d9b0d8c6c257e112835e26b0de8670241b Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sun, 30 Jul 2017 01:24:21 +1000 Subject: [PATCH 23/30] first working crop script --- scripts/pygcode-crop | 65 ++++++++++++++++++++++----------- src/pygcode/gcodes.py | 7 +++- src/pygcode/machine.py | 83 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 121 insertions(+), 34 deletions(-) diff --git a/scripts/pygcode-crop b/scripts/pygcode-crop index a5f79fc..f693872 100755 --- a/scripts/pygcode-crop +++ b/scripts/pygcode-crop @@ -14,7 +14,9 @@ for pygcode_lib_type in ('installed_lib', 'relative_lib'): try: # pygcode from pygcode import Machine, Mode - from pygcode import Line + from pygcode import Line, Comment + from pygcode import GCodePlaneSelect, GCodeSelectXYPlane + from pygcode import GCodeRapidMove except ImportError: import sys, os, inspect @@ -131,9 +133,11 @@ def range_type(value): # --- Create Parser -parser = argparse.ArgumentParser(description='Crop a gcode file down to the') +parser = argparse.ArgumentParser( + description="Remove gcode before and after given 'from' and 'to' events" +) parser.add_argument( - 'infile', type=argparse.FileType('r'), nargs=1, + 'infile', type=argparse.FileType('r'), help="gcode file to normalize", ) parser.add_argument( @@ -159,35 +163,52 @@ post_crop = False (is_first, is_last) = args.range - for (i, line_str) in enumerate(args.infile.readlines()): line = Line(line_str) - # TODO: remember machine's maximum values for each axis - # TODO: based on machine.abs_pos - - # remember machine's (relevant) state before processing - # TODO: create machine.__copy__ to copy position & state + # remember machine's state before processing the current line old_machine = copy(machine) machine.process_block(line.block) if pre_crop: - if is_first(i + 1, old_machine.pos): + if is_first(i + 1, machine.pos): # First line inside cropping range pre_crop = False - # TODO: print mode - print(old_machine.mode) - # TODO: position machine before first cropped line - # TODO: rapid move to Z (maximum Z) - # TODO: rapid move to X,Y - # TODO: rapid move to Z (machine.pos.Z) + # Set machine's accumulated mode (from everything that's been cut) + mode_str = str(old_machine.mode) + if mode_str: + print(Comment("machine mode before cropping")) + print(mode_str) + # Getting machine's current (modal) selected plane + plane = old_machine.mode.plane_selection + if not isinstance(plane, GCodePlaneSelect): + plane = GCodeSelectXYPlane() # default to XY plane + + # --- position machine before first cropped line + print(Comment("traverse into position, up, over, and down")) + # rapid move to Z (maximum Z the machine has experienced thus far) + print(GCodeRapidMove(**{ + plane.normal_axis: getattr(old_machine.abs_range_max, plane.normal_axis), + })) + # rapid move to X,Y + print(GCodeRapidMove(**dict( + (k, v) for (k, v) in old_machine.pos.values.items() + if k in plane.plane_axes + ))) + # rapid move to Z (machine.pos.Z) + print(GCodeRapidMove(**{ + plane.normal_axis: getattr(old_machine.pos, plane.normal_axis), + })) + print('') if (pre_crop, post_crop) == (False, False): - - print(line) - - if is_last(i + 1, old_machine.pos): - # Last line in cropping range - post_crop = True + if is_last(i + 1, machine.pos): + # First line **outside** the area being cropped + # (ie: this line won't be output) + post_crop = True # although, irrelevant because... + break + else: + # inside cropping area + print(line) diff --git a/src/pygcode/gcodes.py b/src/pygcode/gcodes.py index 83f3735..5013fb1 100644 --- a/src/pygcode/gcodes.py +++ b/src/pygcode/gcodes.py @@ -824,9 +824,11 @@ class GCodePlaneSelect(GCode): # vectorYZ = GCodeSelectYZPlane.quat * (GCodeSelectZXPlane.quat.conjugate() * vectorZX) quat = None # Quaternion - # -- Plane Normal + # -- Plane Axis Information # Vector normal to plane (such that XYZ axes follow the right-hand rule) normal_axis = None # Letter of normal axis (upper case) + # Axes of plane + plane_axes = set() normal = None # Vector3 @@ -835,6 +837,7 @@ class GCodeSelectXYPlane(GCodePlaneSelect): word_key = Word('G', 17) quat = Quaternion() # no effect normal_axis = 'Z' + plane_axes = set('XY') normal = Vector3(0., 0., 1.) @@ -846,6 +849,7 @@ class GCodeSelectZXPlane(GCodePlaneSelect): Vector3(0., 0., 1.), Vector3(1., 0., 0.) ) normal_axis = 'Y' + plane_axes = set('ZX') normal = Vector3(0., 1., 0.) @@ -857,6 +861,7 @@ class GCodeSelectYZPlane(GCodePlaneSelect): Vector3(0., 1., 0.), Vector3(0., 0., 1.) ) normal_axis = 'X' + plane_axes = set('YZ') normal = Vector3(1., 0., 0.) diff --git a/src/pygcode/machine.py b/src/pygcode/machine.py index 42c2f15..72017d3 100644 --- a/src/pygcode/machine.py +++ b/src/pygcode/machine.py @@ -52,6 +52,9 @@ class Position(object): self._value = defaultdict(lambda: 0.0, dict((k, 0.0) for k in self.axes)) self._value.update(kwargs) + def __copy__(self): + return self.__class__(axes=copy(self.axes), unit=self._unit, **self.values) + def update(self, **coords): for (k, v) in coords.items(): setattr(self, k, v) @@ -74,10 +77,6 @@ class Position(object): else: self.__dict__[key] = value - # Copy - def __copy__(self): - return self.__class__(axes=copy(self.axes), unit=self._unit, **self.values) - # Equality def __eq__(self, other): if self.axes ^ other.axes: @@ -137,6 +136,36 @@ class Position(object): self._value[k] *= factor self._unit = value + # Min/Max + @classmethod + def _cmp(cls, p1, p2, key): + """ + Returns a position of the combined min/max values for each axis + (eg: key=min for) + note: the result is not necessarily equal to either p1 or p2. + :param p1: Position instance + :param p2: Position instance + :return: Position instance with the highest/lowest value per axis + """ + if p2.unit != p1.unit: + p2 = copy(p2) + p2.unit = p1.unit + return cls( + unit=p1.unit, + **dict( + (k, key(getattr(p1, k), getattr(p2, k))) for k in p1.values + ) + ) + + @classmethod + def min(cls, a, b): + return cls._cmp(a, b, key=min) + + @classmethod + def max(cls, a, b): + return cls._cmp(a, b, key=max) + + # Words & Values @property def words(self): return sorted(Word(k, self._value[k]) for k in self.axes) @@ -149,6 +178,7 @@ class Position(object): def vector(self): return Vector3(self._value['X'], self._value['Y'], self._value['Z']) + # String representation(s) def __repr__(self): return "<{class_name}: {coordinates}>".format( class_name=self.__class__.__name__, @@ -157,12 +187,13 @@ class Position(object): class CoordinateSystem(object): - def __init__(self, axes): - self.offset = Position(axes) + def __init__(self, axes=None): + self.offset = Position(axes=axes) - def __add__(self, other): - if isinstance(other, CoordinateSystem): - pass + def __copy__(self): + obj = self.__class__() + obj.offset = copy(self.offset) + return obj def __repr__(self): return "<{class_name}: offset={offset}>".format( @@ -178,6 +209,7 @@ class State(object): # AFAIK: this is everything needed to remember a machine's state that isn't # handled by modal gcodes. def __init__(self, axes=None): + self._axes = axes # Coordinate Systems self.coord_systems = {} for i in range(1, 10): # G54-G59.3 @@ -206,6 +238,12 @@ class State(object): # Coordinate System selection: # - G54-G59: select coordinate system (offsets from machine coordinates set by G10 L2) + def __copy__(self): + obj = self.__class__(axes=self._axes) + obj.coord_systems = [copy(cs) for cs in self.coord_systems] + obj.offset = copy(self.offset) + return obj + @property def coord_sys(self): """Current equivalent coordinate system, including all """ @@ -249,11 +287,17 @@ class Mode(object): # Mode is defined by gcodes set by processed blocks: # see modal_group in gcode.py module for details - def __init__(self): + def __init__(self, set_default=True): self.modal_groups = defaultdict(lambda: None) # Initialize - self.set_mode(*Line(self.default_mode).block.gcodes) + if set_default: + self.set_mode(*Line(self.default_mode).block.gcodes) + + def __copy__(self): + obj = self.__class__(set_default=False) + obj.modal_groups = deepcopy(self.modal_groups) + return obj def set_mode(self, *gcode_list): """ @@ -335,6 +379,18 @@ class Machine(object): # Absolute machine position self.abs_pos = self.Position() + # Machine's motion range (min/max corners of a bounding box) + self.abs_range_min = copy(self.abs_pos) + self.abs_range_max = copy(self.abs_pos) + + def __copy__(self): + obj = self.__class__() + obj.mode = copy(self.mode) + obj.state = copy(self.state) + obj.abs_pos = copy(self.abs_pos) + obj.abs_range_min = copy(self.abs_range_min) + obj.abs_range_max = copy(self.abs_range_max) + return obj def set_mode(self, *gcode_list): self.mode.set_mode(*gcode_list) # passthrough @@ -425,6 +481,11 @@ class Machine(object): coord_sys_offset = getattr(self.state.coord_sys, 'offset', Position(axes=self.axes)) temp_offset = self.state.offset self.abs_pos = (value + temp_offset) + coord_sys_offset + self._update_abs_range(self.abs_pos) + + def _update_abs_range(self, pos): + self.abs_range_min = Position.min(pos, self.abs_range_min) + self.abs_range_max = Position.max(pos, self.abs_range_max) # =================== Machine Actions =================== def move_to(self, rapid=False, **coords): From 19dd2c71439c3129ceff0e06591c70188f49e7c2 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sun, 30 Jul 2017 01:25:20 +1000 Subject: [PATCH 24/30] pygcode-crop to setup --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 7c04491..ca02036 100644 --- a/setup.py +++ b/setup.py @@ -32,6 +32,7 @@ INSTALL_REQUIRES = [ ] SCRIPTS = [ 'scripts/pygcode-norm', + 'scripts/pygcode-crop', ] ################################################################### From b6ab3ccb08c423f3b1c8e2ec29dd09cf31bb1d87 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sun, 30 Jul 2017 18:28:38 +1000 Subject: [PATCH 25/30] help text, moreso --- scripts/pygcode-crop | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/scripts/pygcode-crop b/scripts/pygcode-crop index f693872..b5d1d66 100755 --- a/scripts/pygcode-crop +++ b/scripts/pygcode-crop @@ -42,7 +42,7 @@ def range_type(value): # All files are cropped from one line, to another, identifying these lines is # done via the [first] and [last] cropping criteria. # - Line numbers (parameters: n) - # - Machine position (parameters: x,y,z,a,b,c,u,v,w) + # - Machine position (parameters: a,b,c,x,y,z) # Comparisons, all with # - = (or ==) equal to # - != not equal to @@ -79,7 +79,7 @@ def range_type(value): m = re.search( r'''^\s* ( - (?P[abcnuvwxyz])?\s* # parameter + (?P[abcnxyz])?\s* # parameter (?P(==?|!=|<=?|>=?)) # comparison )?\s* # parameter & comparison defaults to "n=" (?P-?\d+(\.\d+)?)\s* @@ -134,15 +134,46 @@ def range_type(value): # --- Create Parser parser = argparse.ArgumentParser( - description="Remove gcode before and after given 'from' and 'to' events" + description="Remove gcode before and after given 'from' and 'to' conditions.", + epilog="Range Format:" + """ + range must be of the format: + [condition[,condition...]]:[condition[,condition...]] + the first condition(s) are true for the first line included in the cropped area + the second set are true for the first line excluded after the cropped area + + Conditions: + each condition is of the format: + {variable}{operation}{number} + or, more specifically: + [[{a,b,c,n,x,y,z}]{=,!=,<,<=,>,>=}]{number} + + Condition Variables: + n - file's line number + a|b|c - machine's angular axes + x|y|z - machine's linear axes + + Example Ranges: + "100:200" will crop lines 100-199 (inclusive) + "z<=-2:" will isolate everything after the machine crosses z=-2 + "x>10,y>10:n>=123" starts cropped area where both x and y exceed 10, + but only before line 123 + + Limitations: + Only takes points from start and finish of a gcode operation, so a line + through a condition region, or an arc that crosses a barrier will NOT + trigger the start or stop of cropping. + Probe alignment operations will not change virtual machine's position. + """, + formatter_class=argparse.RawTextHelpFormatter, ) parser.add_argument( 'infile', type=argparse.FileType('r'), - help="gcode file to normalize", + help="gcode file to crop", ) parser.add_argument( 'range', type=range_type, - help="file range to crop, format [first]:[last]", + help="file range to crop, format [from]:[to] (details below)", ) From 3e46bd636a3d2b947177b224eb3ab9ea23bb8654 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sun, 30 Jul 2017 20:36:50 +1000 Subject: [PATCH 26/30] py3 fix --- src/pygcode/machine.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pygcode/machine.py b/src/pygcode/machine.py index 72017d3..ac19ace 100644 --- a/src/pygcode/machine.py +++ b/src/pygcode/machine.py @@ -410,7 +410,9 @@ class Machine(object): raise MachineInvalidState("unable to assign modal parameters when no motion mode is set") params = copy(self.mode.motion.params) # dict params.update(dict((w.letter, w) for w in modal_params)) # override retained modal parameters - (modal_gcodes, unasigned_words) = words2gcodes([self.mode.motion.word] + params.values()) + (modal_gcodes, unasigned_words) = words2gcodes( + [self.mode.motion.word] + list(params.values()) + ) if unasigned_words: raise MachineInvalidState("modal parameters '%s' cannot be assigned when in mode: %r" % ( ' '.join(str(x) for x in unasigned_words), self.mode From 41f7a46aaaf8f55132553a65b90293d8a3680644 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sun, 30 Jul 2017 20:37:13 +1000 Subject: [PATCH 27/30] environment dependencies --- deployment/README.md | 3 +++ deployment/deploy.sh | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/deployment/README.md b/deployment/README.md index d6158a4..1b5e55b 100644 --- a/deployment/README.md +++ b/deployment/README.md @@ -34,6 +34,7 @@ Arguments: Virtual Environments: rmenv py# Remove virtual environment remkenv py# Remove, then create re-create virtual environment + envprereq py# install environment prerequisites (official PyPi) Deploy: deploy test Upload to PyPi test server @@ -98,11 +99,13 @@ password=secret ``` # Python 2.x ./deploy.sh remkenv py2 +./deploy.sh envprereq py2 ./deploy.sh install sdist py2 ./deploy.sh test installed py2 # Python 3.x ./deploy.sh remkenv py3 +./deploy.sh envprereq py3 ./deploy.sh install sdist py3 ./deploy.sh test installed py3 ``` diff --git a/deployment/deploy.sh b/deployment/deploy.sh index 0a254aa..008bbee 100755 --- a/deployment/deploy.sh +++ b/deployment/deploy.sh @@ -13,6 +13,12 @@ function lib_ver() { popd > /dev/null } +function lib_prereq() { + pushd .. > /dev/null + python -c 'from setup import INSTALL_REQUIRES ; print(" ".join(INSTALL_REQUIRES))' + popd > /dev/null +} + # ============ Local Parameters LIB_NAME=pygcode LIB_VER=$(lib_ver) @@ -38,6 +44,7 @@ Arguments: Virtual Environments: rmenv py# Remove virtual environment remkenv py# Remove, then create re-create virtual environment + envprereq py# install environment prerequisites (official PyPi) Deploy: deploy test Upload to PyPi test server @@ -89,6 +96,13 @@ function remkenv() { mkvirtualenv --python=${python_bin} ${env_name} } +function envprereq() { + set_venv_variables $1 + workon ${env_name} + ${env_pip_bin} install $(lib_prereq) + deactivate +} + function deploy() { # Deploy compiled distributions to the test|prod server _deployment_env=$1 @@ -198,6 +212,7 @@ case "$1" in build) build ;; rmenv) rmenv $2 ;; remkenv) remkenv $2 ;; + envprereq) envprereq $2 ;; deploy) deploy $2 ;; install) install $2 $3 ;; test) run_test $2 $3 ;; From a306f8497c0611c6aca0a3ec2980de727f7dceeb Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sun, 30 Jul 2017 20:40:11 +1000 Subject: [PATCH 28/30] deploy notes derp --- deployment/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deployment/README.md b/deployment/README.md index 1b5e55b..8ff11eb 100644 --- a/deployment/README.md +++ b/deployment/README.md @@ -127,7 +127,7 @@ password=secret ## Upload to PyPi Test server ``` -./deploy.sh test +./deploy.sh deploy test ``` **Test** @@ -153,7 +153,7 @@ to make sure it's sane all good!? sweet :+1: time to upload to 'production' ``` -./deploy.sh prod +./deploy.sh deploy prod ``` **Test** From 89002950680159e7a08eb0fa3b01f6d51c9d3b6c Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sun, 30 Jul 2017 20:53:55 +1000 Subject: [PATCH 29/30] more updates --- deployment/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deployment/README.md b/deployment/README.md index 8ff11eb..3bb02bb 100644 --- a/deployment/README.md +++ b/deployment/README.md @@ -134,11 +134,13 @@ password=secret ``` # Python 2.x ./deploy.sh remkenv py2 +./deploy.sh envprereq py2 ./deploy.sh install pypitest py2 ./deploy.sh test installed py2 # Python 3.x ./deploy.sh remkenv py3 +./deploy.sh envprereq py3 ./deploy.sh install pypitest py3 ./deploy.sh test installed py3 ``` From 4a2f7adbdf1b144de484f8da727d69473c3a2e10 Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Sun, 30 Jul 2017 20:59:57 +1000 Subject: [PATCH 30/30] new version build files --- dist/pygcode-0.1.0-py2.py3-none-any.whl | Bin 54139 -> 0 bytes dist/pygcode-0.1.0.tar.gz | Bin 36092 -> 0 bytes dist/pygcode-0.1.1-py2.py3-none-any.whl | Bin 0 -> 57407 bytes dist/pygcode-0.1.1.tar.gz | Bin 0 -> 39957 bytes src/pygcode.egg-info/PKG-INFO | 219 +----------------------- src/pygcode.egg-info/SOURCES.txt | 1 + src/pygcode/__init__.py | 2 +- 7 files changed, 7 insertions(+), 215 deletions(-) delete mode 100644 dist/pygcode-0.1.0-py2.py3-none-any.whl delete mode 100644 dist/pygcode-0.1.0.tar.gz create mode 100644 dist/pygcode-0.1.1-py2.py3-none-any.whl create mode 100644 dist/pygcode-0.1.1.tar.gz diff --git a/dist/pygcode-0.1.0-py2.py3-none-any.whl b/dist/pygcode-0.1.0-py2.py3-none-any.whl deleted file mode 100644 index 1fce84d6f41c6b9719a457c92cb010d8f6e27085..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54139 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

s@e1@C*}&~6Z%Pq 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 B-k$&f diff --git a/dist/pygcode-0.1.0.tar.gz b/dist/pygcode-0.1.0.tar.gz deleted file mode 100644 index 27203aef0526635f739e2ac3a699299243224f2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36092 zcmV(_K-9kR1Rj8KOsx6OqUmhX99&*~@%i7_ zSSy|XPPgsM|3t_XVd=ebrg-xmuBPmeUxV5NbHFA($d*YG!2L0 zG(2A#M%f^ZC(}3?uUy8X2r3-E*nNKRqM2sXrBOVH##z*tC9hxYz4+ne1ptVyuKMx# zGC5zGhFATISv(p-IsE}}v2Kh0$lj0pY4kqM06u+O`sRG5`PC`R{|^j;H;8b8`Px_y4uldS_G3|JvGm`m;Wq152l!|5y&y`Jbm$x#}u?2abap={k*xOEpw%$D7STdqOL_n_}k!y>xn z4c7_bWH=ijeO961ViXaSr{VZsgcr&C=vnh#LmB2!G6AHTUWZfhUeYa?z|hlZ6opw- zcY!=^LfgkK5Fx9JARbSn@h}>S$qc^Ti)kXJQ8tCjlTmVyb?Zz0zU->s2Ssa{*8TDl ze4fVBQN$mm2v~-%hTg|z--lT|5LYW$K}^Cli_(U`j#I#VihqRTp@_yx9geT82UAhlLnDb?CPdi}l&pC5^FG6k~SO;-?mnyY?)kWB8=`09Gf zmG{)2A{f*~2gH^5(E7OC2YX!dgQ@d#ypeCOGo*_oHO+ zj=$5dx?nH4L1y71`3C~cCL`DpMkb7(0SB&!zhNaLZRZyL$f(IQr9bd@`q&x90|2%p z+wboIq8UTra+>{2L(2c;-qqi-{eOzdJxs+|tPI5RWt!Xw$v;i5C}N^N_tOylY<4ji zg;@qAVJ5P{cVdzP_Xf4b-~KixESi4@P6{$;6b*yg-~LwnHiQ4v#JA$A+3%0T8)PV8 z1aSpy4-f(ZU5B4#9tQm_5#&F1FS2Abn?}3o;5k@Z;dl@ol+`J(FbrWCzK>o;(a*jID_?BOqgvALhqAxj3|uxA&e!O6r}%j)|S zq$#ZV$?NEHT2ge3qR~@!91i1IhBYb+T}+?HuoHwM4~JSMmCc~A$e?zOaaEbGamhk_ zp2nk*;>q%oz3X`LeHw-D;6r&W;`{RAqezQoSz4@r4>BnpR7_lJG8jpi7Uc0kQWzQ5c{P?w1xbm_D*xfl@%JaiFEG#c#{^|sXfxws8pGgECh>Ua zu)rapo)#N0&+J`?<16@mmPJnK^!ob|=(MmN3M0nCy<|L1laZ$kK>4`UEI1^!)^s!Wq~jueN591l;!$;6d0 zJbU0;Vv$jB;^#$r|EKp~2fjV0Y)YWoyR+(FrO#I-|5cg{kKo@q& z={2YqL$4-+EXhK(@R|4blFuF)gN48(d$Tl+9Ch{0I4*w3jzG@GjBBd$e_2 zioVHk|GbVe_v-;_M6@LqiqhxIxz_ie!x&V$S7THsm(I~bSN1enh|L@ROWB42HC4Rd z5bm01&}3RS1P+QnNSKYKI`;572R|}k)8{2+YjgPp{;n!;!BTE?bDaVIrE1B-hR98D zY(v&JHz4EL9ubx@s<}-L5Tr%k5V<`r$3VoB@NDy$0h$JSLm1|{!b|?O^g!dB+x5vX zr{hAv5zX^EWu4!lTkJBv+o>_&nliQ@X|EdL-m^aH&xWC z+z?cuA+U;oIvV79DM$m_x(lrUrfq|<3<8AE?g{mcVW^gy-HMi`J<`LvE)-yVql(6+ zQvs6*fhcu~z^F_^slp7690cOQ2#fUSHf$KS_`@M>^o0IsQO3&;xm~WAVtcEUaSSIw z4=eTr7ji#>i^=199f=WE6Cg>Ef0GnH52zX*Ht31o-k#IjX>yExZ73G+}B1qRb>TkFf`6zFk1SY=%Lkm1h(pHpE`_!d2!Ni|L9d~LRD97>$3 zJ+9dks$8g2+PcYe3r)nUzx-7kg(+LwS>B0_iO(xbJ(R)MfSd^__aF4Qa!(jl9)`2S z=_Ni0>ZhU?1tFevlHO%fjn0kcWa=@7}RB;DIs?mMYzH#C`7gg~}k{`EQ%5>&=eYg#5XP zNfT)CLo!~Ojbl987HP;HQE?GwaYjZRn6d%YuN%-D`K$cH1QO;b8V?111J)XvSXf)4 z<2I$nfWQ9i(#M$>?OBC}Fdg)#HR^8H?$30V_P7|D;YT6A<}K~63XULZ-V^e>CG*5V z;*szz?n0oq{TDJB)D~Lfuq5H3XLmE-pjVe?)@I zXREQ_1%hJ*k=M}v6Hx7FDsEsZIOIfPy54nVMBy9)c>w52OEVrT4~v0&R)((MqfTRQ zwj20gpaE5yM+vOkbwGPP@eI66V6nnnz-@Znakq+GyJ1cOeVN z&lQe`nVSegL7^HSNDACry))xcTsQ}i|z%~{G z)~x{6)xb6v1GZKHY)u2(S`65F1+aAuY(xBC>W^#7_XK?tlaP#z zToc@IoFi5cNRP`^;|xWi)p)IlpBW>7?O{>lXQ95Aj4VIu*Q080+NfDaxjioLiH!N} z%}-*2-*w|{Ut@XN+v9TG_@|$p##_F|@<6!9<+}0DZ=A-PzV#u`j0tVs^zAR)R0N`>iiINM(o9A(56RU&;r3cRYPp=~#Im4<)IwGykX#_B zM31WgA`ef2)~$SGcC&VQGZoc>N|w`H1c@vxalA_TpvmrXgcaU{9RNr0HzisY5ofk9 zZ=?adPCGK>I$ZRWt>tJU6PzUAll$T^Jz)F1F;j*#*w z=*e2Efbr{*a93gkRQ2pZ8w7_FuBLI zKq;S0-i_`-Hy_5*(W0vKvTd^e7^z_Du{P@@`(MKP~NA|y49}0eEqm<4m+`nNC%}>(jZhW#7 zVe`B8P#PZ#c7au9Tdz)$VR&05xw>ESSy=&Qac=IKUoC^nC~%Hvj1qnFVt(`b-|Y%s zFS=R9IG`~;``t!!E41g<=*+From*pVZjJT1H8$qf*qmEqYi^D0LJgE`g^$wJQTQ&s z7=`cBK~eZFeGi52(w$KFE`0^o_o@9?rMxQf@6D@WgK(Gg98=zCr%`(FjEctBfkhbk;6=;jl`f8kB8sF_uOtU~AGC3c4NA-Rz$OZe@$tXY@$@$Zc zvG&|FPcP{3HLz@9`rI^)y;qS|Sr&T{ZYV%%UK<_&bQ^I{P6GkDtFdrsQ07`{B*& z(^q?k2L~^HIPL%C@YN4gw%ioU;*mgOK1xM=DQ;$?X*?N4Lb6jP!W07gTz3h45`l4%jFNF+P+TIt zyr-y@ToR2KIY1f1VBWUHFCFon$P$oE*BI+QNfRPzZP}VBKBnD$b9&f6ezE`JEqqEN zyjn7eM^TX0{+2!d4*nPX*U?iXdTMe86UTUJU$eM^8^-#NVgk z;9WG$K5@W7alCbVyq$UD4fIgY{^xJ?^T+kS)gLh4fQMVJ7_S@#bnJ{77KJ=+QA{GH z_Y+)o*l~WVC&2&o4US)4<}socJ{6a<@j!)W(Ji7uf;nHH0G)7ZjZuT%1S5rohS#HC zxgtq;f!X@FDvuCD263sv6a>h@Pd&X2qi6MoB_p27UW2UutX{WpR`~F$0iu8<6)7L$ z?rfT@3}JH}*d#%z@k$KBu>}Hiqny(h!UQJ@KIy?>7Q!^11j~OLFV_M1G=W*e2qZB{ zkUlXCK~Cc!1dR%l8kr;$7s>FRF+-2zV3d*1k=>ETXkp#wzD(d0pvAlBerFWkTns}o z=!rp-n9<-KU=(u9BDUEy0MN~xLz|#R3}a9*0zE8AL;OMc$*p^qm_Zb&0Fg{1GOCAx ztXjA0%2Y3uc@Yu7+12Dm>FHKh6mQ03P;{n2tHFIWuhL{T2`DQ|tzJi{6A-tNJaM!8 zJ7(hR*<-GY-$&zo{tC^^nbp6a^|*JsITO^+#S^29ivWe7-aGe6;+*w>?pB2hbUi6v z+=D-+8eO2OjEj#i^#Z#MGv2mLw(P?Osn}XhnB8$c7pjHaxa?|8&u+>daaFHg0K{F} za00UzDcB_2=M2^`LDc_9wE0K=Pp|$jFUfv&{lB}}>9GFaSp&Vlvqt(qeELKG{~dnh zCOElQM|Svo19X*Wg1;@v@)5ddKoig>ds3Of%fm|*H---mpYOiz?;jt&IqDzm9yQEE zyGMc?rDh7S1^vjmxn6FnKN4@IF{n(j1Z~}21`ECPDt5^oZqF@iY5U1a?f7V(>CVN z*&LRwi{0&@KG6`5AHTZ|(<@VKUjf_Dx4t4=1tJF;1@ zH4UZigV>x+F!6dISu5v5`JK7&@#6uVlNqds9bj+o>(~nyH^Fkb$pXjXkbEaWQ4?+R z!T0!LHihZhkEW|9GWdnpf#zS;GP*Y)1Dn7HYlL>UQqMKUdIk;7bAmG;X%t?hX_5xZ zwGUt!e5?sx{Nfta{Ba^eRZG-90F;llGXGGvm}3ZyMEGCs4YIus#gPNma0m|}fID(v z9{R&rwGIr6$sKBzF1p&cSq)ZPOi~1Msj3SnU~^wYIQzK#aPlg|g}n|fY;_LO$-O}$ zR7OfYGxikFLf*j!LB1Fo6u`8TFIZ%9`ipwaG>g9Y#|*|gHT#bKp=Tz+^IdyVbRXh> zxVW4*UxuSBsuH4?mPFZ+@aRvETr4oW(Zrs4e|PwEM>Zsoibqx~Z^DEU0zr;ieL-CA z6dndK$5AOUB@pB(Iio~*iJ1~1X*|6KJs=(!K*Qniv!|$(;i<0pHWmM|1OG+l&iSfg zz%vByIJ(vLxn#q-B}qwC%UY61Had3M*}HS`#GYIDR3IF;u_VjvqKYs%@@k)c2w`v_ zAvC<`Nv&cmE*hN98lC(&kMJq%DXRHbZm zhvJScxX;C7+35n94&(R#N=#Q5!L;9>rn87J1qc#nSja~lLD~gHhTnb3CBIVX^++ul z#G>40WF;_j8RZke`RK`1(0cps(OKT`{LEuioS#uqk$h+G9L>nowWNB42)-gf;=4)!x?5ZMTc-J~ra4Vs z-FskYNAeU5Ri6>*9+)N+RRR2?&0S-T7urQ(kxIWfOY&l(JjW220P>$a7mV-D2mbd< z&4z@Em;?q{yyvv!cd==`yu3_b@en0cd!jn+q8xy;yS*Rw#4s7m$b&@};_=ue6BC`d zNASie9jvtsvw}^H+;#XqLT`0-gwO`#K{H9ORsmwRdOf`vt+IDE0Ri=@`Pae)<^~pc2KpxqGdR=vk}oLA`n zX;I8t;LhT6I;nM*m$5MNcC)mv+v3r>aiELY-LObx@^-Wc00Ya^KaJ4a7pC{-osW5I zQ>J&2r9m3WByX5@;LZYn5N8?ACpj5;)`D;_pmALxeu^{oq`nW+7~j6Iy-RdE1XEI= zHwBD2=n@AQXuJ$%P1knnUL?uLtwm{Lsw&W}7#?U=)g9Ht43Q#Wen&qDb9)0vKL*uv ze1(|B+gp14kKk+3)67#(m3MdANn_=rn# z!Q1^PeiufIoxV^S|Ftm3OcRG;yC5nU1{9V^FiF74t`9^AN&j6vo0z}_gEegD%aL4C*2BR5?2IK>^ zf0@RzE$)!G z^HBUrTt*l~GHhxj??3ndABA{;eg+c%%Fe>}O#J7*^WkiNueaZ#%rKZp0I!N-B23Jac(5)Gw#8{n zyljb+*12w&MwdO|dB^K&9EGb_fbQyT{4QQa#8=+8o9z{q*yqvJ%E}5Vt}7gOz%Pic z(EM8mYsl|-?pCYmwX!d7!3JtS1Dyh|qU76_%7YM4hJk)A-^JTinfAb_ER%f(YTkRW zNz0s`6RCkTMGT*DBVPvLGaW_Cv=B`ooXa8z(?LJ}`@4P)46}9876Cy-`e*MY(*DzS8rkyfV}h@P#J8f zH%6IEK^qL{0$g9IQGE=T#33UK>1)$wJHCw_OhFav^W|WvKT#_w;qv-2-%yb6Lvm~A ziMCNqrV|Myo6C_#b^;NTHgcvjzNFC4@VbO-h1d8Gtm+5y!n>+YI*m~*Z_5s zQZb&M2+#`i;**x};9^xdRaK^xvPPC5bLXKDB>&Weg61IODWo0&5^)e^c)m$73t7IZ zvnXN%tWObo$P0WIdqRfUY{b%b7=fUWL2w1@%=H!+@UjxMm@GNZac2BmWWz$|9nMSe z7y~H+>r9j;m7_3Z{D|R^&<*9GBxi|7YuZ+N@`*6?VUiz4*rB9ma2vzsfeZQ~%4wQU zl#H6qyXxtvNeZCQv4H@J0f(p`p$~I70~nuqlv9PkR!TydSni#*mxd%PxvWp!LyqQOMZ|^9X0!SED;;G4h%4^nrY&+ z^a-cbPUKU$wrq{eX+LWJHb&s&tCZl)|Pe(u#Tu0&XeatV97MliX#NoNpF^4HRY%$7IB|#L0 z!{TZJqR`P>?yjX4GFHwL9$t3J#|}^(WkUnvgCcpNCmsAA1o-^J6e0hyBYb3iFgBp} z@&WNwP$U9j1swk^7#O!{0xCB3M+c4u6V^Xt+Rec@671oT4MlsNWsJv|e=Rp2)4OW! z0=aC@Z%63s0k%RQcLQgHGWH>;*Zpw_7IjRKTb#8Vmu5J@O94SOgt{wla{!Cp$FWXR zuIk3thdmdxiHDvAF@VqT8ps*TFN67verEA9yB`IBR8oX`X(z(BxChdGHi~aRvqy0o zO~e%M8j)!l-@tMQOCGsJovN~3dOwkoX21$B`g^Z;PcS@D+ngt-yQleQ!wqG`^r=PQ6wHX}<+teSGbIE{2cz;32OP&t70wmFKXbbMnTh+BjsK#59Lnnu#$ z<)W^;2~6D`qeVg-Dp>A(!VYMgmjQya0{&Qx7tJKTdY7~#PAsSk&p?6Tq{T?B<|2~w zg8n?52quMAxPrpIYi)veOu;*L2ic=;6-EUm?f`z&K9hz!=}8#6?3^W86p`jX zLG3XBZSfcFdF2^UoM!qlfPJ1CidzGzi%}D_nqX|tyeLa58@fBeY%nS?iCP=i9OUSO zdR5v^6_2UynARk=xRJH`O4!5Z4tex1RX?Lzy(A2&pq@!J$DUndukhZ7FiCf0=}Dj9 z&~cks(pfjc_$k8)#6iz6?vXs^)a)gF)HZ*Ws_%3+*xVT((ebBXidwefBg~p<8U@&` zW<|r<S!@L5pFE=K(NlAhca~2p&meyur;3&&%*Rt6@Bp2j6t8BBsDA|K({#!?_Jv z8AjhTprTGF#47$e8HEF4R8MQw3pPaS0v{SoX44F}VI@8g85jxE?nUmDB_wt~ljAs?!APq@ro zxG?Lcgv=Fh9iU@bX;NL+XYZnx$oGrwNU9xQusQTK$>AFCoWK!vf8Mf-RtmV`O*aFi zB2<#0^_b5ge;wiOz2q{-VfsDBD|NZIb*puvx1ntOZUxzvvofq%WJsj^XH*~#VT+U7Ie_`S)qC3GdhN6~R5lX-|D(^G9 z!Lmu#A4a2T=!OCA7?({n#zoT=srzIn2V=V^^`Qu!OP1zBF2w&EE&%w|SFDUVjTzZ$ z5!08yR)VZF89=~DiOZfA3?)yDh}ZTRz# z{13ld{)ZckuaNl&K%ilQ7<}J7gx^B?JERXGeCagAByNc8A1PR5gD4*Pvp=}$d7Z?u zW+GOcTq2u%g6M8f_ znye3+@ZUMcY-wr9tF7$dYolO`>~|XbUC!hI*6v% z$mTA;d9r#Z0pYKI$-uVy0{p0+dbvJ6zBOGDg>l>qv+KS8W> zMUwAGm)#+`3Ge!3qbd52@oa9?D4rr?Jl>>FS;HFgj|k%-`Bx6dD`}Qeu5qp^ZxCEZ zqj&%|mxQPO1c-&h4uv6%MgQ(tR|e)#%ly;Pn)5M0J>xH5HGHIKCm*S=iVQ;Bv4~Kt z$m5sQ_>W>GB8;p;{*1a!aR5L~GMP;$x5> zlIbf9AIFU>8p@a@Jncv{=F5f`15q{!;`1vo9de0=LE30-aH7X)Vj=+(d~kGle7gI? zX^#(8WWShYUJUfm>4=yEx%pyHPO^ppEN}~10*0fT1Y}}3x()9$bO}GrdC;g_|9sk* ztWZuH+Qm4)J|`1u^BK%13EuyUGXfJX_94Xn{Vc=zVBIQRJ1S4aBjN0 z!Euw}V2TRESobkfs>zUkwe9;@hF(0uGs25#K(El{ngn{VNSDCC%mLo77!rj(GiQr#e31%GngF!Qz~1QUnCrmDt0fa^0Ir_QGLgJXoJ33a zCj5IM^(K)`(}>f_8q>&E@?cT`-3n^Vy#l|C2lpc*7jV1th0@4WUWq0kTvTlY4;OfC)tl+9HGh>K_teycs3Fb zyrG4^#L;M&dzyo%tf%qylxGd`6qPag7Y7wsyNHq=CbtoUzP#YFQ&eDAikhfy%VW#i z8lal27^8d%>X;jauF;vaP(X%#sXMCPO~rD>qn74M;K)$3i~8~t3n8PCYLYj9QrV4j zVclI&jz^eFq@V@qghJFgnNrt1Z3Ucct66HVWOH#pwqSchKZ~|m@u)WMW5v_Ss^~PG zVCneM9@Mj)f>0^;LW!Cws2bm-Y!hp9UWE*Bocf~wK_OM!%7E_vfgL}(mnJXCO<&OV zQ)Fu76=?($1myT<0&MoDgE$?G@F*9nOcK~Ep1G&NKVWWWU5s&u(mfE-V+VX44R1H< z_ixqDKcw}OI~bbi59g!NK8AV*MAaQl^9BWg?yM9nO8abJq%FgM`*>_Ewz}e2@3Q1k zJ<&#)bzY43<}NQ`yG9cqNRD?+5sez2n->vLOTq%N<1-eY0A#(CAL9kJ)ZT;gUD+Kg zk5rBMiMLaG((XwR2HLV`o8FyRMhy63j5DlF4wGLvs>i`67Z8>?`$)W2yrr~ZD2F|L z%7^*}r!AEs>RA3y3L-BLGB*83uSmxViY_H9!$~^T?;aB?)3Xfu4uIO4e7wV_dsulM zSMjWW7_FcX$(>Rwg7kR2#floCT&H-8c!ci@;bOhPSJP7Ks_F`0gRd#@8>M)Coy=Xf zE@Zy{5yk-B;3|s4k=q(RlBcf<00puY006?4wW;4Np$m{kwG)&zQ8p!~I)-b9S&V_e0RR8b=>|cKmSipV>up-*?Mz1!0a#Uv(ixOSp|ITaDU6QM!@ac)WN`Hqn>Gi?> z4lB+w=QT;nrGtOxg!NXr9$ynju~lv^JjPklhUOZ+X<4a5&sIAasXmQIpx`nCM44Ij ziCOhQ>vV6FWO4_x@Cw*Bu8wJVHSlpzOj-i178UO&Exx(|_yE0mm?dBYRvQLAY8DRw zBbX-qlw#ZprVzuFJY&k}F-8G3h)huG;*N4A5%Uv)>3%gf)+s>{lZ!~*6Z^McphL&r z&rc;R3&~u^&5F%cfvfvhwJ!de>)9QWfdT02(9E~6)^OW>EIRc$V!;^W*Ow4qcO*}Y zkt{ub@pAXg>(l=0UA&_8=fme>$CWQ;ouk*gKfF-SHdql1X07M1PEPS!ovP@K>N4u@ z9`CtLDuN8?Z8GiO?Ze0@&569wz)q0~Muw2#C!a0gWy{wg`IG00FA5#HO(h#4Sm&Fk zm0mhKt!Ar@uapep8;pcS+b-MbI!~tQ@L)k_?KnwRgVtm`Z{&0 z*yK`-)zcDP_h!?ILd`MtQZ`M)dzLo#u6j92LVGf7HtiW_C$dCviMUDzLwQz)2^BH2 zo(@AAm<51NMQ(siu8`rRJ*BK#d~YnyhwhRN7J>axA7?C(n{cL{ zGBcT|=+(ALcZ4Bi%n}8QnYI9gKU=Ly@JS~)G}P=+Y@8Qa0F;2sVOVTcgku+5unc(_ zk#MG1kwAH-On|u;Qv*|PBL*f5G&})J3aZ6KCh!6e6%p1`)~FCab7HU+9{Kc} zNa(K>6I+VKLqq!NCO`P`u}Vyw%($2qUdGga-^?<)Rtn#j^CuJr;zY;cAW(hwp?IXp z*}07dFQhNh4th66UpfU=hS@?mcz&@LCLA3JBTS5XuM%Ndi!>S!`C>NZq{8dNzr~ZF zc6a|~ZqN{;!44V`ML5v2N>2Xxu??H++9^SN zBSt&x$quOy>45KsrSc|B=IJhtgQ}Ssj`gN?GEzOzq7H4*FLsiBB??vs0>Rf`wGmyt{aJ0trYR#BW?=UIBmYn@G!>38bV`En5k zqRzJPEro;V6A5`D8fX4(%1Cfh45&m_mZN7f9@AwJV_E}EJPE*EOEkl>vOFy=QW-m7 zJTW1ok`%!RU&`XMY;|??*Uz$R{Lx9Tg;z)qlO@nv%0;&D)fmBmjBmPdvMYF;f$kHb!`~9hj?! z;FTLPJl7{Wlr4nnI zg^7|r zLw>^n#O~d_nY;P!zCY+#3TyKpGmsmPMNqy67)=d*)oEzTRI^zSw!yyW)JdM>CAi>m zjzshRt}gG!$TZ)HWMw#rw}P zuqMXgO_EWlH)r?ChAI5;KtkJB!(=;rP$Q zH{;BpirJY_%b28E&$@`^)&b0P4YU>Aa-I%d#l5vv%eP`#N1Bv&4VpDs!MUqYvt|S8 z*cZKu^%!I0FZrOfL0`Q1We^&aa}V7$)bnTRt?-Klx9qiOUg zKLU}?oQr#Y>?0iVV^`PFjl8ImAB<>vmR-?(GhW$~Hk1D*t~wJq+1p#>XcntI=xi1n z9KSd{-rcj>_-{+|!7N2J$CsdSP^JC=YX$O;!WpeM&$4j{BM)NTgV{8~tg>^?Wz84l zcQ`$)eG+>jQ5B4xAXND*mSQ_D!Ym#rsfQ6I(9w8mox+;q>M1z-EEeO=xDQOj7Pz$g zH#m{~9S>3Iy<$p%tHuRuA(~)9Ed4Zxkr~)`^ta$~on8%}d|qcRlpKi3bwxNsEF zolF=xYwZ|JmP>VGZb@2mT5aoQo~g?ae)@uB8);%KkLGK&JnNi-+Ag$|tm_0oP3SU9 z*-@kCl9Yi#-OY=bhwMEE@phfLH<>(3l#jY0-QFitk4^LfUtdO6U3p_4jw>BoxH5Mq39XU`0 z5?=(@5eDX?Q^4x8UQOR;W*PKgsNa^`3 ziB~6b@ur&Cw^pw)MJk3K`0iLfSH3+=_vfLDjmnc9VdpY5bNTC9b0mN}I-~NE2SZ{E zG%4_WfY*=AevpllTZ~^Pevs*2OYp$mCHY#B{~`KyyY}+ zZOvIiy;9@$k(vv!9Eyv0x?EbbWI_zC#$(ocu8#5p&$E=S56E831M|gb!bqxn6c^ET z_&!c%X|E*V+e6W>l93gX!Ih<$Qf}$fCyUzGD+N1M366G%#$FOn@WPsl8E@E23sAz? zfF&Jd^uJV|m;R6B|KwEDpPT!0e*VwadS{*Uf3~~b_QqQKn^p(@Z{v^rpTEbC%y5{h zWRdh(h{}67jqau$`qB_TA09u)H^aQ?7|r)o)ZICHv7+#>73b0?-Vy=7MjyYAU|S8x z^2Jlmu}()Hcx_Cc=Vw&mDR%ViDW#BpR@Xi(Poh9XUAi#&jx|R^Ry-7f*F~~vI1{b#+_5VaalYMr)Xy66k4<}}JC;Q(iay#JN( z020CxML@$DzR$?vjv6FACo#gx(srJoU@a_;D$z#0}8Jo<-HUvpr3F7A$?q}1Rr{&#Z~esY+nY{$}UP@ z4?y%wb1M}&&q|AAEiYA~U);;ZgN=&Qne*H+zH(Wyh7qUI@ogw$R1}( zf@(ZO%h7L>h)$@?=v-o=!h^g6njLyOK_gV=@6ax8>FW44GhUb~bVV;qoq09FyZk{Z zV}NC9_nr0P=gtly?R#QZM>o0WeR^O`SkHkRa(yv!(wb5!X{P4Gv6+XK3%_pcsXn&& zrRoLKFE$SkoQqGK58s@)%R|kK@vUC@KC<)vFQTt>iC*E9`c{vwgugL`lzcG`2lTFl z`YZ=-9mc`NN$%;R34q`EwXf3m_bMXYzQTLV4|1IsGMUsq4Up>XbqUeXt zlJRd*n)Lf1@)QUP>%N~}Cu8wcbm^EjoQ4IU&8#GXaBX=I=TJVUMKsn)$ROY|NU<7KQxuCqTYZ2b$HrG29VYstF^L}tR-dT zy)L|7TxE>8$N&Tk3yeKW6$GT`kh*~A^lo)K2-VJC#%&Z&&Rq-bh+OB&=<{fDkxEJ zy#8C3G03d{;C<%I-Du8om<@}b=cF;6|Nm^CDVP89NzX5^160cY_S!~kbB*8s>29p8 zby_I@yPJQ=|KHR9m)&P9>IcbaB(Dc6c`wft=p|=aXL7F!@%JVDbkN<>!q2DR&5Mrt zl(x?SiI1%|3^(M`Ltb)`2M7q`WGWwbS$ZT+=>RerC0F;H*lBrx1?w#@(Q7F(x$$I{ zPB3kjPVPC1FVZl*2bqzq3@|n25E?FXwiq!?XsZ}U_-bO9#-n=zrjngYdj;#W(HEy= zhcoZ2tzGt(D+^t}wTwNhDlq;7WvB&5`;~n;< zIK>3+coxPjt|NklsiIO$n>)Um;oV8R10e||5lAjBXW4-7z(c3G&6ri!^xlp9j8vUYTnhcPs*>!t>EiabZ}DIy*9o97pt{!G7f#4ZHd&FBTx%LEgV zaUwYl3#&+U2-f@LT{NUwm1s4M5lrtVbU!G%3o&9w^FKcP09u(bTKw7Xw2W?`4kfRV zPyZR1<^%yGr)dyD!OcybNeT4AD+xpha?RmGzBH^2yA@QE zG2iO7Yz={~mVp!KafOGOz=)3UVWZmhY*Pkdix5 zuoQC_g42a#zLXW;z@8Y6BO<7p?o-N^Kv_lC#g#MbX>{2W*VE~ww~EH~>~1g~G?Vmd z6-0TqdOf`vvCg%M8ByNH(QOmIJ?fj@H`$NrKHMnZb?my>7#U7YENaxh)Kh3Yzx6Vw=01W%CZEL6$`YW@#8`yUWRB2=5Hj<>hjsMvsLbSK| zpY3Ljs0v3F2Yexb0CtPy*x$wxZW{{$coMHVdjYJ~&4xS+ZKKzh5eTzm6clEw^?I>a znoOk3_PTEUhGd^?v{5f7ZU=ETWa-|F)S~CHJW$&Q^+$P?=bY<;`&a7JCw5E~`jX*!t> zHpRgfD*~V>v(5wC<3Y}PhbnW{322hE*-4<=Hqe8$Ekq-4_$I?;C-WrO{B1XEw^}O) zZRGZ)C8BztsE%hh`r`1T+zwjeOT;A0Ydz8C!wPw8Sj$N$>Btgw{|P>IMVG*jeY`A7LDx{QE(=Keg1s{KdSlH2pwDc5yZ8fNj`K6!XlG3GWTq9gJ8e1%ZfhpP^ShUR~ z_Yy{HHgx*7nWKqpM&H!XRHn6lCi#U*w-pgHBpEXW7T}20wHdrtjZ;T&7N9af+DJ6a zujcQLrq>h@3qw(fUoz4&Z7YDo<)>Ot8Yj{Wlr5%-2Fbb}8A*7lvnfszj2+S4khV%% z2?4w(I{}qIG7~~8gWRKBRc4h|ef)EBi<*A}8&N)aOAQaR4A?LuBzjIR`uAWI4q>l? zMr_VWD-6vFj5i#`11d!KA}ElV(;V+Z=)BCW{779Wk7oy2 z7k3dXJlwkvQ?TE2F@=AjQ67yyMg6_%Q&>QPP++ZMrY+G4#=&|E{?~^8b>M$p69`T%Zm=sV5z(IJ zI=!Eo^>KPBXc=bTocFexSLc$kX-t^aH)M7Bmc>kJ za66?NbgZ@D^!hAolZ!gYUPn=ip(f%+S=lYbs?vU@3R~OgkD*OlI=m*Z4aFCu`#MTX zu(&d(hGCZ`AxL~jp> ztWlD@lhI7n=q6-sSU0?s?;>NA39!U4Oz-ubS3KIFm^1TOnZT$hBT?J0kyz<;u$+J=GD!p4>-3pJWhIL?Aj!(W9E*Bj@y!>af6yMU-A@&>v=( zmrG8}mN_ybrpASY*J|z+NqV^ZO$@}+DEC6E2sl<(6bA18Pa#wAjkj*-WqW&D(uiK~ z#jW)gzd1Z-$D~SZfQSE3OgL_FFYR zC{F1Pn07w8P-O-`ip52>!-Aig5Z|t}n;ifOYv^tzU)^;t&R078u}_d?fbLnZokw!> z#HnCZE^qg&EO8DP`)ofi6gzHBGpU;yDp1Du+3-$2hIDaa z{D$wEqJ4hcKLoC7gy9O?)M z;c~u#ymB#6-y*hMoTuUXXhyC4oCl)QGm^lxcSbSI4&G>J|Yf2%R%0N(h5hJr@VSR_SZ;66AI37Q{R)E|W>6 z!<`F|*n%2cv5-IE?zH?VJF3$${#-JfKLPL z*}L;%ye$r$0%bG0h;G(z!j5R=19oF}WdO|b(+?avieaN4d*TD}-^ULO<>NDd@M+#; zvG`L0x}#aGQKV6}qe+#Q*5`)t&@+@|8{?EknLg-Fq=0M46P(**HX2g;pNOBm2<6=* zx<+J**Uy^eCp#EY1X8T_ubN@~CrL#fhFbbfd*$Tse!I)sd0;q)goAsGx_qEM7CGvJ zDw1480^p;ckyOfESp)!8_I@3DnX&DxocQ^9ZbL+FsfR8sXE@D z72a=C6$7rW=VE(G>tii4t;^v-NSMZ%N>RiMWt3|{q&qpw1*2dCo!r3lD-3F=;hyql2A1f{7j`Y3>>a~$-y*n37hRhe`rkwTQM*UQke zP+J_Q92eynncl_&OxKiQ!fq2WDL9Qz&*gmAmweijRa5H4I=wK@laHya*B*)+P|i*a zf=G&SKxz-dM+r69{3SmM-Fa`^nWNZ~6n3!*-*!a+(&fvsRkr*0I}OPNBEvjXgw+aW zb{JZwP@&CHwHNy{a*Q%CpbO+ssdL_Ee7A-ou)amUH0;asYueGT#^ z<6~ZYAhGlnuMaJJb%?GFMfXeoOG8<4G8;T$&ULOYIwk(OfCatioRnGuIr{ag`&^Q8 z80y;Z6AHTXl2G?ylnv6DP7_K((G|>O(C_CYW1h{v{Kd&_p%2;^_wnLlNWxidY|^*p#N85*tix~K8B z3bUMSATRNc20LVsmWXJ)TJ7A=&v@Ubuw~0$G1lrReiw=5w-gQX%SvZiniG;pA8K#$ zU>XZ+zrb%RosX`zptxONHem9Kkj||iSqn~Py6?t0?RT<3t9od~L=O_R_M z3dRG?tCJyFg9y}(PSBffn-X99HmKw{-ZF|T7w8CTm5dOX_SVo?WQDqGWIVzLu`p_z z7n^3u34fKmD0k=*=2H+txnSi1A#0!q+|-?F39+Zj^(t@BX)T`zuzR&I>D0>$%AKK` zeJ41X2KP+dKyi-OAstxWI9QnIb4a}oDdu>3g%y69GNnJc>CGH+-MOn2>rB z!RCes)tKn1%A=;$9tq#nlobZnGk_9r^FEi1U3FYoa>6LMLUm(38N_oVea!=ZYo{UY zg%;onb|AcLP0pmUENW)aGzaDBr>YCZXk@+ccmh{ztJ^*g)X~baUSr~G8F*PzOs6}+ zTk(tdRqTrI#h!R0eiA?9o2d8@cS1qje5#b;aoQfHuGT+CyT`i+FHT<^pUB|G7bkni zuZ~V%9sU4y_ghr~Zk&b;@eZhu2nvAKn~)kAZ7= zK8G)Q;J@pI;h(5jW#Enr0^02w#ea3HtLVP_@!&d5#`xZmQ z`vL1sEm%AT>Q9s4@ngQCZtE&aOHs8cpKjeg>&&x<8RIrmBDH!3yQ}4E9DmBwsaiv{ z>Yp(HI@Q|YLxWErjFBwRKbm&WT#=Q-X*;mxYdC(uYUwJ7F0UAkY*R%1llkb?U;cW0 zR5K`8=>YJtVwIQHOf&9e9pM)JyZhe^maf&spXd*(qq^IOUoceoFW4wmO^z4uh2G-J z`~0VdW$vLXD=Wq@_w8Xm5-_YDUbw)kR8!G56-e}H<#brsX#|EZ05z3*jDbMi5Dc#= z9;U){m%I|EUlAku-(#BzRKd2ev!7tP`+VSds;P#)Fq#yhi#=iMV-sCz^Up)^cmcZM zBrQ(3D5lUgHT=bJDxK<|>|AF#$x<3JuZ&~N$l|^=SM?Aer^1-5HX zEd3&OO-78Bi9%ZYAnGV1s0@nbCm=X{Xkt4ZNy8w zb!RfQ>Q{|j6ZTG5OZ*HRD=}=kn=fgbrI^72!np6*IHpK4&fgb~=;fA-QeR+jBEhJC zGRjAx!P12PAm?kHag{)+v3L)r`hvsIv$2g-F0V!tPg2?lp=~t$TCyD7IKC4!{(0h20#gp6gyiqjVf7l3l;wg zE8f1nR%OiR_B?0>jxle&Nz#yR9riX`LC8f*-)HT6EdDLmjz0#AH#o8{9;t-S(qhDB zod-8-N^Z>v-TXL{r9)nK{uEt`TOe&o46%! zEawLFFlzelg)RQ>$0N14RIcz$#rHOk8>HmZ@4pIuV@SJHoh(w;2-O?)ABy=JO~jqs zck;PTdQYRLFt8weH0*$)6U0Kn)mhD4?Zrpf3>gSg+Fmu4V%h-Wm(|CwkE*2gR=Zvi z{JdZnde@%p*ru2jIcx?f=2KUR+0d^ntBQQjiJ-(U1a>*z3Sch>ylyn zYmh4(%e7mMKh5(5Ur+#Ouo7Mz z)Q?tMM5r{Lwp$Bnp*rEfxs7JY3zyZHf_`H@N&Nt1+n_qwJnd!``9En$?JqPWT1aXQ&K=2S&$ntTG2L7UO()}o4@q9^ zb5Y#t6@^2!E8|lUESKd@`l2r_%#EB!r2^7M!J;M>VM#$c&LM%5?ZjgpcU$gyc@K;n zoyIptXJ+^2BI)81q51+FEFhU&e;nm~Is!J1$Fu1IJ+Ad+s;DDmWZkH`)3uULkE8b} zuC&jxtkZR~)4Wl2r|Z?agK~wcL`z?m;qt@?I%LDca1IXGuD!j$PJWoin4Cg3C;sLv zP6lZ4d|r1&E|(Q726t{zAJjZof?KY~Jxr$-Ecr)1r$C>BHT1PZ%^WXv$fhQC&f-!j zbI!}VSI2zjHxrAwC_M5y#!mQH?u0G{V0u%`+bXZL-GuKb(VZ5q zEE~X_5fq6iPb~j6BUvjPz9f@5oUkr44#<+<72WmvXYd)X!a1XBgWYH^*HWp42(`CM zPIoXJOfH@6e*B3J78{hA&Fb9SHNB`7!a!%~WjH9oM1M8K_D0VXIRr#VD4dtB^62~d zNtJ21z2PU+@zKFz$Zh7xL7PSJsYGY9ULB&T(${?9ZANFnsoE}7-)ft&&I7n?0g*q4 zpH!|gkBZZFjYiq&0cfL#a_g6$jFkfuL|*nA48tGj>_3&uXS43@=;bI$hUGnN$(}B; z+M-=;`MWy2ye#WxTXuutwz`wc%gSE1tCbitVdfXsnAhAxvp;({tC+Bpn>O2Xb(rV( zU0fLwb%eVJ#%_1`{`( zrge+%jvI+!v1PIqJm3IL!YskSg|^ASROcF z&3=qgc*U*{@`ot={kOS)_rZ$Ak!ZU}v@0i_li8o>ER1u4$V3p*eZwqI#lO{F+26th zjcctHnJ)5^IHkRbcbzaTewBDO(6tv37V!6n@Qs_J+Q&ibEp=xUW8(<{w$C|1L;kvv ztaXA9*I+DkvzaFxeov1fz5N9M%6E~1r}xP$6*6oo9*eiDzi^=4v%1sl*SG4Jlt=jM zTSB9Wk12`A8g{YO6VOMJn@DPpeg5vlsRVd)kc|I6yTWjzy6))Lw-UlQnMOS_PX3{3 zkm=Wt-pbMNeQXLCR(YlIEtqheQAjaeLj_c)iNG5l*di0}<4|UlHXt_y5KP?6vZ;i_ zc@+uNh+fR0)NpTqY48Q_Ea^Ezg$}Ht{_?9u$KYX9;8~)!d5FBh4KCCCKoMB-D>H%M zs4PTV=6TH&^Uwtt3{z8&`yfqI3^QK2#_cAZjpS_-BeKgtZxN2W z(*o-Qty@W{H$N>xsm+2(%TRxQvjF!Rz5V=VA^t7t?Wdm?-~pqzpMGA53%IumCn#r| zmZ!|tOEF*Cd$ovlXdwVbIyG!JKO7wS8Uc_wvE8??GWXlL{+6 zL=W;lo#9i4HeJW8(`oL_bP7!8MV?07H?fBm9!~OIxW*I1LKv^3%jx{?+m+o1BLGtW zbjSW$yA-`++`i}I*Qv&jlz`7cu;X{qJ(!H9qwX^a`nsB;1))?xc~R0Xit{2wu12~u zPqrO}T%Sm60DkjxuQR{fMs$IlhePwH($% zgI}zNbbKDMmLq-$d+adp$?4vh{SBCV9xlBSF!yHQM!`FUjnOr_SZ__;AA0!~>94@& z2wo9+p-$I&_RLh@6|M{--&m{WU-PvzFkctFjP_~KSX+yo$Y=}{cCVxN5!+Yt8BBt< z{fW@%@(w=ii$F0Y!Nt8e_S}}@>JR3A-y2lERnTcIm0i)|o@vy97a{XRd#ktDC?{!* z$x{=)BZx_kQhomMNGz*2F=RXSx+|Npq*LF93Q0LLGDvoQbK8HM~$?<&RZ1)ytfdz<>KOZX}^F8J)wemi_Inb)H z%{jL@r0fs;CPUxa8 zVPm%LE;^qH6RtvmX%L+>U0mwdwZkkDVB&|hnnhk2C~?4(y*RwYC``MrsDQbDwn zoM?~C*Fbxib0#v=uj0O9aZmlhv1~qaueW?&5R@?G#6InrlBk5tr@uFuPbSRnZ|5$Mh?M0C5d?s?8YUI|- zkn1dhT=z4P>sBMTQHET15#-iB6S=i&`P?H>;2?IYo3a*!oQLw&u{T*(sym)*|R_elhTKIf)071cPE5Tp8hVt6{RLn-?L+my4X>j#W^10~)O2V;~6MY+Hn!Mw2LnA#hi053JLUn4r6+ookl~g+}FqulIONswxSZdP=yWk_}RTfI`@Q{DGg^|2r3XukPs zhkgeeVgad2_t5w<3bk?f@*hi%{Pt#PikIEx>D_+2C0@7P=#yhlL+bDpz2>@EtKw;w zie~LkYSyulJob;Sa5Sb`FM_MLb!Q8&)NED9_3S6B2;d0xBl+y+kvxf}=U(tuPPg?r zAl4VrdnhG-tY5=2#=~(Ki)dvg*9J^ZuKtH{$zYlqEaMbbuyCKbe5m2c(HqZ^y6_=1XbI2?9g%ZH|;0W zBwu7|jg_JY%YPp)BVse(;uQSikA5p$z|T-9bzA3ilF@gz79j`_|3UNs z89>5}r_DnWsD|!uD430hAwF1#PXo&5bTRxUm5;T)s)0R>mnuOK%D~8seh&OA2R?v%5MynlE2{IHk5Oo;x6Cf^Vgj|-Pp z-@wCZFU!#Qru(Z7F)XIz-GOITXoOBBUc|E(p|+t8X@{KY|c+{!z{|f zGrqn^v5bV*0{|?6x2xUmqFUw^5Ec+mr>~Meam~C+-)s%;X1?X zB23IVc^cnL;}MAA3bSO1^89DB3waLNr|8NcO_C|URosB_4`yiwvYg9yTKN>yzkiOS zG)xEa0Bj)j3@@e4VTk5or<^kNQY-et)nMo3Uf#>-7Wrsvjz>>coZ$oPVJ4>OZ2S(p zy5{b$??oVA{KZ$9*<`n2+2iPm?3&&l4oA1)eTMnRS|XT@NBG{S#%6R+-rQ(tg0hBx zA4dSBielUp?~(&^(F42WX*8NN`{oq%gF3zcy(6Fb9l+T2o8pEDqj#dAU4uhn>9y$M zR1!lw7(Hn_uO-Mq7{HbatYP45gawZ96}2xg>x!H-D8jjFPz6--K|ouDJLQ^_Pj1KK z%Osno!9|$KPdoCd_(=+D>29Z1bNKo-jtYka3(Y;QCp7aR@$9_toQ3=j_Vw znd=9J0W+c^c7a_Q0Occa3M(8(AFJ<(2T?4?#h@5TJ_c5+nQw9cxTe}4Y)&znAUVy7 z#;YC*$tQs22PW{x4_NP`_z=@G8y{E12ju9FJ@LT^cKi6Z@p2Pyr-#n#)pC~jpGE9ocgCsT1$?;2`5>f_eR`T=$UqYBo4$C>Jqot5x4|kdm9}$LpWDcePX2yI7wdcI8+7QiVQ+!l_E@xvpC+m|m*ueuf z2ijR61=?-Tjp1!L5snP|TrT8`Sv(>nvmjriM{*>>9SCmAKAiHK0x!ndER`fjsA82C zA5&;Bib77*a5YLUU{7=4dy1@XsN6?fv!F<}(q=4>g-)1#j zss#aJzrEx1d}dZX2cn^*S9PP2iMmwgs_3#i93m=e>rxYv`7p3%s|jl~8V`fO?X7|R z*X2__HiMW8)?@=`AyfQum8kfc5|*qyW3rZOby}-6cEA8XG(h9L4rdug9`2Cba5g<; z7gAU8%2AT0Q8r2VNit(5%{>k)_iPR`i@Cda`abF*bMafqxWnDjP;kM4u?xfhj%JFk zDb@B5UY^LgpbC3$#}ihL)?7!OvVY9t0cM>8Cc0sR$$76600#&; zC!VqsVH8S|VFg$(68oa5iCn09ytvl_Uj&yS5Fo9qo^F|z3bC(DHa&C0+QgSUT zGC>AAL6kN?`4qsdgLlAjK+9s>rOHIh;z-@{*0>u@-8XHUmJV$47$q#h=6hMTBH^mvKQaQv$%^;LPT|=?p|! zaQ2i~?pZ_VUtp6uZxD#!>1<4<34whkC7I?-9tR70o*;a&JL6S0&SEeC<@dd0d^w6S z%@ZBDj$!`x|0(f@p}{gb`RB`jp5}RqoJ8S<;R-)1;-uYbwVZDUU2)PeKN~J=xBY3y zZM-2)`N8BzIm$rrjNXOLm$mWyF=Y#CC?aGL40)&+^(AEz8e+v8bb;Mo$AfDFj1)Vt z+9>eEct4kvE46=WF0`(UT+Wz?Ne{w?%07!}(pR`rJ6-3aZSTblkrre$p4~)vYe_B; zs;NZ)aM(L@7WlnMlZ+~ll(aTOmhg9~1Pet9%1nTf9YG6g=Dk0djB!lBA!PF=L(UWRA>PLIt~8rs5G#VzK_x=RYP&jd!L>k z(9rl6KUgaxP*;(USaFu|jQId8O$WiDq63SKTydeY|1j|M3u-!QHc-!@nlxPc!lUJ? zno#WL=B-Okx1;eXmDs3hsKI1+a)1?{kW5o)eDZ7(5s}eMVl~8U3_KKH;Xy=BuAcZd zMT6ADXvx)AvoGOl$9LPOeK|2+`;gH`Ohr3rGdYZc57nc)LTj%sr;tM2 zZE${r2vr`gifb^8$GllZPNzIflXG$ed!=1LM+C-fXTw#-8#I;@2YqqzF@raZ;Hr&CU3KWc3_@82UBeM2 z&n1`y$hr}_nqf6WHcm|E@C7GFEIt=)5M zm0jS|vwBFl|5NRrn8fcB_WGwd1`~*$CIhb5p+yzWTBuRwLpkdi?arOL?Q?s2&dj=Q z<&Fc`sQUyIQEL-qNnjqoWc~0W>!i^rp!6~QNrDgE102dUwZk?NCR^RX7tGx=nCD}$>w}xm7Q^p{0Q*Z-vafD{ifU>C5 zgGDG{G0iw06^`HC*BO#_tXxDmb3?{4A}fzLGrF5ZgDH0<31hp?g-iv^kN?5O9Huf9 zL`v1BB~2CKdi*PPDnkhJBsYPIxUsf=O=ul-0Hab*B~n@}nR?gvG$YN(t4cPWSO0A!obZ}@3=H3G@=rBQ?wBkApQDnOCj%u1TBtdz^D7gj6{dH)mQERgn+3eyVsHU#KVn4}i12|TaVYfszusMIvoYKU*} zf{}vJpyX|hJg(Plh^v8ghMHQI6w4!<)*2#EQ0fiG;YA*$gTv=9`g^Z;Pflt*3Frq< zg0V+xj6Gw^nhH>%q<=k8+uv^0K03#u1QFS^#>?9-{a6p|K@;cG;jml_OEyiCRGXc2 z=rWJ^Dra{ZU&aH@5cwwx)tz3$j(K%m%L>({`>nWryT@q72na@v{5&w>u-mXt2mS*x zH!gOCcNqQf9^oSyC|eAzy5Jj0vOY1%4wKDWsUW1J?O6s81f~M#trJTvylI9R{f8&c zh<8`lnNdMA+WUqPED7Vbkg}c1U?{JEw*sB&`RB4ABkJXNvZeS#GJS=rJ&N{dC~d`W zNwbKjs0m^=4)rDg>sk6%pa_T$)CM04V2yi`#RyNI9oEr=G(7`Fo=_IPtE{O0z0F{2 z>GPtJ^Sh!sXUR`ebaE(5{Op!}I=J8@q^3MIxm00m=VhE?fa)Rs$nOZnA{HAfBk^05 zCf~uPfuy^3-RecYvFv?TMhP)=a2oyAVWR;j6&lsLj`tjkwvVN9VIZp^W_&1zf=elkXlw%S12ylzQzVnh=}?(1DytN4 zVN2iq@$9jwYPt6+AIvgYLe^ZRJQ&&I|Y{@dPMZ<+t%&t|)| z@lCti?smJI>l>T!z0>M!YWK-heDp&XwcbcUml zXBI?5&)`n;4aSwInSbD4*krEAfD$#c0jM@DJ_TNBY9OSqO%Wi2q;l1iS*bLwXd3p+ zih0$lnK!Y7k4&cfCqq#3S526WqRnBVxN50f*C5vx%ZlX(kB-L!Vg7m-a2rH7nhHUZ zjGeki(TiO{f}1e~Khg{klgLj@adPK;YC=P=T1+%HTfF~KyQ!Lh0|FWh07OUjCPYVR z3o%A;W^5{>7vGB@FGQD0c?gi*Y!%>yXtZF~Fd2*8;DD`G+IkO@L3`TfS0*h{9avz> zVq#klhoT$v(gTGZ;x|+eQu)cRmQ2>umOipDQ!6-`^ik?K(WiQK)fze19TFdQCA9*! zNBx1bDJz6OE3#B={RWSzbY0&AltL_>@J%HH!LZKMcSo$x)0b9_-ba)FZOx?tJnXyE zSbxQhG2UBM{3u-kRHz$NlRcICUxlCx2=Sr%AtH<3R^pj}e5|msrvf?ERUjwcGkJ^K z{7a?zpH`J143V)a6pl-K?3CCZB#TYv-GVSJ;*n-#0}W-{roXD>*6gzRV3}Dmy)7!3 zN{KpG(uNa`CSFU{rR9rfB35@=;!bO>A*Qn9-;(1)<;%Y%lTcM;oiY-rs@-Z3#x=ei z0zv?44kYxXkvRuM2Td#EQ9kOqs^>$ILgTTO&F@4#RDqW+GKh`3BT9w+0>=;!{pCAj zrY>=*3o3o2BB1eJ0S~mb@pz8$Gk>RzYcWkmMhE557QvZ3UQwd>r&`d6k3B8=8CFr1 z;f-YMwd~5OKIJICxZrBmWUumT&9KW#YkG;)fhY6(X$n&zH+)U@Y zDfm2@L)VuqgJ8^(*OES4$h%GZ3cziw91(nLrYE=4f+$ikf74P+#{H@yRdff5>^SuN zirq)C#n1n0i)yuHDfd3-+p;Ww=VZFz?TZytRiOGlC`?T>kxhbrWG_tfv2m0y-@Mln z1)n0%oJJms?;dls#U(~#B%}sqLi!ZcxN^=6*3B^wp;=B+mzA?PH!>e@n}Knj5pl_NvU zio80h`SjuB09##E`hXDYO~|koU?}hWcM<6@SpkeCqlPB028t2K1Nj5TKDZTo>4jSz zHEcU{m`MWvvv+)}u`_P{VkhYT;r@?v1O8G_$#>lZ%Gv*EwjR^|PlNrp-dg)pqt$FZ zX%_oG5An&ukeNreAAtVYk=-CYp?(bi#lY)+*+uswIW*+M%CI;F??;c$1Uir?Fr87? zn*jC!uLJ$$m=}Hy86tKLErLiqERL4TD+tf9@ly>R#1gc|cx z?pJN|ir)|~LER~RYqa~{CDj3fKPy)?6X0p|3~zq4=KLOsPRor~#xQ<;bNmukQ*h#( zPcSbPaX|np9|(kpy-V((D4^Nw{gpjj@I0dU_8q&|^Bsy^!CmsOSB?DM=GF~|e3ZA? zB3(h0%Hr@Gb{Vx%U8ZZ(r63}EKNyZqiD90UV8A4l6`^eU#=q{VBirq0M?RyICI=Zr1h>ZPxbeW_?_^SugLcSww0D zm|A|Kj5W`<*)P~1MP9Fow23L^aaRj=Y?&{?{*p<0OxfebgY;k{smqDA;K}i&7kcA?hv)jN+l%axiuA_^^3J`<@Q9h6E*u{=Aq=07 zSRSO;@f{nf2c#qxc=fyYR_$G0*+qoASKpSXxboiORfI`m#+V}wO@~Z<2i9Am=TBuv z$*Z}_T~-`ViVH$keDKx1k1a5c%z-oNi*!VktRnQJGI6ZFRf8^MBe8d# z84QE!BJXU=@8Zyg*tm40itukFhW&dNgU!n41+&E&ONnOX4S%~9oy``6 zY1)}mbOIm`*$@r^-pDY&3n+^6zaF^ZAO2e!{__Jj{NsHzyk4P~UJ&!aSS|&pFDXe0Z;~ z35%=Xo?_J;VX@GY$G+ER9rLN+B~{&&r-8#>=t;WEn>wOW%tMwpHTF$MNETndexL*=7c zosVUrgbXP5i_ih15l_JNfffijnE7c+n;yE83OjN9E6`wpR<5m?BUiTXLSNoP%a!xn zETVUgobDI3pdeBF`yMqj80g}7p&dA2SU7eUz=_>2Ph+*gO;jzqe6Xn5ag1gMHSYM{ zr=0+RJ3!|t4IbPP?(y5c!#ZF$G%p=MQb8NRq(XAcyS7zu8DVT_YVOJXHx~+H^PmgZ zGc(Yu0L>02{sllX=mJ}zIU}(s0hjY4%|s)bLf46@w{{h)UfVy-MN4=i(2kt4fO8bUUU9Rft%8ma5@GO zV?0{U{=p?DAuY@;lgIoEs$^q{!O(*f^(HVMLWe-}in~{kh>T5db`Qo9Q_s+u%J0k7 zMQqJqexP{B;9j88zy82Vf4tQ@UC7|Y6Q|lv=ldVJcSfCfk-qieht~VU!u9_6L+kx< zk$QiZB>G6KOJF1Jhd?()#~rz0r&D1H_M&F4#LmOI7qAUd!K;F95)Lx7;-}N_yyI37 zI6hRDA9Zvgwiuh#`x9tRz$d)6St0hX8u>Etd|XA4C|66>^wKvs%~l-erbQ8GL?K}D zA~vBK!Hk1*GP8d)%F(Q3pa96>Q{$A5p(9HPzZXePt{s)S**--qDRJ4*L}?`QrZ3h6 z&y8z`IpMWf^oBWQ&Za3mE}!V3(@(r7o@PA7`bfr8s`s46ii}k(dQ&u!yP{NIVy)v{ zDM?0J`bJrO|Avo!Pbb}`G@Du-YDwvCs#-*Ox2t+(0OFfno1eZBOS@nMrx)}6S$efp zS}ME4Io>-N)ZLWZCV2j^{6rO*<>?`>hF0N$8i#l)AtiQ*E*I@xRL!5v3O*xm(l5HJ zOQnB@LY~cA$iTTnOE%|j${k91Hb*Is%pKUNa>J=ssPi?m&?tcq-mQUa-J;&m0g!Q= zYyeXcvpw>b(PPzF4FOH4SDizK^^v)mDYH?o%J(~uMn5WD?7N1_S#E!C3Bd; z%}VB5;JN-2PE@mrLy1`q?Rd7OQfV9Y8DDTn7{5&f!W;<}z~&oU4P%^RFA`}|rw)p1 zNlk{b!Q|vWq8hr~^2(@jh7h!Jc!Tk~6)4pj&7x+)K`b3I5L4Y*M4$!OSV|iZAa)1xD;K5hf?L<+k#?^8Dy0YU8s{e+f>j zWhReu+4|jcM-?Fn>x(lDD%C24I|AMrRAHxO1M@+44F z0vrbVnAb;CAEpCtKHy;iTSx2h8n23kwM3?LGM7`$6y2OYO?gsCP)j$D40R+9&m)yY zbSCj5b|45YV2bEngtcV-g)8S&+fXZ%zk@2CeE?Sf9`C0Gs`s8PGtNPks&{xjYb zyQSV!wrQ+U$+3}S!{gAClEM|}CY1_iCf^aS!!Lh6Dc98P>KxRXG@kL;13ib^N<5r{ z%89EUIgQHYM0+Mls7w~&!VeM)AWj+j%xtEuds3=B1g6OF(jFmcAa)bfPo>1vj#;yX z!c10rd^kRoaU~DeJBZRq|hVhx00fYu)V0rZ4i4hk+#Z@LH}s{ujTanbs!U4 zT?+p9$&-z&^B)M8<@_Iy8ym#`v9|svbEClj{x`gTaxyrh?v(ZQ(U-sqZ^C7s|AC*e z_rJc@XchSH2RZ*!9Dyj#f6N~LY~rl{;g0Kpec{~4`9E#^uWvkQ!1+Ho6H<)-V*D4M z|AO)FJ6|U*vzc!_@6SE{o9nUpzxB9P@V`CChts(kaLTI~4aN9R8ULX-rl`G(DuDd) zA7B5qo@{Is2#B|4*7v;^V*BD#rhVe2#avUcTP3 zAgWH_gp;w=z3B6AVS1ip{0nI;+{beG zADT}R`@iga!T<9hpVv-k_w3NF|Kj)*Gq-6q4LGFIHic~l?N8h03p;ST zf_Ds9Zoo@|L5#+}gDw+r@d3L}4p zGc?|TwqVmy(JZIYuo&_CTC^A7K{&#;q95pJ$|^ESCfuI*K2v}L3|ilV;pvS*Bi78b zGhW)+83p1Uc-M6tz%rPflwdS4D;8xX%i0GR#9&}Y!VN@tf)bCs!-Gs`N7EzM{7Jlp z@pSB3ycA$rfZyz&o-=gqXJ?&GJDCq_j5{VA#$aH|hNTtAUU;-}$wdFcfRerq`FTE) zQ$u`T%SvhVuZh6x7!X?jWIsggdPqA#?d42+(LjReYft3SP7woqo;`aea^xXph$3Yr zkxGT%j@$yrW-_8s<>Tf?ECx;_;Rzrr_(_%RUn{ecrUjvzl^%|i!;$++t1&ZOG;C7S z+L*5rxefEiyj^LnI!%ZbnGP%E&m#`T0f<2+f*k>q`| zVSZ>eBG-3YjYceC)BFg6$S+|dSsVG~EfCUT99|DS>jON;0iX<`F|L_YZvtmcA$$qz z+35r2?)_Ec{g2W9XXh-4p|d)9l;%FGdr5ly`IEJ7k!~#~-TcYsP8EZqM|*NYilNux zQEha7oo{%!xpE*e7)q19ONz z=hz57t(mYi0gMm;Ue3-y-pnRIz@{3?Jd+wno2p)*>9uavH^?fvE@<)0*8l0 z;aq0D*)LZCo^x@T1l&P?233ggG7Q{yX@P`MJytRTZ(+RYO{_^pKAh2yrB#SS0#aiT zNQ`QM*YJf6RP4R37YtcP>GEUZK{c}q7Oj@Kh*_pC3fhkeKks?sE=FV)<|1NVDGo~t zYA#|+BNIChRfcgtWZ+RnR~(7hofUx#>%bTH*%8k4R2IG^R!3|mznEcKv7zD&>~oA? zT0_$hTZZQtQQVxFGPwIJm)#}d3B9+JL3P|T&1s8uy(XK(1NKkDd}^K#?9143AZ3PN zuSwBoOlg_Bkjsgd%Zxneh3DrqD+@04XeP0e^F+WUP`U8DDv62l=YAY)3!0PlHldKUL>kg!Ul?WWkf{$wS zv6B4KtnAp+5|b{2+`a#d-Mx`1t9z=H?h5 zk!((+ZKj~GGd_i;M!i*xHNLLh2hQveXT?)_IdGx&9Kg3}e9EI)cgE8nm3%tnK%_jw zU<93-7}QFhCW<3s89rex`)>J!)S#eaq9TRLf|4YyW&hGzux0xr*ql#ltKOpO;m~KH zuJ=EabgtqgCcd-*5W2t*)tNiy!n!e8A#5!2QLNpz3lqOXa~?C~7s$_ec$K-oXdu|J zdHHCzeZwce6A%W%ZK^Df1;pHLL)O6eg)+8##@FQ5^_xaIqIA072x9PQ-d*Q&MMG$)mIj|9rNS)$T<*+r zTds4RlCvABQ(-jBzu=7mclmw@UD^}gZx?vefa4H0NF{k%_gg%}FVk@y)aUBhKvKQIk`i)vA4ThOJxirymI-SlIITVl?TcABlDQOb6C(bnu71*ExEDNjTg?R73O6Mk*rS$wEnBY z|6NT~?w!j%h`+}JpG;>@Lsyf{R{8s9nwJX;WHWb9VBN6^M|REgMj=Hf!gB^%Q&X$U z`>AnLiGLhisv{{ds*(HM*?EJqF^54ibIyzC)f(kL*5s}UnCP-2P|fh0JW0+Z&m0 z+0?@?8};;+?ymaL3g-!#x2s&4Q~2d}rIngZWXJ1?IZWgCjs1UXHJH&wX(q)bh6ZbZ zLY-kFDq*BmAfb>k;|1GJ9QaL}^QuN6!6EIJOj&ru=)k^93fcuP-hYEG^CPRpFY6UD z&y=40G?XiiyKKG^`?XNhbgwf=QL2K_MbalJJ_9=4^XKX=XL*+OY$@9#g z$|J+fM#3>9N1yeUX>>Acxu?R@+4Fad)E@MLfsBaHjK8EC%|s9R!|LmX*Q1JD?sLy< zwhq+~e3N1~q09Fn^@HEXMy4TLF?T=#S0T`d6uV@r>5$n}7c)dM6A*;vBO*kcACJBVM~B2>6eC94-(;kA>$UjjoRMFK&h1e$T9yA z055zy+zy;^Scy%i3Q|*F|I~r4^)I_(AZ9+$A#rhLIT;RvVW#}4BVFc?UnZ2uQRa{n z4Q^U*WJ%L1GkPEfKE@ryDE^E31^M?#T~eRYDNEP(@j~l?qR?%Ei1RJ(PnSQ58GBPr zbn9m7nF31qJnucEV;1UXm-PoJ`IvtV#>To|;~TLf1U7etiL5|-I+5@|On`qnQWn~a z^62~rMD+LE1@4W4e6g&Rbu)QkK$X|tBA@hU*o`B*B)=yw^*;_VjP&SsGMwnRPE!Je z=LWXBl4^bcsyGZY17mH0g4+&(_5BwnRzpqZot!3=8D4qW`eDcuxW!f9uhlgPHN~p8 z=Qr21Ie4H*?vlCFI^tPhxYh#5_0pn`0xLi4p@k}Iy%YU4LK(U?O8DPP(&K{sG(r!+5ms@Y_f2Wu%$nDVgoZ^i*qlG4%0WFH-R@C+Yt0T zV3rRvM)Jkueckcq23I?tua6Go`t}UF8gt#`(9ASwEEROHW|lPBFaM%W#85@JO1@>MH(7S~hCzst6$w^6* z;k>K2aSb6^8kdpo3sW%ogA8!HW+2^Gus zIi9at1jum6E8=!u|Kt~VlBQ?c)3B+%r7W!qP-M>5g}=aI4O#NLzCZWyVZ3%BXwkmB z|NI2CTNc{PsQ<^^2rHhu(cqL*5ni4&Z=YgxHi~-YMvwAb4@MEm8u&gx&7t8F5$U-& zm=QtN5hbG0Bc^U)b^`PajZQBMhi&~n;t@kFH5(~UW}Qc+P!iapB%9Ls{^lO{*9Hwz zn#aB0Qvy1EQ~nWH0dx%18q*yWc2Gc=X;4XaAw)x8z1U2$^S))H(lI)_`>Nr*-qBM- z&T@s$X45x8$BJ)foGUMOo>)y9AiJVoN`p=mBVx-GMQM9P7e6JAR*lSnWuOn^%y=I! z2F+^Ktb4dDwV|12;ni`Sb$^4_f;*>>DDnk3^)rbA{iPn-KhH6rF2rh;L86XkY)OH%Gduz zZdGW&?Hf+RoSSqx*M4^Gwt)B32khck{VdWq(;Dp5`_<=F8VEF}jx3#X(8OkkYzt7~ z1K;a+gjJ#mxv#l+eTT&Y^GWEO$ldfv~fb^GYqE&38siw}{T-QE#suh=@;Y!nO z5?;Ax`8sr^EXQvzGEv@ZOh@cH6|erJa2Fo2|1*XRtwl9io|u%A1otyhtkT=`y0=#L zf?mkkl86IGV359l3etuxOZi90%fU5!F)@Pz)SEnTC6`Z`hXMhjXu6m$T6w&Nc-lK0Lm>4aWSsB{<@5mp1suuwx>Bq$N quYaXazcc)8ilx-9L`nR=q*iamDSPpn4Q#ELLJKR-`9OsRQ2h@bm7J&m diff --git a/dist/pygcode-0.1.1-py2.py3-none-any.whl b/dist/pygcode-0.1.1-py2.py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..1a9aa6be1397b70eea7ba9e6115f194f4db320ec GIT binary patch literal 57407 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 Venv(=PoV?=U1R`YeD3GB{{j{Ml~(`& literal 0 HcmV?d00001 diff --git a/dist/pygcode-0.1.1.tar.gz b/dist/pygcode-0.1.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..3fc5658cfc8cd1a6becba27816a5c43f3a39c80b GIT binary patch literal 39957 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 - Usage - ===== + Documentation + ============= - - Writing GCode - ------------- - - Writing gcode from python object instances to text - - :: - - >>> from pygcode import * - >>> gcodes = [ - ... GCodeRapidMove(Z=5), - ... GCodeStartSpindleCW(), - ... GCodeRapidMove(X=10, Y=20), - ... GCodeFeedRate(200), - ... GCodeLinearMove(Z=-1.5), - ... GCodeRapidMove(Z=5), - ... GCodeStopSpindle(), - ... ] - >>> print('\n'.join(str(g) for g in gcodes)) - - G00 Z5 - M03 - G00 X10 Y20 - F200 - G01 Z-1.5 - G00 Z5 - M05 - - - To plot along a lines of vectors, you could write... - - :: - - >>> from pygcode import * - >>> from euclid import Vector3 - - >>> vectors = [ - ... Vector3(0, 0, 0), - ... Vector3(10, 0, 0), - ... Vector3(10, 20, 0), - ... Vector3(10, 20, 3), - ... Vector3(0, 20, 3), - ... Vector3(0, 0, 3), - ... Vector3(0, 0, 0) - ... ] - - >>> to_coords = lambda v: {'X': v.x, 'Y': v.y, 'Z': v.z} - >>> for v in vectors: - ... print("%s" % GCodeLinearMove(**to_coords(v))) - - G01 X0 Y0 Z0 - G01 X10 Y0 Z0 - G01 X10 Y20 Z0 - G01 X10 Y20 Z3 - G01 X0 Y20 Z3 - G01 X0 Y0 Z3 - G01 X0 Y0 Z0 - - - Reading / Interpreting GCode - ---------------------------- - - To read gcode from a file, utilise the ``Line`` class. - Each ``Line`` instance contains a ``Block`` and an optional ``Comment``. - The ``Block`` contains a list of gcodes you're after. - - :: - - from pygcode import Line - - with open('part.gcode', 'r') as fh: - for line_text in fh.readlines(): - line = Line(line_text) - - print(line) # will print the line (with cosmetic changes) - line.block.gcodes # is your list of gcodes - line.block.modal_params # are all parameters not assigned to a gcode, assumed to be motion modal parameters - if line.comment: - line.comment.text # your comment text - - To elaborate, here are some line examples - - :: - - >>> from pygcode import Line - - >>> line = Line('G01 x1 y2 f100 s1000 ; blah') - >>> print(line) - G01 X1 Y2 F100 S1000 ; blah - >>> print(line.block) - G01 X1 Y2 F100 S1000 - >>> sorted(line.block.gcodes) - [, - , - ] - >>> print(line.comment) - ; blah - - - Interpreting what a line of gcode does depends on the machine it's running on, - and also that machine's state (or 'mode') - - The simple line of a rapid move to ``x=10, y=10`` may be ``G00 X10 Y10``. - However, if the machine in question is in "Incremental Motion" mode ``G91`` then - the machine will only end up at ``x=10, y=10`` if it started at ``x=0, y=0`` - - So, GCode interpretation is done via a virtual machine: - - :: - - >>> from pygcode import Machine, GCodeRapidMove - - >>> m = Machine() - >>> m.pos - - >>> g = GCodeRapidMove(X=10, Y=20) - >>> m.process_gcodes(g) - >>> m.pos - - >>> m.process_gcodes(g) - >>> m.pos - # same position; machine in absolute mode - >>> m.mode.distance - # see - - >>> m.process_gcodes(GCodeIncrementalDistanceMode()) - >>> m.process_gcodes(g) # same gcode as above - >>> m.pos - - - all valid ``m.mode`` attributes can be found with ``from pygcode.gcodes import MODAL_GROUP_MAP; MODAL_GROUP_MAP.keys()`` - - Also note that the order codes are interpreted is important. - For example, the following code is WRONG - - :: - - from pygcode import Machine, Line - m = Machine() - line = Line('G0 x10 y10 G91') - m.process_gcodes(*line.block.gcodes) # WRONG! - - This will process the movement to ``x=10, y=10``, and **then** it will change the - distance mode to *Incremental*... there are 2 ways to do this correctly. - - - ``m.process_gcodes(*sorted(line.block.gcodes))``, or simply - - ``m.process_block(line.block)`` - - sorting a list of gcodes will sort them in execution order (as specified by - `LinuxCNC's order of execution `__). - ``process_block`` does this automatically. - - If you need to process & change one type of gcode (usually a movement), - you must split a list of gcodes into those executed before, and after the one - in question. - - :: - - from pygcode import GCodeRapidMove, GCodeLinearMove - from pygcode import Machine, Line, split_gcodes - m = Machine() - line = Line('M0 G0 x10 y10 G91') - (befores, (g,), afters) = split_gcodes(line.block.gcodes, (GCodeRapidMove, GCodeLinearMove)) - m.process_gcodes(*sorted(befores)) - if g.X is not None: - g.X += 100 # shift linear movements (rapid or otherwise) - m.process_gcodes(g) - m.process_gcodes(*sorted(afters)) - - - For a more practical use of machines & interpreting gcode, have a look at - `pygcode-normalize.py `__ - - At the time of writing this, that script converts arcs to linear codes, and - expands drilling cycles to basic movements (so my - `GRBL `__ machine can understand them) - - - Development - =========== - - This library came from my own needs to interpret and convert erroneous - arcs to linear segments, and to expand canned drilling cycles, but also - as a means to *learn* GCode. - - As such there is no direct plan for further development, however I'm - interested in what you'd like to use it for, and cater for that. - - Generally, in terms of what to support, I'm following the lead of: - - - `GRBL `__ and - - `LinuxCNC `__ - - More support will come with increased interest. - So that is... if you don't like what it does, or how it's documented, make some - noise in the `issue section `__. - if you get in early, you may get some free labour out of me ;) - - - Supported G-Codes - ----------------- - - All GCodes supported by `LinuxCNC `__ can be written, and - parsed by ``pygcode``. - - Few GCodes are accurately interpreted by a virtual CNC ``Machine`` instance. - Supported movements are currently; - - - linear movements - - arc movements - - canned drilling cycles + `Check out the wiki `__ for documentation. Keywords: gcode,cnc,parser,interpreter Platform: UNKNOWN diff --git a/src/pygcode.egg-info/SOURCES.txt b/src/pygcode.egg-info/SOURCES.txt index 548f5a9..3429030 100644 --- a/src/pygcode.egg-info/SOURCES.txt +++ b/src/pygcode.egg-info/SOURCES.txt @@ -1,6 +1,7 @@ README.rst setup.cfg setup.py +scripts/pygcode-crop scripts/pygcode-norm src/pygcode/__init__.py src/pygcode/block.py diff --git a/src/pygcode/__init__.py b/src/pygcode/__init__.py index c5ce90a..afb4bd2 100644 --- a/src/pygcode/__init__.py +++ b/src/pygcode/__init__.py @@ -6,7 +6,7 @@ # 1.x - Development Status :: 5 - Production/Stable # .y - developments on that version (pre-release) # *.dev* - development release (intended purely to test deployment) -__version__ = "0.1.1.dev0" +__version__ = "0.1.1" __title__ = "pygcode" __description__ = "Basic g-code parser, interpreter, and encoder library."