-
Notifications
You must be signed in to change notification settings - Fork 21
/
yuml
executable file
·170 lines (130 loc) · 5.42 KB
/
yuml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This is an unofficial command line client for the yUML <http://yuml.me> web
app. Use it to draw class diagrams, activity diagrams and usecase diagrams
from the command line, integrate yUML into your documentation workflow or what
have you.
Copyright (c) 2012-2016 Wander Nauta.
yuml is distributed under the terms of the ISC license.
***
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
The software is provided "as is" and the author disclaims all warranties with
regard to this software including all implied warranties of merchantability and
fitness. In no event shall the author be liable for any special, direct,
indirect, or consequential damages or any damages whatsoever resulting from
loss of use, data or profits, whether in an action of contract, negligence or
other tortious action, arising out of or in connection with the use or
performance of this software.
"""
from optparse import OptionParser
import codecs
import os
import sys
import time
# <monkey>
# We try to be compatible with both Python 2 and 3 here.
if sys.version_info >= (3, 0):
# noinspection PyUnresolvedReferences, PyCompatibility
from urllib.request import urlopen, Request, HTTPError
# noinspection PyUnresolvedReferences, PyCompatibility
from urllib.parse import quote
def decode(s):
return s
else:
# noinspection PyUnresolvedReferences, PyCompatibility
from urllib import quote
# noinspection PyUnresolvedReferences, PyCompatibility
from urllib2 import urlopen, Request, HTTPError
def decode(b):
return b.decode('utf-8')
# </monkey>
class YumlRequest(object):
"""Represents a single request to the yUML web service."""
opts = None
body = ""
out = None
API_BASE = "http://yuml.me/diagram"
def log(self, msg):
"""
Optionally log an informative message.
@param msg: The message to log.
"""
if self.opts.v:
print("[yuml] %s" % msg)
def loadbody(self):
"""Load the yUML text from stdin or a file."""
infile = self.opts.infile
self.log('Reading from %s' % ('stdin' if infile == '-' else infile))
if infile == '-':
source = decode(sys.stdin.read())
elif os.path.exists(infile):
source = decode(open(infile, 'r').read())
else:
raise IOError("File %s not found" % infile)
self.body = [x.strip() for x in source.splitlines() if x.strip()]
self.log('Done reading.')
def prepout(self):
"""Open the output file."""
if self.opts.outfile:
self.out = open(self.opts.outfile, 'wb')
else:
print("Usage: yuml [-i FILE] -o FILE")
sys.exit(1)
def run(self):
"""Execute the request."""
start = time.time()
if not self.out:
self.prepout()
if not self.body:
self.loadbody()
opts = self.opts.style
if self.opts.scale:
opts += ";scale:" + str(self.opts.scale)
if self.opts.dir:
opts += ";dir:" + str(self.opts.dir)
dsl_text = ', '.join(self.body).encode('utf-8')
url = "%s/%s/%s/%s.%s" % (self.API_BASE, opts, self.opts.type, quote(dsl_text), self.opts.fmt)
self.log('Requesting %s' % url)
try:
req = Request(url, headers={'User-Agent': 'wandernauta/yuml v0.2'})
response = urlopen(req).read()
self.out.write(response)
self.log('Done after %f seconds' % (time.time() - start))
except HTTPError as exception:
if exception.code == 500:
self.log("Service returned 500: probably malformed input.")
sys.exit(1)
else:
raise
def main():
"""Entry point for the command-line tool."""
parser = OptionParser(usage="%prog [-i FILE] -o FILE", version="%prog 0.1")
parser.add_option("-i", "--in", dest="infile", metavar="FILE", default="-",
help="read yuml from FILE instead of stdin")
parser.add_option("-o", "--out", dest="outfile", metavar="FILE",
help="store output in FILE")
parser.add_option("-f", "--format", dest="fmt", metavar="FMT",
choices=['png', 'pdf', 'jpg', 'svg'],
help="use format FMT")
parser.add_option("-t", "--type", dest="type", metavar="TYPE",
choices=['class', 'activity', 'usecase'],
help="draw a TYPE diagram")
parser.add_option("-s", "--style", dest="style", metavar="STY",
choices=['scruffy', 'nofunky', 'plain'],
help="use style STY")
parser.add_option("--scale", dest="scale", metavar="PERCENT", type="int",
help="scale output to percentage")
parser.add_option("--dir", dest="dir", choices=['LR', 'RL', 'TD'],
help="direction of the diagram LR RL TD")
parser.add_option("-v", "--verbose", dest="v", action="store_true",
help="print some debug info")
parser.set_defaults(v=False, fmt="png", type="class", style="scruffy")
(options, _) = parser.parse_args()
request = YumlRequest()
request.opts = options
request.run()
if __name__ == "__main__":
main()