[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-cvs: xgsch2pcb.git: branch: master updated (rel_0.1.3-12-g2eb0dc8)



The branch, master has been updated
       via  2eb0dc8b7725a3b6ef52cedd48ab631471893516 (commit)
      from  3c3f8d00678111d5823e87cb136ddcd0df9e1487 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


=========
 Summary
=========

 configure.ac                     |    2 +-
 lib/xgsch2pcb/funcs.py           |  136 ++++++++++++++++++++++++++++++++++++++
 lib/xgsch2pcb/gsch2pcbproject.py |   15 ++--
 3 files changed, 144 insertions(+), 9 deletions(-)


=================
 Commit Messages
=================

commit 2eb0dc8b7725a3b6ef52cedd48ab631471893516
Author: Krzysztof KoÅ?ciuszkiewicz <k.kosciuszkiewicz@xxxxxxxxx>
Commit: Krzysztof KoÅ?ciuszkiewicz <k.kosciuszkiewicz@xxxxxxxxx>

    Support quoting of gsch2pcb option values
    
    Function shell_parse splits lines according to POSIX shell rules.
    
    Function shell_quote quotes and escapes argument according to POSIX
    shell rules.
    
    Standard module shlex could have been used, but it requires Python 2.6
    to support POSIX-compatible parsing.
    
    Closes-bug: lp-726828

:100644 100644 950ea19... 3caabd4... M	configure.ac
:100644 100644 9a99e7f... 1f6b29a... M	lib/xgsch2pcb/funcs.py
:100644 100644 e703ec8... e813d7f... M	lib/xgsch2pcb/gsch2pcbproject.py

=========
 Changes
=========

commit 2eb0dc8b7725a3b6ef52cedd48ab631471893516
Author: Krzysztof KoÅ?ciuszkiewicz <k.kosciuszkiewicz@xxxxxxxxx>
Commit: Krzysztof KoÅ?ciuszkiewicz <k.kosciuszkiewicz@xxxxxxxxx>

    Support quoting of gsch2pcb option values
    
    Function shell_parse splits lines according to POSIX shell rules.
    
    Function shell_quote quotes and escapes argument according to POSIX
    shell rules.
    
    Standard module shlex could have been used, but it requires Python 2.6
    to support POSIX-compatible parsing.
    
    Closes-bug: lp-726828

diff --git a/configure.ac b/configure.ac
index 950ea19..3caabd4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,7 +28,7 @@ AM_INIT_AUTOMAKE([foreign])
 
 
 PYTHON_WANTVERSION=2.4
-PYTHON_WANTMODULES="commands gettext os os.path re shutil stat subprocess dbus dbus.glib dbus.service"
+PYTHON_WANTMODULES="commands gettext os os.path re shutil stat subprocess dbus dbus.glib dbus.service string"
 GTK_WANTVERSION=2.8
 
 
diff --git a/lib/xgsch2pcb/funcs.py b/lib/xgsch2pcb/funcs.py
index 9a99e7f..1f6b29a 100644
--- a/lib/xgsch2pcb/funcs.py
+++ b/lib/xgsch2pcb/funcs.py
@@ -19,6 +19,8 @@
 
 import commands
 import os
+import string
+import re
 
 def find_tool_path (tool):
 
@@ -64,3 +66,137 @@ def rel_path(topath, fromdir=""):
     # Return the topath without the common prefix
     return topath[len(prefix):]
 
+def shell_parse (line):
+    # FIXME: shlex.split could be used instead of this function.
+    # Forcing shlex.split to follow POSIX is possible since Python 2.6
+    r"""Parse shell command line according to POSIX rules.
+
+    >>> shell_parse('')
+    []
+
+    >>> shell_parse(' \t ')
+    []
+
+    >>> shell_parse(' \  ')
+    [' ']
+
+    >>> shell_parse('abc def')
+    ['abc', 'def']
+
+    >>> shell_parse(' abc""d\'\'ef')
+    ['abcdef']
+
+    >>> shell_parse(' " \' " ')
+    [" ' "]
+
+    >>> shell_parse("'\\'")
+    ['\\']
+
+    >>> shell_parse("'")
+    Traceback (most recent call last):
+        ...
+    ValueError: unmatched single quote
+
+    >>> shell_parse('"')
+    Traceback (most recent call last):
+        ...
+    ValueError: unmatched double quote
+
+    >>> shell_parse('\\')
+    Traceback (most recent call last):
+        ...
+    ValueError: unmatched escape character
+    """
+
+    parsed = []
+    state = 'white'
+    collect = ""
+    escape = False
+    C_SQUOTE = "'"
+    C_DQUOTE = '"'
+    C_BSLASH = '\\'
+
+    for c in line:
+        if escape:
+            collect += c
+            escape = False
+        elif state == 'white':
+            if c == C_SQUOTE:
+                state = 'squote'
+            elif c == C_DQUOTE:
+                state = 'dquote'
+            elif c == C_BSLASH:
+                escape = True
+                state = 'text'
+            elif c not in string.whitespace:
+                state = 'text'
+                collect += c
+        elif state == 'squote':
+            if c == C_SQUOTE:
+                state = 'text'
+            else:
+                collect += c
+        elif state == 'dquote':
+            if c == C_DQUOTE:
+                state = 'text'
+            elif c == C_BSLASH:
+                escape = True
+            else:
+                collect += c
+        elif state == 'text':
+            if c == C_SQUOTE:
+                state = 'squote'
+            elif c == C_DQUOTE:
+                state = 'dquote'
+            elif c == C_BSLASH:
+                escape = True
+            elif c in string.whitespace:
+                parsed.append (collect)
+                collect = ""
+                state = 'white'
+            else:
+                collect += c
+
+    if escape:
+        raise ValueError, 'unmatched escape character'
+    elif state == 'text':
+        parsed.append (collect)
+    elif state == 'squote':
+        raise ValueError, 'unmatched single quote'
+    elif state == 'dquote':
+        raise ValueError, 'unmatched double quote'
+    return parsed
+
+def shell_quote (line):
+    """Quote string according to POSIX shell rules.
+
+    >>> s = '"'; s == shell_parse(shell_quote(s))[0]
+    True
+
+    >>> s = "'"; s == shell_parse(shell_quote(s))[0]
+    True
+
+    >>> s = "test abc"; s == shell_parse(shell_quote(s))[0]
+    True
+
+    >>> s = ' ab " \\'c'; s == shell_parse(shell_quote(s))[0]
+    True
+
+    >>> shell_quote("abc")
+    'abc'
+
+    >>> shell_quote(" def ")
+    '" def "'
+    """
+
+    toquote = '"\'\\'
+
+    if any ([c in line for c in toquote + string.whitespace]):
+        escaped = re.sub ("([%s])" % re.escape(toquote), r'\\\1', line)
+        return '"%s"' % escaped
+    else:
+        return line
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
diff --git a/lib/xgsch2pcb/gsch2pcbproject.py b/lib/xgsch2pcb/gsch2pcbproject.py
index e703ec8..e813d7f 100644
--- a/lib/xgsch2pcb/gsch2pcbproject.py
+++ b/lib/xgsch2pcb/gsch2pcbproject.py
@@ -18,7 +18,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-import os, gobject
+import os, gobject, funcs
 
 class Gsch2PCBOption(object):
     """Gsch2PCBOption - class representing project's option
@@ -40,7 +40,8 @@ function to write option's value to the config and default option's value corres
         def default_write_function(option, project, save_file):
             value = getattr(project, option.attr_name)
             if value:
-                save_file.write(option.name + ' %s\n' % value)
+                line = "%s %s\n" % (option.name, funcs.shell_quote (value))
+                save_file.write(line)
 
         self.name=kwargs['name']
         self.attr_name=kwargs['attr_name']
@@ -59,7 +60,8 @@ function to write option's value to the config and default option's value corres
     def join_then_write(option, project, save_file):
         values = getattr(project, option.attr_name)
         if values:
-            save_file.write(option.name + ' %s\n' % ' '.join(values))
+            s = " ".join (map (funcs.shell_quote, values))
+            save_file.write("%s %s\n" % (option.name, s))
     @staticmethod
     def write_if_equal(value):
         def func(option, project, save_file):
@@ -76,10 +78,7 @@ function to write option's value to the config and default option's value corres
 
     @staticmethod
     def read_multiple_values(option, project, parts):
-        if len(parts) > 1:
-            value = parts[1].split()
-        else:
-            value = []
+        value = parts[1:]
         setattr(project, option.attr_name, value)
     @staticmethod
     def read_and_set_value(value):
@@ -190,7 +189,7 @@ class Gsch2PCBProject(gobject.GObject):
         fp = open(fromfile, 'rb')
         for line in fp:
             self.lines.append(line)
-            parts = line.strip().split(None, 1)
+            parts = funcs.shell_parse (line)
 
             option_name = None
             if parts:



_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs