Merge pull request #37 from pydot/bug/36
Adjusted quoting to DOT lang specification
This commit is contained in:
commit
4ab4b6a0f5
@ -198,15 +198,13 @@ class frozendict(dict):
|
||||
return "frozendict(%s)" % dict.__repr__(self)
|
||||
|
||||
|
||||
dot_keywords = ['graph', 'subgraph', 'digraph', 'node', 'edge', 'strict']
|
||||
|
||||
id_re_alpha_nums = re.compile('^[_a-zA-Z][a-zA-Z0-9_,]*$', re.UNICODE)
|
||||
id_re_alpha_nums_with_ports = re.compile(
|
||||
'^[_a-zA-Z][a-zA-Z0-9_,:\"]*[a-zA-Z0-9_,\"]+$', re.UNICODE)
|
||||
id_re_num = re.compile('^[0-9,]+$', re.UNICODE)
|
||||
id_re_with_port = re.compile('^([^:]*):([^:]*)$', re.UNICODE)
|
||||
id_re_dbl_quoted = re.compile('^\".*\"$', re.S | re.UNICODE)
|
||||
id_re_html = re.compile('^<.*>$', re.S | re.UNICODE)
|
||||
# cases when no qoutes needed, from http://www.graphviz.org/doc/info/lang.html
|
||||
dot_keywords = ('graph', 'subgraph', 'digraph', 'node', 'edge', 'strict')
|
||||
id_alpha_num = re.compile(r'^[_a-zA-Z\200-\377][_a-zA-Z0-9\200-\377]*$',
|
||||
re.UNICODE)
|
||||
id_num = re.compile(r'^[-]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)$', re.UNICODE)
|
||||
id_html = re.compile(r'^<.*>$', re.DOTALL | re.UNICODE)
|
||||
id_quoted = re.compile(r'^".*"$', re.DOTALL | re.UNICODE)
|
||||
|
||||
|
||||
def needs_quotes(s):
|
||||
@ -228,19 +226,18 @@ def needs_quotes(s):
|
||||
if s in dot_keywords:
|
||||
return False
|
||||
|
||||
chars = [ord(c) for c in s if ord(c) > 0x7f or ord(c) == 0]
|
||||
if chars and not id_re_dbl_quoted.match(s) and not id_re_html.match(s):
|
||||
return True
|
||||
|
||||
for test_re in [
|
||||
id_re_alpha_nums, id_re_num, id_re_dbl_quoted,
|
||||
id_re_html, id_re_alpha_nums_with_ports]:
|
||||
id_alpha_num,
|
||||
id_num,
|
||||
id_html,
|
||||
id_quoted,
|
||||
]:
|
||||
if test_re.match(s):
|
||||
return False
|
||||
|
||||
m = id_re_with_port.match(s)
|
||||
if m:
|
||||
return needs_quotes(m.group(1)) or needs_quotes(m.group(2))
|
||||
chars = [ord(c) for c in s if ord(c) > 0x7f or ord(c) == 0]
|
||||
if chars and not id_quoted.match(s) and not id_html.match(s):
|
||||
return True
|
||||
|
||||
return True
|
||||
|
||||
|
@ -285,6 +285,33 @@ class TestGraphAPI(unittest.TestCase):
|
||||
data = g.create(format='jpe')
|
||||
self.assertEqual(len(data) > 0, True)
|
||||
|
||||
|
||||
class TestQuoting(unittest.TestCase):
|
||||
|
||||
def test_quote_cases(self):
|
||||
checks = (
|
||||
('A:', '"A:"'),
|
||||
(':B', '":B"'),
|
||||
('A:B', '"A:B"'),
|
||||
('1A', '"1A"'),
|
||||
('A', 'A'),
|
||||
('11', '11'),
|
||||
('_xyz', '_xyz'),
|
||||
('.11', '.11'),
|
||||
('-.09', '-.09'),
|
||||
('1.8', '1.8'),
|
||||
('', '""'),
|
||||
('"1abc"', '"1abc"'),
|
||||
('@', '"@"'),
|
||||
('ÿ', 'ÿ'),
|
||||
('$GUID__/ffb73e1c-7495-40b3-9618-9e5462fc89c7',
|
||||
'"$GUID__/ffb73e1c-7495-40b3-9618-9e5462fc89c7"')
|
||||
)
|
||||
|
||||
for input, expected in checks:
|
||||
self.assertEqual(pydot.quote_if_necessary(input), expected)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestGraphAPI)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
|
Loading…
Reference in New Issue
Block a user