Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: fragmuffin/pygcode
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.2.0
Choose a base ref
...
head repository: fragmuffin/pygcode
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 13 commits
  • 64 files changed
  • 2 contributors

Commits on Aug 22, 2017

  1. added pygcode-norm cleaning and finalizing

    Peter Boin committed Aug 22, 2017
    Copy the full SHA
    5b3c070 View commit details

Commits on Aug 23, 2017

  1. wording & punctuation

    Peter Boin committed Aug 23, 2017
    Copy the full SHA
    709610b View commit details
  2. sperling

    Peter Boin committed Aug 23, 2017
    Copy the full SHA
    471aba6 View commit details
  3. 0.2.1 change log

    Peter Boin committed Aug 23, 2017
    Copy the full SHA
    3773cd0 View commit details

Commits on Oct 7, 2017

  1. Copy the full SHA
    4a6a111 View commit details

Commits on Oct 11, 2017

  1. built 0.2.1 candidate

    fragmuffin committed Oct 11, 2017
    Copy the full SHA
    b776572 View commit details
  2. updated improvements list

    fragmuffin committed Oct 11, 2017
    Copy the full SHA
    97ee873 View commit details
  3. Merge pull request #7 from fragmuffin/develop

    0.2.1
    fragmuffin authored Oct 11, 2017
    Copy the full SHA
    80d89c7 View commit details

Commits on Apr 17, 2018

  1. removed test files

    fragmuffin committed Apr 17, 2018
    Copy the full SHA
    87a990f View commit details
  2. Copy the full SHA
    62ccd35 View commit details
  3. Copy the full SHA
    2dd1a1d View commit details

Commits on Apr 18, 2018

  1. Copy the full SHA
    71d3e02 View commit details

Commits on Apr 22, 2018

  1. linuxcnc word map

    fragmuffin committed Apr 22, 2018
    Copy the full SHA
    5577d65 View commit details
Showing with 698 additions and 261 deletions.
  1. +44 −0 dist/README.md
  2. BIN dist/pygcode-0.2.0.tar.gz
  3. BIN dist/{pygcode-0.2.0-py2.py3-none-any.whl → pygcode-0.2.1-py2.py3-none-any.whl}
  4. BIN dist/pygcode-0.2.1.tar.gz
  5. +79 −19 scripts/pygcode-norm
  6. +39 −2 setup.py
  7. +3 −2 src/pygcode.egg-info/PKG-INFO
  8. +11 −2 src/pygcode/__init__.py
  9. +21 −5 src/pygcode/block.py
  10. +40 −0 src/pygcode/dialect.py
  11. +55 −0 src/pygcode/dialects/__init__.py
  12. +216 −0 src/pygcode/dialects/linuxcnc.py
  13. +47 −0 src/pygcode/dialects/mapping.py
  14. 0 src/pygcode/dialects/reprap.py
  15. +9 −0 src/pygcode/dialects/utils.py
  16. +47 −2 src/pygcode/gcodes.py
  17. +44 −9 src/pygcode/machine.py
  18. +25 −208 src/pygcode/words.py
  19. +1 −1 tests/runtests.sh
  20. 0 tests/test-files/{ → linuxcnc}/Alien.tap
  21. 0 tests/test-files/{ → linuxcnc}/Chucks Deer (V-Carve) {3}.tap
  22. 0 tests/test-files/{ → linuxcnc}/Circular Pocket.tap
  23. 0 tests/test-files/{ → linuxcnc}/Clamp.nc
  24. 0 tests/test-files/{ → linuxcnc}/Colt.tap
  25. 0 tests/test-files/{ → linuxcnc}/Cross2.tap
  26. 0 tests/test-files/{ → linuxcnc}/DB25.tap
  27. 0 tests/test-files/{ → linuxcnc}/Disc3.tap
  28. 0 tests/test-files/{ → linuxcnc}/Heart.tap
  29. 0 tests/test-files/{ → linuxcnc}/Horse.tap
  30. 0 tests/test-files/{ → linuxcnc}/Horse2.tap
  31. 0 tests/test-files/{ → linuxcnc}/Letter A (V-Carve).tap
  32. 0 tests/test-files/{ → linuxcnc}/Mach3 write.tap
  33. 0 tests/test-files/{ → linuxcnc}/Mach4 write.tap
  34. 0 tests/test-files/{ → linuxcnc}/Scorpion.tap
  35. 0 tests/test-files/{ → linuxcnc}/Skull2.tap
  36. 0 tests/test-files/{ → linuxcnc}/Smiley face.tap
  37. 0 tests/test-files/{ → linuxcnc}/Smiley001.nc
  38. 0 tests/test-files/{ → linuxcnc}/Smiley002.nc
  39. 0 tests/test-files/{ → linuxcnc}/Snow White.tap
  40. 0 tests/test-files/{ → linuxcnc}/Star Trek.tap
  41. 0 tests/test-files/{ → linuxcnc}/Trispokedovetiles(laser).tap
  42. 0 tests/test-files/{ → linuxcnc}/Tweakie's CNC Cube.nc
  43. 0 tests/test-files/{ → linuxcnc}/Tweakie's CNC Cube2.nc
  44. 0 tests/test-files/{ → linuxcnc}/plug6a.tap
  45. 0 tests/test-files/{ → linuxcnc}/random-sample-1.gcode
  46. 0 tests/test-files/{ → linuxcnc}/unsupported/Chucks Deer (V-Carve) {3}.tap
  47. 0 tests/test-files/{ → linuxcnc}/unsupported/Circular Pocket.tap
  48. 0 tests/test-files/{ → linuxcnc}/unsupported/Colt.tap
  49. 0 tests/test-files/{ → linuxcnc}/unsupported/Cross2.tap
  50. 0 tests/test-files/{ → linuxcnc}/unsupported/DB25.tap
  51. 0 tests/test-files/{ → linuxcnc}/unsupported/Disc3.tap
  52. 0 tests/test-files/{ → linuxcnc}/unsupported/Horse.tap
  53. 0 tests/test-files/{ → linuxcnc}/unsupported/Horse2.tap
  54. 0 tests/test-files/{ → linuxcnc}/unsupported/Mach3 write.tap
  55. 0 tests/test-files/{ → linuxcnc}/unsupported/Mach4 write.tap
  56. 0 tests/test-files/{ → linuxcnc}/unsupported/README.md
  57. 0 tests/test-files/{ → linuxcnc}/unsupported/Skull2.tap
  58. 0 tests/test-files/{ → linuxcnc}/unsupported/Snow White.tap
  59. 0 tests/test-files/{ → linuxcnc}/unsupported/Star Trek.tap
  60. 0 tests/test-files/{ → linuxcnc}/unsupported/Trispokedovetiles(laser).tap
  61. 0 tests/test-files/{ → linuxcnc}/unsupported/plug6a.tap
  62. 0 tests/test-files/{ → linuxcnc}/vertical-slot.ngc
  63. +11 −7 tests/test_parsing.py
  64. +6 −4 tests/test_words.py
