From c7578de0d74ee0748f713360083e1f3d4726927b Mon Sep 17 00:00:00 2001 From: Peter Boin Date: Thu, 6 Jul 2017 22:11:20 +1000 Subject: [PATCH] named modal groups, clean words to str --- pygcode/block.py | 10 +++- pygcode/file.py | 1 + pygcode/gcodes.py | 127 ++++++++++++++++++++++++++++------------- pygcode/line.py | 7 +-- pygcode/words.py | 132 +++++++++++++++++++++++++++++-------------- tests/test_file.py | 2 +- tests/test_gcodes.py | 2 +- tests/test_words.py | 4 +- 8 files changed, 194 insertions(+), 91 deletions(-) diff --git a/pygcode/block.py b/pygcode/block.py index 9e4b178..2f456ba 100644 --- a/pygcode/block.py +++ b/pygcode/block.py @@ -1,6 +1,6 @@ import re from .words import iter_words, WORD_MAP -from .gcodes import words_to_gcodes +from .gcodes import words2gcodes class Block(object): """GCode block (effectively any gcode file line that defines any )""" @@ -21,7 +21,7 @@ class Block(object): self.text = text self.words = list(iter_words(self.text)) - (self.gcodes, self.modal_params) = words_to_gcodes(self.words) + (self.gcodes, self.modal_params) = words2gcodes(self.words) self._assert_gcodes() @@ -31,7 +31,9 @@ class Block(object): def _assert_gcodes(self): modal_groups = set() code_words = set() + for gc in self.gcodes: + # Assert all gcodes are not repeated in the same block if gc.word in code_words: raise AssertionError("%s cannot be in the same block" % ([ @@ -39,6 +41,7 @@ class Block(object): if x.modal_group == gc.modal_group ])) code_words.add(gc.word) + # Assert all gcodes are from different modal groups if gc.modal_group is not None: if gc.modal_group in modal_groups: @@ -61,3 +64,6 @@ class Block(object): cls=self.__class__.__name__, key=k )) + + def __str__(self): + return ' '.join(str(x) for x in (self.gcodes + [p.clean_str for p in self.modal_params])) diff --git a/pygcode/file.py b/pygcode/file.py index 9172e19..ed8d780 100644 --- a/pygcode/file.py +++ b/pygcode/file.py @@ -24,5 +24,6 @@ def parse(filename): with open(filename, 'r') as fh: for line in fh.readlines(): line_obj = Line(line) + # FIXME: don't dump entire file into RAM; change to generator model file.append(line_obj) return file diff --git a/pygcode/gcodes.py b/pygcode/gcodes.py index 5caf0ca..3d1ccff 100644 --- a/pygcode/gcodes.py +++ b/pygcode/gcodes.py @@ -64,6 +64,44 @@ from .words import Word # Override Switches (Group 9) M48, M49 # User Defined (Group 10) M100-M199 # + +MODAL_GROUP_NUM = { + # "G" codes + 'motion': 1 + 'plane_selection': 2, + 'distance': 3, + 'arc_ijk_distance': 4, + 'feed_rate_mode': 5, + 'units': 6, + 'cutter_diameter_comp': 7, + 'tool_length_offset': 8, + 'canned_cycles_return': 10, + 'coordinate_system': 12, + 'control_mode': 13, + 'spindle_speed': 14, + 'lathe_diameter': 15, + + # "M" codes + 'stopping': 104, + 'spindle': 107, + 'coolant': 108, + 'override_switches': 109, + 'user_defined': 110, + + # 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 + # modal group. + # However, having a modal group assists with: + # - validating gcode blocks for conflicting commands + # - remembering machine's state with consistency across gcodes + # Therefore, I've added F, S, and T GCodes to custom group numbers (> 200) + 'feed_rate': 201, + 'spindle_speed': 202, + 'tool': 203, +} + + # Execution Order # Order taken http://linuxcnc.org/docs/html/gcode/overview.html#_g_code_order_of_execution # (as of 2017-07-03) @@ -132,12 +170,15 @@ class GCode(object): def __str__(self): """String representation of gcode, as it would be seen in a .gcode file""" - return "{gcode} {parameters}".format( - gcode=self.word, - parameters=' '.join([ - "{}".format(self.params[k]) + param_str = '' + if self.params: + param_str += ' ' + ' '.join([ + "{}".format(self.params[k].clean_str) for k in sorted(self.params.keys()) - ]), + ]) + return "{gcode}{parameters}".format( + gcode=self.word.clean_str, + parameters=param_str, ) # Sort by exec_order @@ -167,6 +208,16 @@ class GCode(object): def description(self): return self.__doc__ + @property + def mode(self): + """ + Mode word for modal GCodes + :return: Word to save machine's state, or None if GCode is not modal + """ + if self.modal_group is None: + return None + return self.word + # ======================= Motion ======================= # (X Y Z A B C U V W apply to all motions) @@ -185,7 +236,7 @@ class GCode(object): class GCodeMotion(GCode): param_letters = set('XYZABCUVW') - modal_group = 1 + modal_group = MODAL_GROUP_NUM['motion'] exec_order = 241 class GCodeRapidMove(GCodeMotion): @@ -281,7 +332,7 @@ class GCodeCancelCannedCycle(GCodeMotion): class GCodeCannedCycle(GCode): param_letters = set('XYZUVW') - modal_group = 1 + modal_group = MODAL_GROUP_NUM['motion'] exec_order = 241 class GCodeDrillingCycle(GCodeCannedCycle): @@ -340,36 +391,36 @@ class GCodeDistanceMode(GCode): class GCodeAbsoluteDistanceMode(GCodeDistanceMode): """G90: Absolute Distance Mode""" word_key = Word('G', 90) - modal_group = 3 + modal_group = MODAL_GROUP_NUM['distance'] class GCodeIncrementalDistanceMode(GCodeDistanceMode): """G91: Incremental Distance Mode""" word_key = Word('G', 91) - modal_group = 3 + modal_group = MODAL_GROUP_NUM['distance'] class GCodeAbsoluteArcDistanceMode(GCodeDistanceMode): """G90.1: Absolute Distance Mode for Arc IJK Parameters""" word_key = Word('G', 90.1) - modal_group = 4 + modal_group = MODAL_GROUP_NUM['arc_ijk_distance'] class GCodeIncrementalArcDistanceMode(GCodeDistanceMode): """G91.1: Incremental Distance Mode for Arc IJK Parameters""" word_key = Word('G', 91.1) - modal_group = 4 + modal_group = MODAL_GROUP_NUM['arc_ijk_distance'] class GCodeLatheDiameterMode(GCodeDistanceMode): """G7: Lathe Diameter Mode""" word_key = Word('G', 7) - modal_group = 15 + modal_group = MODAL_GROUP_NUM['lathe_diameter'] class GCodeLatheRadiusMode(GCodeDistanceMode): """G8: Lathe Radius Mode""" word_key = Word('G', 8) - modal_group = 15 + modal_group = MODAL_GROUP_NUM['lathe_diameter'] # ======================= Feed Rate Mode ======================= @@ -377,7 +428,7 @@ class GCodeLatheRadiusMode(GCodeDistanceMode): # G93, G94, G95 Feed Rate Mode class GCodeFeedRateMode(GCode): - modal_group = 5 + modal_group = MODAL_GROUP_NUM['feed_rate_mode'] exec_order = 30 class GCodeInverseTimeMode(GCodeFeedRateMode): @@ -409,20 +460,20 @@ class GCodeStartSpindleCW(GCodeSpindle): """M3: Start Spindle Clockwise""" #param_letters = set('S') # S is it's own gcode, makes no sense to be here word_key = Word('M', 3) - modal_group = 7 + modal_group = MODAL_GROUP_NUM['spindle'] class GCodeStartSpindleCCW(GCodeSpindle): """M4: Start Spindle Counter-Clockwise""" #param_letters = set('S') # S is it's own gcode, makes no sense to be here word_key = Word('M', 4) - modal_group = 7 + modal_group = MODAL_GROUP_NUM['spindle'] class GCodeStopSpindle(GCodeSpindle): """M5: Stop Spindle""" #param_letters = set('S') # S is it's own gcode, makes no sense to be here word_key = Word('M', 5) - modal_group = 7 + modal_group = MODAL_GROUP_NUM['spindle'] class GCodeOrientSpindle(GCodeSpindle): @@ -434,14 +485,14 @@ class GCodeSpindleConstantSurfaceSpeedMode(GCodeSpindle): """G96: Spindle Constant Surface Speed""" param_letters = set('DS') word_key = Word('G', 96) - modal_group = 14 + modal_group = MODAL_GROUP_NUM['spindle_speed'] class GCodeSpindleRPMMode(GCodeSpindle): """G97: Spindle RPM Speed""" param_letters = set('D') word_key = Word('G', 97) - modal_group = 14 + modal_group = MODAL_GROUP_NUM['spindle_speed'] @@ -450,7 +501,7 @@ class GCodeSpindleRPMMode(GCodeSpindle): # M7, M8, M9 Coolant Control class GCodeCoolant(GCode): - modal_group = 8 + modal_group = MODAL_GROUP_NUM['coolant'] exec_order = 110 @@ -477,7 +528,7 @@ class GCodeCoolantOff(GCodeCoolant): # G49 Cancel Tool Length Compensation class GCodeToolLength(GCode): - modal_group = 8 + modal_group = MODAL_GROUP_NUM['tool_length_offset'] exec_order = 180 @@ -510,7 +561,7 @@ class GCodeCancelToolLengthOffset(GCodeToolLength): # M60 Pallet Change Pause class GCodeProgramControl(GCode): - modal_group = 4 + modal_group = MODAL_GROUP_NUM['stopping'] exec_order = 250 class GCodePauseProgram(GCodeProgramControl): @@ -543,7 +594,7 @@ class GCodePalletChangePause(GCodeProgramControl): # G20, G21 Units class GCodeUnit(GCode): - modal_group = 6 + modal_group = MODAL_GROUP_NUM['units'] exec_order = 160 @@ -563,7 +614,7 @@ class GCodeUseMillimeters(GCodeUnit): # G17 - G19.1 Plane Select class GCodePlaneSelect(GCode): - modal_group = 2 + modal_group = MODAL_GROUP_NUM['plane_selection'] exec_order = 150 @@ -604,7 +655,7 @@ class GCodeSelectVWPlane(GCodePlaneSelect): # G41.1, G42.1 D L Dynamic Cutter Compensation class GCodeCutterRadiusComp(GCode): - modal_group = 7 + modal_group = MODAL_GROUP_NUM['cutter_diameter_comp'] exec_order = 170 @@ -643,7 +694,7 @@ class GCodeDynamicCutterCompRight(GCodeCutterRadiusComp): # G64 P Q Path Blending class GCodePathControlMode(GCode): - modal_group = 13 + modal_group = MODAL_GROUP_NUM['control_mode'] exec_order = 200 @@ -668,7 +719,7 @@ class GCodePathBlendingMode(GCodePathControlMode): # G98 Canned Cycle Return Level class GCodeCannedReturnMode(GCode): - modal_group = 10 + modal_group = MODAL_GROUP_NUM['canned_cycles_return'] exec_order = 220 @@ -698,11 +749,7 @@ class GCodeFeedRate(GCodeOtherModal): @classmethod def word_matches(cls, w): return w.letter == 'F' - # Modal Group : - # although this sets the machine's state, there are no other codes to - # group with this one, so although it's modal, it usually has no group. - # However, - modal_group = 101 + modal_group = MODAL_GROUP_NUM['feed_rate'] exec_order = 40 @@ -712,7 +759,7 @@ class GCodeSpindleSpeed(GCodeOtherModal): def word_matches(cls, w): return w.letter == 'S' # Modal Group: (see description in GCodeFeedRate) - modal_group = 102 + modal_group = MODAL_GROUP_NUM['spindle_speed'] exec_order = 50 @@ -722,21 +769,21 @@ class GCodeSelectTool(GCodeOtherModal): def word_matches(cls, w): return w.letter == 'T' # Modal Group: (see description in GCodeFeedRate) - modal_group = 103 + modal_group = MODAL_GROUP_NUM['tool'] exec_order = 60 class GCodeSpeedAndFeedOverrideOn(GCodeOtherModal): """M48: Speed and Feed Override Control On""" word_key = Word('M', 48) - modal_group = 9 + modal_group = MODAL_GROUP_NUM['override_switches'] exec_order = 120 class GCodeSpeedAndFeedOverrideOff(GCodeOtherModal): """M49: Speed and Feed Override Control Off""" word_key = Word('M', 49) - modal_group = 9 + modal_group = MODAL_GROUP_NUM['override_switches'] exec_order = 120 @@ -783,7 +830,7 @@ class GCodeSelectCoordinateSystem(GCodeOtherModal): @classmethod def word_matches(cls, w): return (w.letter == 'G') and (w.value in [54, 55, 56, 57, 58, 59, 59.1, 59.2, 59.3]) - modal_group = 12 + modal_group = MODAL_GROUP_NUM['coordinate_system'] exec_order = 190 @@ -950,6 +997,7 @@ class GCodeUserDefined(GCodeNonModal): #def word_matches(cls, w): # return (w.letter == 'M') and (101 <= w.value <= 199) exec_order = 130 + modal_group = MODAL_GROUP_NUM['user_defined'] # ======================= Utilities ======================= @@ -997,7 +1045,7 @@ _gcode_function_list = [] # of the form: [(lambda w: w.letter == 'F', GCodeFeedR def build_maps(): """Populate _gcode_word_map and _gcode_function_list""" - # Ensure lists are clear + # Ensure Word maps / lists are clear global _gcode_word_map global _gcode_function_list _gcode_word_map = {} @@ -1043,8 +1091,7 @@ def word_gcode_class(word, exhaustive=False): return None - -def words_to_gcodes(words): +def words2gcodes(words): """ Group words into g-codes (includes both G & M codes) :param words: list of Word instances diff --git a/pygcode/line.py b/pygcode/line.py index f12ebd6..a1bd290 100644 --- a/pygcode/line.py +++ b/pygcode/line.py @@ -20,9 +20,8 @@ class Line(object): @property def text(self): if self._text is None: - return self.build_line_text() + return str(self) return self._text - - def build_line_text(self): - return ' '.join([str(x) for x in [self.block, self.comment] if x]) + '\n' + def __str__(self): + return ' '.join([str(x) for x in [self.block, self.comment] if x]) diff --git a/pygcode/words.py b/pygcode/words.py index 9765b65..47a6bbe 100644 --- a/pygcode/words.py +++ b/pygcode/words.py @@ -5,10 +5,21 @@ import six from .exceptions import GCodeBlockFormatError -FLOAT_REGEX = re.compile(r'^-?(\d+\.?\d*|\.\d+)') # testcase: ..tests.test_words.WordValueMatchTests.test_float -INT_REGEX = re.compile(r'^-?\d+') -POSITIVEINT_REGEX = re.compile(r'^\d+') -CODE_REGEX = re.compile(r'^\d+(\.\d)?') # similar +REGEX_FLOAT = re.compile(r'^-?(\d+\.?\d*|\.\d+)') # testcase: ..tests.test_words.WordValueMatchTests.test_float +REGEX_INT = re.compile(r'^-?\d+') +REGEX_POSITIVEINT = re.compile(r'^\d+') +REGEX_CODE = re.compile(r'^\d+(\.\d)?') # similar + +# 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: "%g" % v +CLEAN_CODE = _clean_codestr +CLEAN_INT = lambda v: "%g" % v WORD_MAP = { # Descriptions copied from wikipedia: @@ -17,148 +28,174 @@ WORD_MAP = { # Rotational Axes 'A': { 'class': float, - 'value_regex': FLOAT_REGEX, + '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': FLOAT_REGEX, + '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': FLOAT_REGEX, + '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': FLOAT_REGEX, + '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': FLOAT_REGEX, + 'value_regex': REGEX_FLOAT, 'description': "Precision feedrate for threading on lathes", + 'clean_value': CLEAN_FLOAT, }, 'F': { 'class': float, - 'value_regex': FLOAT_REGEX, + 'value_regex': REGEX_FLOAT, 'description': "Feedrate", + 'clean_value': CLEAN_FLOAT, }, # G-Codes 'G': { 'class': float, - 'value_regex': CODE_REGEX, + 'value_regex': REGEX_CODE, 'description': "Address for preparatory commands", + 'clean_value': CLEAN_CODE, }, # Tool Offsets 'H': { 'class': float, - 'value_regex': FLOAT_REGEX, + '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': FLOAT_REGEX, + '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': FLOAT_REGEX, + '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': FLOAT_REGEX, + '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': POSITIVEINT_REGEX, + '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': CODE_REGEX, + 'value_regex': REGEX_CODE, 'description': "Miscellaneous function", + 'clean_value': CLEAN_CODE, }, # Line Number 'N': { 'class': int, - 'value_regex': POSITIVEINT_REGEX, + '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': FLOAT_REGEX, + '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': FLOAT_REGEX, + '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': FLOAT_REGEX, + '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': FLOAT_REGEX, + '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': POSITIVEINT_REGEX, # tool string may have leading '0's, but is effectively an index (integer) + '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': FLOAT_REGEX, + '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': FLOAT_REGEX, + 'value_regex': REGEX_FLOAT, 'description': "Incremental axis corresponding to Y axis", + 'clean_value': CLEAN_FLOAT, }, 'W': { 'class': float, - 'value_regex': FLOAT_REGEX, + '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': FLOAT_REGEX, + 'value_regex': REGEX_FLOAT, 'description': "Absolute or incremental position of X axis.", + 'clean_value': CLEAN_FLOAT, }, 'Y': { 'class': float, - 'value_regex': FLOAT_REGEX, + 'value_regex': REGEX_FLOAT, 'description': "Absolute or incremental position of Y axis.", + 'clean_value': CLEAN_FLOAT, }, 'Z': { 'class': float, - 'value_regex': FLOAT_REGEX, + 'value_regex': REGEX_FLOAT, 'description': "Absolute or incremental position of Z axis.", + 'clean_value': CLEAN_FLOAT, }, } @@ -174,8 +211,8 @@ class Word(object): else: self._value = value - # Sorting Order - self._order_linuxcnc = None + self._value_class = WORD_MAP[self.letter]['class'] + self._value_clean = WORD_MAP[self.letter]['clean_value'] def __str__(self): return "{letter}{value}".format( @@ -183,6 +220,14 @@ class Word(object): value=self.value_str, ) + @property + def clean_str(self): + """same as __str__ but with a cleaned value (eg: X.4 is X0.4)""" + return "{letter}{value}".format( + letter=self.letter, + value=self.value_cleanstr, + ) + def __repr__(self): return "<{class_name}: {string}>".format( class_name=self.__class__.__name__, @@ -190,6 +235,8 @@ class Word(object): ) def __eq__(self, other): + if isinstance(other, six.string_types): + other = str2word(other) return (self.letter == other.letter) and (self.value == other.value) def __ne__(self, other): @@ -198,42 +245,45 @@ class Word(object): def __hash__(self): return hash((self.letter, self.value)) + # Value Properties @property def value_str(self): - """Value string, or """ + """Value string, or string representation of value""" if self._value_str is None: return str(self._value) return self._value_str + @property + def value_cleanstr(self): + """Clean string representation, for consistent file output""" + return self._value_clean(self.value) + @property def value(self): if self._value is None: - return WORD_MAP[self.letter]['class'](self._value_str) + return self._value_class(self._value_str) return self._value # Order - @property - def orderval_linuxcnc(self): - if self._order_linuxcnc is None: - self._order_linuxcnc = _word_order_linuxcnc(self) - return self._order_linuxcnc + def __lt__(self, other): + return self.letter < other.letter @property def description(self): return "%s: %s" % (self.letter, WORD_MAP[self.letter]['description']) -NEXT_WORD = re.compile(r'^.*?(?P[%s])' % ''.join(WORD_MAP.keys()), re.IGNORECASE) def iter_words(block_text): """ Iterate through block text yielding Word instances :param block_text: text for given block with comments removed """ - index = 0 + next_word = re.compile(r'^.*?(?P[%s])' % ''.join(WORD_MAP.keys()), re.IGNORECASE) + index = 0 while True: - letter_match = NEXT_WORD.search(block_text[index:]) + letter_match = next_word.search(block_text[index:]) if letter_match: # Letter letter = letter_match.group('letter').upper() diff --git a/tests/test_file.py b/tests/test_file.py index b09bae3..82a20ee 100644 --- a/tests/test_file.py +++ b/tests/test_file.py @@ -17,4 +17,4 @@ class FileParseTest(unittest.TestCase): self.assertEqual(len(file.lines), 26) # FIXME: just verifying content visually #for line in file.lines: - # print(' '.join(["%s%s" % (w.letter, w.value_str) for w in line.block.words])) + # print(line) diff --git a/tests/test_gcodes.py b/tests/test_gcodes.py index 8462928..828107d 100644 --- a/tests/test_gcodes.py +++ b/tests/test_gcodes.py @@ -82,7 +82,7 @@ class TestWordsToGCodes(unittest.TestCase): def test_stuff(self): # FIXME: function name line = 'G1 X82.6892 Y-38.6339 F1500' word_list = list(words.iter_words(line)) - result = gcodes.words_to_gcodes(word_list) + result = gcodes.words2gcodes(word_list) # result form self.assertIsInstance(result, tuple) self.assertEqual(len(result), 2) diff --git a/tests/test_words.py b/tests/test_words.py index e42e8ef..6dfa959 100644 --- a/tests/test_words.py +++ b/tests/test_words.py @@ -58,7 +58,7 @@ class WordValueMatchTests(unittest.TestCase): def test_float(self): self.regex_assertions( - regex=words.FLOAT_REGEX, + regex=words.REGEX_FLOAT, positive_list=[ ('1.2', '1.2'), ('1', '1'), ('200', '200'), ('0092', '0092'), ('1.', '1.'), ('.2', '.2'), ('-1.234', '-1.234'), @@ -71,7 +71,7 @@ class WordValueMatchTests(unittest.TestCase): def test_code(self): self.regex_assertions( - regex=words.CODE_REGEX, + regex=words.REGEX_CODE, positive_list=[ ('1.2', '1.2'), ('1', '1'), ('10', '10'), ('02', '02'), ('02.3', '02.3'),