mirror of
https://git.mirrors.martin98.com/https://github.com/petaflot/pygcode
synced 2025-07-28 04:02:02 +08:00
linuxcnc word map
This commit is contained in:
parent
71d3e02261
commit
5577d6560e
@ -34,6 +34,7 @@ __all__ = [
|
||||
'Block',
|
||||
# Comment
|
||||
'Comment', 'split_line',
|
||||
|
||||
# Word
|
||||
'Word', 'text2words', 'str2word', 'words2dict',
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
import re
|
||||
from .words import text2words, WORD_MAP
|
||||
from .words import text2words
|
||||
from .gcodes import words2gcodes
|
||||
from . import dialects
|
||||
|
||||
|
||||
class Block(object):
|
||||
"""GCode block (effectively any gcode file line that defines any <word><value>)"""
|
||||
|
||||
def __init__(self, text=None, verify=True):
|
||||
def __init__(self, text=None, dialect=None, verify=True):
|
||||
"""
|
||||
Block Constructor
|
||||
:param text: gcode line content (including comments) as string
|
||||
@ -26,6 +28,12 @@ class Block(object):
|
||||
self.gcodes = []
|
||||
self.modal_params = []
|
||||
|
||||
if dialect is None:
|
||||
dialect = dialects.get_default()
|
||||
self.dialect = dialect
|
||||
|
||||
self._word_map = getattr(getattr(dialects, dialect), 'WORD_MAP')
|
||||
|
||||
# clean up block string
|
||||
if text:
|
||||
self._raw_text = text # unaltered block content (before alteration)
|
||||
@ -71,7 +79,7 @@ class Block(object):
|
||||
modal_groups.add(gc.modal_group)
|
||||
|
||||
def __getattr__(self, k):
|
||||
if k in WORD_MAP:
|
||||
if k in self._word_map:
|
||||
for w in self.words:
|
||||
if w.letter == k:
|
||||
return w
|
||||
|
@ -1,14 +0,0 @@
|
||||
__all__ = [
|
||||
|
||||
'DEFAULT',
|
||||
|
||||
# registration decorators
|
||||
'gcode_dialect',
|
||||
'word_dialect',
|
||||
]
|
||||
|
||||
DEFAULT = 'linuxcnc'
|
||||
|
||||
# Registration decorators
|
||||
from .mapping import gcode_dialect
|
||||
from .mapping import word_dialect
|
@ -1,18 +0,0 @@
|
||||
"""
|
||||
LinuxCNC
|
||||
|
||||
The linuxcnc gcode dialect is typically used for subtractive fabrication, such
|
||||
as milling.
|
||||
|
||||
This dialect is the basis for all other dialects; GCodes and Words in other
|
||||
dialects either inherit, or directly reference these classes.
|
||||
|
||||
**Specification:** http://www.linuxcnc.org
|
||||
|
||||
TODO: verify above info before publishing
|
||||
"""
|
||||
|
||||
# ======================== WORDS ========================
|
||||
|
||||
|
||||
# ======================== G-CODES ========================
|
55
src/pygcode/dialects/__init__.py
Normal file
55
src/pygcode/dialects/__init__.py
Normal file
@ -0,0 +1,55 @@
|
||||
__all__ = [
|
||||
'DEFAULT',
|
||||
|
||||
# registration decorators
|
||||
'gcode_dialect',
|
||||
'word_dialect',
|
||||
|
||||
# dialects
|
||||
'linuxcnc',
|
||||
'reprap',
|
||||
]
|
||||
|
||||
|
||||
# Registration decorators
|
||||
from .mapping import gcode_dialect
|
||||
from .mapping import word_dialect
|
||||
|
||||
# Dialects
|
||||
from . import linuxcnc
|
||||
from . import reprap
|
||||
|
||||
|
||||
_DEFAULT = 'linuxcnc'
|
||||
|
||||
|
||||
def get_default():
|
||||
"""
|
||||
Get the default gcode interpreter dialect.
|
||||
(see :meth:`set_default` for details)
|
||||
"""
|
||||
return _DEFAULT
|
||||
|
||||
|
||||
def set_default(name):
|
||||
"""
|
||||
Set the default gcode interpreter dialect.
|
||||
This dialect will be used if no other is specified for particular function
|
||||
calls.
|
||||
|
||||
:param name: name of dialect
|
||||
:type name: :class:`str`
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> from pygcode import dialect
|
||||
>>> dialect.get_default()
|
||||
'linuxcnc'
|
||||
>>> dialect.set_default('reprap')
|
||||
>>> dialect.get_default()
|
||||
'reprap'
|
||||
|
||||
"""
|
||||
|
||||
# TODO: verify valid name
|
||||
_DEFAULT = name
|
216
src/pygcode/dialects/linuxcnc.py
Normal file
216
src/pygcode/dialects/linuxcnc.py
Normal file
@ -0,0 +1,216 @@
|
||||
"""
|
||||
LinuxCNC
|
||||
|
||||
The linuxcnc gcode dialect is typically used for subtractive fabrication, such
|
||||
as milling.
|
||||
|
||||
This dialect is the basis for all other dialects; GCodes and Words in other
|
||||
dialects either inherit, or directly reference these classes.
|
||||
|
||||
**Specification:** http://www.linuxcnc.org
|
||||
|
||||
TODO: verify above info before publishing
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from .utils import WordType
|
||||
|
||||
# ======================== WORDS ========================
|
||||
|
||||
REGEX_FLOAT = re.compile(r'^\s*-?(\d+\.?\d*|\.\d+)') # testcase: ..tests.test_words.WordValueMatchTests.test_float
|
||||
REGEX_INT = re.compile(r'^\s*-?\d+')
|
||||
REGEX_POSITIVEINT = re.compile(r'^\s*\d+')
|
||||
REGEX_CODE = re.compile(r'^\s*\d+(\.\d)?') # float, but can't be negative
|
||||
|
||||
# Value cleaning functions
|
||||
def _clean_codestr(value):
|
||||
if value < 10:
|
||||
return "0%g" % value
|
||||
return "%g" % value
|
||||
|
||||
CLEAN_NONE = lambda v: v
|
||||
CLEAN_FLOAT = lambda v: "{0:g}".format(round(v, 3))
|
||||
CLEAN_CODE = _clean_codestr
|
||||
CLEAN_INT = lambda v: "%g" % v
|
||||
|
||||
WORD_MAP = {
|
||||
# Descriptions copied from wikipedia:
|
||||
# https://en.wikipedia.org/wiki/G-code#Letter_addresses
|
||||
|
||||
# Rotational Axes
|
||||
'A': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of A axis (rotational axis around X axis)",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'B': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of B axis (rotational axis around Y axis)",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'C': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of C axis (rotational axis around Z axis)",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'D': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines diameter or radial offset used for cutter compensation. D is used for depth of cut on lathes. It is used for aperture selection and commands on photoplotters.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Feed Rates
|
||||
'E': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Precision feedrate for threading on lathes",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'F': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Feedrate",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# G-Codes
|
||||
'G': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_CODE,
|
||||
description="Address for preparatory commands",
|
||||
clean_value=CLEAN_CODE,
|
||||
),
|
||||
# Tool Offsets
|
||||
'H': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines tool length offset; Incremental axis corresponding to C axis (e.g., on a turn-mill)",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Arc radius center coords
|
||||
'I': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines arc center in X axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'J': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines arc center in Y axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'K': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines arc center in Z axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles, equal to L address.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Loop Count
|
||||
'L': WordType(
|
||||
cls=int,
|
||||
value_regex=REGEX_POSITIVEINT,
|
||||
description="Fixed cycle loop count; Specification of what register to edit using G10",
|
||||
clean_value=CLEAN_INT,
|
||||
),
|
||||
# Miscellaneous Function
|
||||
'M': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_CODE,
|
||||
description="Miscellaneous function",
|
||||
clean_value=CLEAN_CODE,
|
||||
),
|
||||
# Line Number
|
||||
'N': WordType(
|
||||
cls=int,
|
||||
value_regex=REGEX_POSITIVEINT,
|
||||
description="Line (block) number in program; System parameter number to change using G10",
|
||||
clean_value=CLEAN_INT,
|
||||
),
|
||||
# Program Name
|
||||
'O': WordType(
|
||||
cls=str,
|
||||
value_regex=re.compile(r'^.+$'), # all the way to the end
|
||||
description="Program name",
|
||||
clean_value=CLEAN_NONE,
|
||||
),
|
||||
# Parameter (arbitrary parameter)
|
||||
'P': WordType(
|
||||
cls=float, # parameter is often an integer, but can be a float
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Serves as parameter address for various G and M codes",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Peck increment
|
||||
'Q': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Depth to increase on each peck; Peck increment in canned cycles",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Arc Radius
|
||||
'R': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines size of arc radius, or defines retract height in milling canned cycles",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Spindle speed
|
||||
'S': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines speed, either spindle speed or surface speed depending on mode",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Tool Selecton
|
||||
'T': WordType(
|
||||
cls=str,
|
||||
value_regex=REGEX_POSITIVEINT, # tool string may have leading '0's, but is effectively an index (integer)
|
||||
description="Tool selection",
|
||||
clean_value=CLEAN_NONE,
|
||||
),
|
||||
# Incremental axes
|
||||
'U': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Incremental axis corresponding to X axis (typically only lathe group A controls) Also defines dwell time on some machines (instead of 'P' or 'X').",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'V': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Incremental axis corresponding to Y axis",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'W': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Incremental axis corresponding to Z axis (typically only lathe group A controls)",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Linear Axes
|
||||
'X': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of X axis.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'Y': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of Y axis.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'Z': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of Z axis.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
# ======================== G-CODES ========================
|
9
src/pygcode/dialects/utils.py
Normal file
9
src/pygcode/dialects/utils.py
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
# Data Classes
|
||||
|
||||
class WordType(object):
|
||||
def __init__(self, cls, value_regex, description, clean_value):
|
||||
self.cls = cls
|
||||
self.value_regex = value_regex
|
||||
self.description = description
|
||||
self.clean_value = clean_value
|
@ -2,218 +2,31 @@ import re
|
||||
import itertools
|
||||
import six
|
||||
|
||||
from . import dialects
|
||||
from .exceptions import GCodeBlockFormatError, GCodeWordStrError
|
||||
|
||||
REGEX_FLOAT = re.compile(r'^\s*-?(\d+\.?\d*|\.\d+)') # testcase: ..tests.test_words.WordValueMatchTests.test_float
|
||||
REGEX_INT = re.compile(r'^\s*-?\d+')
|
||||
REGEX_POSITIVEINT = re.compile(r'^\s*\d+')
|
||||
REGEX_CODE = re.compile(r'^\s*\d+(\.\d)?') # float, but can't be negative
|
||||
|
||||
# Value cleaning functions
|
||||
def _clean_codestr(value):
|
||||
if value < 10:
|
||||
return "0%g" % value
|
||||
return "%g" % value
|
||||
|
||||
CLEAN_NONE = lambda v: v
|
||||
CLEAN_FLOAT = lambda v: "{0:g}".format(round(v, 3))
|
||||
CLEAN_CODE = _clean_codestr
|
||||
CLEAN_INT = lambda v: "%g" % v
|
||||
|
||||
WORD_MAP = {
|
||||
# Descriptions copied from wikipedia:
|
||||
# https://en.wikipedia.org/wiki/G-code#Letter_addresses
|
||||
|
||||
# Rotational Axes
|
||||
'A': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Absolute or incremental position of A axis (rotational axis around X axis)",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'B': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Absolute or incremental position of B axis (rotational axis around Y axis)",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'C': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Absolute or incremental position of C axis (rotational axis around Z axis)",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'D': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Defines diameter or radial offset used for cutter compensation. D is used for depth of cut on lathes. It is used for aperture selection and commands on photoplotters.",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
# Feed Rates
|
||||
'E': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Precision feedrate for threading on lathes",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'F': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Feedrate",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
# G-Codes
|
||||
'G': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_CODE,
|
||||
'description': "Address for preparatory commands",
|
||||
'clean_value': CLEAN_CODE,
|
||||
},
|
||||
# Tool Offsets
|
||||
'H': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Defines tool length offset; Incremental axis corresponding to C axis (e.g., on a turn-mill)",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
# Arc radius center coords
|
||||
'I': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Defines arc center in X axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'J': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Defines arc center in Y axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'K': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Defines arc center in Z axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles, equal to L address.",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
# Loop Count
|
||||
'L': {
|
||||
'class': int,
|
||||
'value_regex': REGEX_POSITIVEINT,
|
||||
'description': "Fixed cycle loop count; Specification of what register to edit using G10",
|
||||
'clean_value': CLEAN_INT,
|
||||
},
|
||||
# Miscellaneous Function
|
||||
'M': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_CODE,
|
||||
'description': "Miscellaneous function",
|
||||
'clean_value': CLEAN_CODE,
|
||||
},
|
||||
# Line Number
|
||||
'N': {
|
||||
'class': int,
|
||||
'value_regex': REGEX_POSITIVEINT,
|
||||
'description': "Line (block) number in program; System parameter number to change using G10",
|
||||
'clean_value': CLEAN_INT,
|
||||
},
|
||||
# Program Name
|
||||
'O': {
|
||||
'class': str,
|
||||
'value_regex': re.compile(r'^.+$'), # all the way to the end
|
||||
'description': "Program name",
|
||||
'clean_value': CLEAN_NONE,
|
||||
},
|
||||
# Parameter (arbitrary parameter)
|
||||
'P': {
|
||||
'class': float, # parameter is often an integer, but can be a float
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Serves as parameter address for various G and M codes",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
# Peck increment
|
||||
'Q': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Depth to increase on each peck; Peck increment in canned cycles",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
# Arc Radius
|
||||
'R': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Defines size of arc radius, or defines retract height in milling canned cycles",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
# Spindle speed
|
||||
'S': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Defines speed, either spindle speed or surface speed depending on mode",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
# Tool Selecton
|
||||
'T': {
|
||||
'class': str,
|
||||
'value_regex': REGEX_POSITIVEINT, # tool string may have leading '0's, but is effectively an index (integer)
|
||||
'description': "Tool selection",
|
||||
'clean_value': CLEAN_NONE,
|
||||
},
|
||||
# Incremental axes
|
||||
'U': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Incremental axis corresponding to X axis (typically only lathe group A controls) Also defines dwell time on some machines (instead of 'P' or 'X').",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'V': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Incremental axis corresponding to Y axis",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'W': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Incremental axis corresponding to Z axis (typically only lathe group A controls)",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
# Linear Axes
|
||||
'X': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Absolute or incremental position of X axis.",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'Y': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Absolute or incremental position of Y axis.",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
'Z': {
|
||||
'class': float,
|
||||
'value_regex': REGEX_FLOAT,
|
||||
'description': "Absolute or incremental position of Z axis.",
|
||||
'clean_value': CLEAN_FLOAT,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class Word(object):
|
||||
def __init__(self, *args):
|
||||
if len(args) not in (1, 2):
|
||||
raise AssertionError("input arguments either: (letter, value) or (word_str)")
|
||||
if len(args) == 2:
|
||||
# Word('G', 90)
|
||||
(letter, value) = args
|
||||
else:
|
||||
def __init__(self, *args, **kwargs):
|
||||
# Parameters (listed)
|
||||
args_count = len(args)
|
||||
if args_count == 1:
|
||||
# Word('G90')
|
||||
letter = args[0][0] # first letter
|
||||
value = args[0][1:] # rest of string
|
||||
elif args_count == 2:
|
||||
# Word('G', 90)
|
||||
(letter, value) = args
|
||||
else:
|
||||
raise AssertionError("input arguments either: (letter, value) or (word_str)")
|
||||
|
||||
# Parameters (keyword)
|
||||
dialect = kwargs.pop('dialect', dialects.get_default())
|
||||
|
||||
letter = letter.upper()
|
||||
|
||||
self._value_class = WORD_MAP[letter]['class']
|
||||
self._value_clean = WORD_MAP[letter]['clean_value']
|
||||
self._word_map = getattr(getattr(dialects, dialect), 'WORD_MAP')
|
||||
self._value_class = self._word_map[letter].cls
|
||||
self._value_clean = self._word_map[letter].clean_value
|
||||
|
||||
self.letter = letter
|
||||
self.value = value
|
||||
@ -272,15 +85,19 @@ class Word(object):
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return "%s: %s" % (self.letter, WORD_MAP[self.letter]['description'])
|
||||
return "%s: %s" % (self.letter, self._word_map[self.letter].description)
|
||||
|
||||
|
||||
def text2words(block_text):
|
||||
def text2words(block_text, dialect=None):
|
||||
"""
|
||||
Iterate through block text yielding Word instances
|
||||
:param block_text: text for given block with comments removed
|
||||
"""
|
||||
next_word = re.compile(r'^.*?(?P<letter>[%s])' % ''.join(WORD_MAP.keys()), re.IGNORECASE)
|
||||
if dialect is None:
|
||||
dialect = dialects.get_default()
|
||||
word_map = getattr(getattr(dialects, dialect), 'WORD_MAP')
|
||||
|
||||
next_word = re.compile(r'^.*?(?P<letter>[%s])' % ''.join(word_map.keys()), re.IGNORECASE)
|
||||
|
||||
index = 0
|
||||
while True:
|
||||
@ -291,7 +108,7 @@ def text2words(block_text):
|
||||
index += letter_match.end() # propogate index to start of value
|
||||
|
||||
# Value
|
||||
value_regex = WORD_MAP[letter]['value_regex']
|
||||
value_regex = word_map[letter].value_regex
|
||||
value_match = value_regex.search(block_text[index:])
|
||||
if value_match is None:
|
||||
raise GCodeWordStrError("word '%s' value invalid" % letter)
|
||||
|
@ -6,6 +6,7 @@ add_pygcode_to_path()
|
||||
|
||||
# Units under test
|
||||
from pygcode import words
|
||||
from pygcode import dialects
|
||||
|
||||
|
||||
class WordIterTests(unittest.TestCase):
|
||||
@ -33,8 +34,7 @@ class WordIterTests(unittest.TestCase):
|
||||
self.assertEqual([w[5].letter, w[5].value], ['F', 70])
|
||||
|
||||
|
||||
class WordValueMatchTests(unittest.TestCase):
|
||||
|
||||
class WordValueMatchTest(unittest.TestCase):
|
||||
def regex_assertions(self, regex, positive_list, negative_list):
|
||||
# Assert all elements of positive_list match regex
|
||||
for (value_str, expected_match) in positive_list:
|
||||
@ -47,9 +47,11 @@ class WordValueMatchTests(unittest.TestCase):
|
||||
match = regex.search(value_str)
|
||||
self.assertIsNone(match, "matched for '%s'" % value_str)
|
||||
|
||||
|
||||
class WordTests_LinuxCNC(WordValueMatchTest):
|
||||
def test_float(self):
|
||||
self.regex_assertions(
|
||||
regex=words.REGEX_FLOAT,
|
||||
regex=dialects.linuxcnc.REGEX_FLOAT,
|
||||
positive_list=[
|
||||
('1.2', '1.2'), ('1', '1'), ('200', '200'), ('0092', '0092'),
|
||||
('1.', '1.'), ('.2', '.2'), ('-1.234', '-1.234'),
|
||||
@ -63,7 +65,7 @@ class WordValueMatchTests(unittest.TestCase):
|
||||
|
||||
def test_code(self):
|
||||
self.regex_assertions(
|
||||
regex=words.REGEX_CODE,
|
||||
regex=dialects.linuxcnc.REGEX_CODE,
|
||||
positive_list=[
|
||||
('1.2', '1.2'), ('1', '1'), ('10', '10'),
|
||||
('02', '02'), ('02.3', '02.3'),
|
||||
|
Loading…
x
Reference in New Issue
Block a user