44 changes: 44 additions & 0 deletions dist/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
# Change History

----
## 0.2.1

### Improvements

**`pygcode-norm` script:**

Added "Final Machine Actions:"

Final Machine Actions:
standardize what's done at the end of a gcode program.

--zero_xy, -zxy On completion, move straight up to
rapid_safety_height, then across to X0 Y0.
--zero_z, -zz On completion, move down to Z0 (done after zero_xy, if
set).
--rapid_safety_height RAPID_SAFETY_HEIGHT, -rsh RAPID_SAFETY_HEIGHT
Z value to move to before traversing workpiece (if not
set, max value will be attempted).
--spindle_off, -so On completion, turn spindle off.


Added ability to remove all codes & parameters that cannot be parsed.

--rm_invalid_modal, -rmim
Simply remove everything that isn't understood. Use
with caution.

**Library Improvements**

* `Machine.abs2work(<Position>)` and `Machine.work2abs(<Position>)` position
converters, apply machine's offset to the given position without effecting
machine's current position.
* `Machine.clean_block(<Block>)` removes content from a block that's not parsable (use with caution)
* `Machine.ignore_invalid_modal` bool class parameter, if set, will continue on merrily while ignoring
anything not parsable (similarly to `clean_block`)
* deployment version category validation in `setup.py` (ie: alpha, beta, and so on)

### Bugfixes

(none)

----
## 0.2.0

Moved to `alpha`
@@ -20,6 +63,7 @@ Improvements to read more versatile formats
* [#5](https://github.com/fragmuffin/pygcode/issues/5) Line number in program


----
## 0.1.2

Changes to accommodate implementation of [grbl-stream](https://github.com/fragmuffin/grbl-stream)
Binary file removed dist/pygcode-0.2.0.tar.gz
Binary file not shown.
Binary file not shown.
Binary file added dist/pygcode-0.2.1.tar.gz
Binary file not shown.
98 changes: 79 additions & 19 deletions scripts/pygcode-norm
Original file line number Diff line number Diff line change
@@ -18,12 +18,14 @@ for pygcode_lib_type in ('installed_lib', 'relative_lib'):
from pygcode import Machine, Mode, Line
from pygcode import GCodeArcMove, GCodeArcMoveCW, GCodeArcMoveCCW
from pygcode import GCodeCannedCycle
from pygcode import GCodeRapidMove, GCodeStopSpindle, GCodeAbsoluteDistanceMode
from pygcode import split_gcodes
from pygcode import Comment
from pygcode.transform import linearize_arc, simplify_canned_cycle
from pygcode.transform import ArcLinearizeInside, ArcLinearizeOutside, ArcLinearizeMid
from pygcode.gcodes import _subclasses
from pygcode import utils
from pygcode.exceptions import MachineInvalidState

except ImportError:
import sys, os, inspect
@@ -65,7 +67,9 @@ def arc_lin_method_type(value):

def word_list_type(value):
"""
:return: [Word('G73'), Word('G89'), ... ]
Convert csv string list into Word instances.
>>> word_list_type("G73,G89") == set([Word('G73'), Word('G89')])
:return: set of Word instances
"""
canned_code_words = set()
for word_str in re.split(r'\s*,\s*', value):
@@ -82,29 +86,29 @@ 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 when using different CAM software"
description="Normalize gcode for machine consistency when using different CAM software."
)
parser.add_argument(
'infile', type=argparse.FileType('r'),
help="gcode file to normalize",
help="Gcode file to normalize.",
)

parser.add_argument(
'--singles', '-s', dest='singles',
action='store_const', const=True, default=False,
help="only output one command per gcode line",
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",
help="Output full commands, any modal parameters will be acompanied with "
"the fully qualified gcode command.",
)

# Machine
parser.add_argument(
'--machine_mode', '-mm', dest='machine_mode', default=DEFAULT_MACHINE_MODE,
help="Machine's startup mode as gcode (default: '%s')" % DEFAULT_MACHINE_MODE,
help="Machine's startup mode as gcode (default: '%s')." % DEFAULT_MACHINE_MODE,
)

# Arc Linearizing
@@ -117,20 +121,20 @@ group = parser.add_argument_group(
group.add_argument(
'--arc_linearize', '-al', dest='arc_linearize',
action='store_const', const=True, default=False,
help="convert G2,G3 commands to a series of linear interpolations (G1 codes)",
help="Convert G2,G3 commands to a series of linear interpolations (G1 codes).",
)
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 <cw>,<ccw>, eg 'i,o'. 'i' is equivalent to 'i,i'. "
"(default: '%s')" % DEFAULT_ARC_LIN_METHOD,
"(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,
help="Maximum positional error when creating linear interpolation codes "
"(default: %g)." % DEFAULT_PRECISION,
)

#parser.add_argument(
@@ -149,41 +153,73 @@ group = parser.add_argument_group(
group.add_argument(
'--canned_expand', '-ce', dest='canned_expand',
action='store_const', const=True, default=False,
help="Expand canned cycles into basic linear movements, and pauses",
help="Expand canned cycles into basic linear movements, and pauses.",
)
group.add_argument(
'--canned_codes', '-cc', dest='canned_codes',
type=word_list_type, default=DEFAULT_CANNED_CODES,
help="List of canned gcodes to expand, (default is '%s')" % DEFAULT_CANNED_CODES,
help="List of canned gcodes to expand, (default is '%s')." % DEFAULT_CANNED_CODES,
)

# Finalize Code
group = parser.add_argument_group(
"Final Machine Actions",
"standardize what's done at the end of a gcode program."
)
group.add_argument(
'--zero_xy', '-zxy', dest="zero_xy",
action='store_const', const=True, default=False,
help="On completion, move straight up to rapid_safety_height, "
"then across to X0 Y0.",
)
group.add_argument(
'--zero_z', '-zz', dest="zero_z",
action='store_const', const=True, default=False,
help="On completion, move down to Z0 (done after zero_xy, if set).",
)
group.add_argument(
'--rapid_safety_height', '-rsh', dest="rapid_safety_height",
type=float, default=None,
help="Z value to move to before traversing workpiece (if not set, max "
"value will be attempted).",
)
group.add_argument(
'--spindle_off', '-so', dest="spindle_off",
action='store_const', const=True, default=False,
help="On completion, turn spindle off.",
)

# Removing non-functional content
group = parser.add_argument_group(
"Removing Content",
"options for the removal of 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)",
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)",
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)",
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 "
help="Remove gcode (and it's parameters) with words in the given list "
"(eg: M6,G43) (note: only works for modal params with --full)",
)

group.add_argument(
'--rm_invalid_modal', '-rmim', dest='rm_invalid_modal',
action='store_const', const=True, default=False,
help="Simply remove everything that isn't understood. Use with caution.",
)

# --- Parse Arguments
args = parser.parse_args()
@@ -195,6 +231,7 @@ class MyMode(Mode):

class MyMachine(Machine):
MODE_CLASS = MyMode
ignore_invalid_modal = args.rm_invalid_modal

machine = MyMachine()

@@ -276,6 +313,9 @@ def split_and_process(gcode_list, gcode_class, comment):
for line_str in args.infile.readlines():
line = Line(line_str)

if args.rm_invalid_modal:
machine.clean_block(line.block)

# Effective G-Codes:
# fills in missing motion modal gcodes (using machine's current motion mode).
effective_gcodes = machine.block_modal_gcodes(line.block)
@@ -315,3 +355,23 @@ for line_str in args.infile.readlines():
else:
write(line.block.gcodes, modal_params=line.block.modal_params, comment=line.comment, macro=line.macro)
machine.process_block(line.block)

# Finalizing Motion & Spindle
if any([args.spindle_off, args.zero_xy, args.zero_z]):
write([], comment=Comment("pygcode-norm: finalizing"))
if any([args.zero_xy, args.zero_z]) and not(isinstance(machine.mode.distance, GCodeAbsoluteDistanceMode)):
write([GCodeAbsoluteDistanceMode()])
if args.spindle_off:
write([GCodeStopSpindle()], comment=Comment("spindle off"))

if args.zero_xy:
rapid_safety_height = args.rapid_safety_height
if rapid_safety_height is None:
rapid_safety_height = machine.abs2work(machine.abs_range_max).Z

if args.zero_xy:
write([GCodeRapidMove(Z=rapid_safety_height)], comment=Comment("move to safe height"))
write([GCodeRapidMove(X=0, Y=0)], comment=Comment("move to planar origin"))

if args.zero_z:
write([GCodeRapidMove(Z=0)], comment=Comment("move to zero height"))
41 changes: 39 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import codecs
import os
import re
from distutils.version import LooseVersion

from setuptools import setup, find_packages

@@ -14,7 +15,7 @@
META_PATH = os.path.join("src", NAME, "__init__.py")
KEYWORDS = ['gcode', 'cnc', 'parser', 'interpreter']
CLASSIFIERS = [
"Development Status :: 2 - Pre-Alpha", # see src/pygcode/__init__.py
"Development Status :: 3 - Alpha", # see src/pygcode/__init__.py
"Intended Audience :: Developers",
"Intended Audience :: Manufacturing",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
@@ -65,13 +66,49 @@ def find_meta(meta):
raise RuntimeError("Unable to find __{meta}__ string.".format(meta=meta))


def assert_version_classifier(version_str):
"""
Verify version consistency:
version number must correspond to the correct "Development Status" classifier
:raises: ValueError if error found, but ideally this function does nothing
"""
V = lambda v: LooseVersion(v)
# cast version
version = V(version_str)

# get "Development Status" classifier
dev_status_list = [x for x in CLASSIFIERS if x.startswith("Development Status ::")]
if len(dev_status_list) != 1:
raise ValueError("must be 1 'Development Status' in CLASSIFIERS")
classifier = dev_status_list.pop()

version_map = [
(V('0.1'), "Development Status :: 2 - Pre-Alpha"),
(V('0.2'), "Development Status :: 3 - Alpha"),
(V('0.3'), "Development Status :: 4 - Beta"),
(V('1.0'), "Development Status :: 5 - Production/Stable"),
]

for (test_ver, test_classifier) in reversed(sorted(version_map, key=lambda x: x[0])):
if version >= test_ver:
if classifier == test_classifier:
return # all good, now forget any of this ever happened
else:
raise ValueError("for version {ver} classifier should be \n'{good}'\nnot\n'{bad}'".format(
ver=str(version), good=test_classifier, bad=classifier
))


if __name__ == "__main__":
version = find_meta("version")
assert_version_classifier(version)

setup(
name=NAME,
description=find_meta("description"),
license=find_meta("license"),
url=find_meta("url"),
version=find_meta("version"),
version=version,
author=find_meta("author"),
author_email=find_meta("email"),
maintainer=find_meta("author"),
5 changes: 3 additions & 2 deletions src/pygcode.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
Metadata-Version: 1.1
Name: pygcode
Version: 0.2.0
Version: 0.2.1
Summary: Basic g-code parser, interpreter, and encoder library.
Home-page: https://github.com/fragmuffin/pygcode
Author: Peter Boin
Author-email: peter.boin@gmail.com
License: GPLv3
Description-Content-Type: UNKNOWN
Description: =======
pygcode
=======
@@ -33,7 +34,7 @@ Description: =======

Keywords: gcode,cnc,parser,interpreter
Platform: UNKNOWN
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Manufacturing
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Loading