├── .gitattributes
├── .gitignore
├── LICENSE.txt
├── README.rst
├── compile.py
├── dashie.png
├── ez_setup.py
├── pydashie
├── __init__.py
├── assets
│ ├── images
│ │ ├── dashie.png
│ │ └── favicon.ico
│ ├── javascripts
│ │ ├── app.js
│ │ ├── application.coffee
│ │ ├── application.js
│ │ ├── batman.jquery.js
│ │ ├── batman.js
│ │ ├── d3.v2.min.js
│ │ ├── dashing.coffee
│ │ ├── dashing.gridster.coffee
│ │ ├── es5-shim.js
│ │ ├── jquery.gridster.js
│ │ ├── jquery.js
│ │ ├── jquery.knob.js
│ │ ├── jquery.leanModal.min.js
│ │ └── rickshaw.min.js
│ └── stylesheets
│ │ ├── application.css
│ │ ├── application.css~
│ │ ├── application.scss
│ │ ├── font-awesome.css
│ │ └── jquery.gridster.css
├── dashie_sampler.py
├── example_app.py
├── example_samplers.py
├── main.py
├── repeated_timer.py
├── samplers
│ ├── __init__.py
│ ├── trello_sampler.py
│ └── website_up.py
├── templates
│ ├── main.html
│ └── small.html
└── widgets
│ ├── clock
│ ├── clock.coffee
│ ├── clock.html
│ └── clock.scss
│ ├── comments
│ ├── comments.coffee
│ ├── comments.html
│ └── comments.scss
│ ├── graph
│ ├── graph.coffee
│ ├── graph.html
│ └── graph.scss
│ ├── iframe
│ ├── iframe.coffee
│ ├── iframe.html
│ └── iframe.scss
│ ├── image
│ ├── image.coffee
│ ├── image.html
│ └── image.scss
│ ├── list
│ ├── list.coffee
│ ├── list.html
│ └── list.scss
│ ├── meter
│ ├── meter.coffee
│ ├── meter.html
│ └── meter.scss
│ ├── number
│ ├── number.coffee
│ ├── number.html
│ └── number.scss
│ └── text
│ ├── text.coffee
│ ├── text.html
│ └── text.scss
├── requirements.txt
└── setup.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .project.txt
2 | .pydevproject.txt
3 | *.pyc
4 | *Thumbs.db
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Stephen Brown
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | PyDashie
2 | ########
3 |
4 | This project is mostly dormant now.
5 |
6 | `Main Documentation `_
7 |
8 | PyDashy is a port of `Dashing `_ by `Shopify `_ to Python 2.7
9 |
10 | .. image:: http://evolvedlight.github.com/pydashie/images/mainscreen.png
11 |
12 | Installation
13 | ############
14 |
15 | For development purposes,
16 |
17 | python setup.py develop
18 |
19 | OR
20 |
21 | python setup.py install
22 |
23 | And you can run the application by
24 |
25 | pydashie
26 |
27 | Goto localhost:5000 to view the sample application in action.
28 |
--------------------------------------------------------------------------------
/compile.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import logging
4 | import shutil
5 | import subprocess
6 | from scss import Scss
7 |
8 | log = logging.getLogger('PydashieCompiler')
9 | logging.basicConfig()
10 | log.setLevel(logging.INFO)
11 | #Requirements:
12 |
13 | #pip install pyScss
14 |
15 |
16 | #
17 | def main():
18 | #Options
19 | refreshDashingCode=True
20 |
21 |
22 | #Check out dashing into temp directory
23 | current_directory = os.getcwd()
24 |
25 | tmp_dir = os.path.join(current_directory, 'tmp')
26 | if not os.path.exists(tmp_dir):
27 | log.info('Creating tmp dir %s' % tmp_dir)
28 | os.mkdir(tmp_dir)
29 |
30 | tmp_build_dir = os.path.join(tmp_dir, 'bin')
31 | if not os.path.exists(tmp_build_dir):
32 | log.info('Creating bin dir %s' % tmp_build_dir)
33 | os.mkdir(tmp_build_dir)
34 |
35 | dashing_dir = os.path.join(current_directory, 'tmp', 'dashing')
36 | if refreshDashingCode:
37 | if os.path.exists(dashing_dir):
38 | log.info('Removing old Dashing Clone')
39 | shutil.rmtree(dashing_dir)
40 |
41 | log.info('Creating dashing tmp dir %s' % dashing_dir)
42 | os.mkdir(dashing_dir)
43 |
44 | os.chdir(dashing_dir)
45 | if refreshDashingCode:
46 | log.info('Cloning Dashing Code')
47 | subprocess.call("git clone https://github.com/Shopify/dashing", shell=True)
48 | fileList = []
49 | for root, subFolders, files in os.walk(dashing_dir):
50 | for fileName in files:
51 | if 'scss' in fileName:
52 | fileList.append(os.path.join(root, fileName))
53 | log.info('Found SCSS to compile: %s' % fileName)
54 | import StringIO
55 | css_output = StringIO.StringIO()
56 | css = Scss()
57 | css_output.write('\n'.join([css.compile(open(filePath).read()) for filePath in fileList]))
58 |
59 | fileList = []
60 | for root, subFolders, files in os.walk(dashing_dir):
61 | for fileName in files:
62 | if 'css' in fileName and 'scss' not in fileName:
63 | fileList.append(os.path.join(root, fileName))
64 | log.info('Found CSS to append: %s' % fileName)
65 | css_output.write('\n'.join([open(filePath).read() for filePath in fileList]))
66 |
67 | with open(os.path.join(tmp_build_dir, 'application.css'), 'w') as outfile:
68 | outfile.write(css_output.getvalue())
69 | log.info('Wrote CSS out')
70 |
71 | if __name__ == '__main__':
72 | main()
--------------------------------------------------------------------------------
/dashie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evolvedlight/pydashie/b93f799596b0e86ea970b26f3a7bf5415bb01e55/dashie.png
--------------------------------------------------------------------------------
/ez_setup.py:
--------------------------------------------------------------------------------
1 | #!python
2 | """Bootstrap distribute installation
3 |
4 | If you want to use setuptools in your package's setup.py, just include this
5 | file in the same directory with it, and add this to the top of your setup.py::
6 |
7 | from distribute_setup import use_setuptools
8 | use_setuptools()
9 |
10 | If you want to require a specific version of setuptools, set a download
11 | mirror, or use an alternate download directory, you can do so by supplying
12 | the appropriate options to ``use_setuptools()``.
13 |
14 | This file can also be run as a script to install or upgrade setuptools.
15 | """
16 | import os
17 | import sys
18 | import time
19 | import fnmatch
20 | import tempfile
21 | import tarfile
22 | from distutils import log
23 |
24 | try:
25 | from site import USER_SITE
26 | except ImportError:
27 | USER_SITE = None
28 |
29 | try:
30 | import subprocess
31 |
32 | def _python_cmd(*args):
33 | args = (sys.executable,) + args
34 | return subprocess.call(args) == 0
35 |
36 | except ImportError:
37 | # will be used for python 2.3
38 | def _python_cmd(*args):
39 | args = (sys.executable,) + args
40 | # quoting arguments if windows
41 | if sys.platform == 'win32':
42 | def quote(arg):
43 | if ' ' in arg:
44 | return '"%s"' % arg
45 | return arg
46 | args = [quote(arg) for arg in args]
47 | return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
48 |
49 | DEFAULT_VERSION = "0.6.14"
50 | DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
51 | SETUPTOOLS_FAKED_VERSION = "0.6c11"
52 |
53 | SETUPTOOLS_PKG_INFO = """\
54 | Metadata-Version: 1.0
55 | Name: setuptools
56 | Version: %s
57 | Summary: xxxx
58 | Home-page: xxx
59 | Author: xxx
60 | Author-email: xxx
61 | License: xxx
62 | Description: xxx
63 | """ % SETUPTOOLS_FAKED_VERSION
64 |
65 |
66 | def _install(tarball):
67 | # extracting the tarball
68 | tmpdir = tempfile.mkdtemp()
69 | log.warn('Extracting in %s', tmpdir)
70 | old_wd = os.getcwd()
71 | try:
72 | os.chdir(tmpdir)
73 | tar = tarfile.open(tarball)
74 | _extractall(tar)
75 | tar.close()
76 |
77 | # going in the directory
78 | subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
79 | os.chdir(subdir)
80 | log.warn('Now working in %s', subdir)
81 |
82 | # installing
83 | log.warn('Installing Distribute')
84 | if not _python_cmd('setup.py', 'install'):
85 | log.warn('Something went wrong during the installation.')
86 | log.warn('See the error message above.')
87 | finally:
88 | os.chdir(old_wd)
89 |
90 |
91 | def _build_egg(egg, tarball, to_dir):
92 | # extracting the tarball
93 | tmpdir = tempfile.mkdtemp()
94 | log.warn('Extracting in %s', tmpdir)
95 | old_wd = os.getcwd()
96 | try:
97 | os.chdir(tmpdir)
98 | tar = tarfile.open(tarball)
99 | _extractall(tar)
100 | tar.close()
101 |
102 | # going in the directory
103 | subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
104 | os.chdir(subdir)
105 | log.warn('Now working in %s', subdir)
106 |
107 | # building an egg
108 | log.warn('Building a Distribute egg in %s', to_dir)
109 | _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
110 |
111 | finally:
112 | os.chdir(old_wd)
113 | # returning the result
114 | log.warn(egg)
115 | if not os.path.exists(egg):
116 | raise IOError('Could not build the egg.')
117 |
118 |
119 | def _do_download(version, download_base, to_dir, download_delay):
120 | egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
121 | % (version, sys.version_info[0], sys.version_info[1]))
122 | if not os.path.exists(egg):
123 | tarball = download_setuptools(version, download_base,
124 | to_dir, download_delay)
125 | _build_egg(egg, tarball, to_dir)
126 | sys.path.insert(0, egg)
127 | import setuptools
128 | setuptools.bootstrap_install_from = egg
129 |
130 |
131 | def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
132 | to_dir=os.curdir, download_delay=15, no_fake=True):
133 | # making sure we use the absolute path
134 | to_dir = os.path.abspath(to_dir)
135 | was_imported = 'pkg_resources' in sys.modules or \
136 | 'setuptools' in sys.modules
137 | try:
138 | try:
139 | import pkg_resources
140 | if not hasattr(pkg_resources, '_distribute'):
141 | if not no_fake:
142 | _fake_setuptools()
143 | raise ImportError
144 | except ImportError:
145 | return _do_download(version, download_base, to_dir, download_delay)
146 | try:
147 | pkg_resources.require("distribute>="+version)
148 | return
149 | except pkg_resources.VersionConflict:
150 | e = sys.exc_info()[1]
151 | if was_imported:
152 | sys.stderr.write(
153 | "The required version of distribute (>=%s) is not available,\n"
154 | "and can't be installed while this script is running. Please\n"
155 | "install a more recent version first, using\n"
156 | "'easy_install -U distribute'."
157 | "\n\n(Currently using %r)\n" % (version, e.args[0]))
158 | sys.exit(2)
159 | else:
160 | del pkg_resources, sys.modules['pkg_resources'] # reload ok
161 | return _do_download(version, download_base, to_dir,
162 | download_delay)
163 | except pkg_resources.DistributionNotFound:
164 | return _do_download(version, download_base, to_dir,
165 | download_delay)
166 | finally:
167 | if not no_fake:
168 | _create_fake_setuptools_pkg_info(to_dir)
169 |
170 | def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
171 | to_dir=os.curdir, delay=15):
172 | """Download distribute from a specified location and return its filename
173 |
174 | `version` should be a valid distribute version number that is available
175 | as an egg for download under the `download_base` URL (which should end
176 | with a '/'). `to_dir` is the directory where the egg will be downloaded.
177 | `delay` is the number of seconds to pause before an actual download
178 | attempt.
179 | """
180 | # making sure we use the absolute path
181 | to_dir = os.path.abspath(to_dir)
182 | try:
183 | from urllib.request import urlopen
184 | except ImportError:
185 | from urllib2 import urlopen
186 | tgz_name = "distribute-%s.tar.gz" % version
187 | url = download_base + tgz_name
188 | saveto = os.path.join(to_dir, tgz_name)
189 | src = dst = None
190 | if not os.path.exists(saveto): # Avoid repeated downloads
191 | try:
192 | log.warn("Downloading %s", url)
193 | src = urlopen(url)
194 | # Read/write all in one block, so we don't create a corrupt file
195 | # if the download is interrupted.
196 | data = src.read()
197 | dst = open(saveto, "wb")
198 | dst.write(data)
199 | finally:
200 | if src:
201 | src.close()
202 | if dst:
203 | dst.close()
204 | return os.path.realpath(saveto)
205 |
206 | def _no_sandbox(function):
207 | def __no_sandbox(*args, **kw):
208 | try:
209 | from setuptools.sandbox import DirectorySandbox
210 | if not hasattr(DirectorySandbox, '_old'):
211 | def violation(*args):
212 | pass
213 | DirectorySandbox._old = DirectorySandbox._violation
214 | DirectorySandbox._violation = violation
215 | patched = True
216 | else:
217 | patched = False
218 | except ImportError:
219 | patched = False
220 |
221 | try:
222 | return function(*args, **kw)
223 | finally:
224 | if patched:
225 | DirectorySandbox._violation = DirectorySandbox._old
226 | del DirectorySandbox._old
227 |
228 | return __no_sandbox
229 |
230 | def _patch_file(path, content):
231 | """Will backup the file then patch it"""
232 | existing_content = open(path).read()
233 | if existing_content == content:
234 | # already patched
235 | log.warn('Already patched.')
236 | return False
237 | log.warn('Patching...')
238 | _rename_path(path)
239 | f = open(path, 'w')
240 | try:
241 | f.write(content)
242 | finally:
243 | f.close()
244 | return True
245 |
246 | _patch_file = _no_sandbox(_patch_file)
247 |
248 | def _same_content(path, content):
249 | return open(path).read() == content
250 |
251 | def _rename_path(path):
252 | new_name = path + '.OLD.%s' % time.time()
253 | log.warn('Renaming %s into %s', path, new_name)
254 | os.rename(path, new_name)
255 | return new_name
256 |
257 | def _remove_flat_installation(placeholder):
258 | if not os.path.isdir(placeholder):
259 | log.warn('Unkown installation at %s', placeholder)
260 | return False
261 | found = False
262 | for file in os.listdir(placeholder):
263 | if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
264 | found = True
265 | break
266 | if not found:
267 | log.warn('Could not locate setuptools*.egg-info')
268 | return
269 |
270 | log.warn('Removing elements out of the way...')
271 | pkg_info = os.path.join(placeholder, file)
272 | if os.path.isdir(pkg_info):
273 | patched = _patch_egg_dir(pkg_info)
274 | else:
275 | patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
276 |
277 | if not patched:
278 | log.warn('%s already patched.', pkg_info)
279 | return False
280 | # now let's move the files out of the way
281 | for element in ('setuptools', 'pkg_resources.py', 'site.py'):
282 | element = os.path.join(placeholder, element)
283 | if os.path.exists(element):
284 | _rename_path(element)
285 | else:
286 | log.warn('Could not find the %s element of the '
287 | 'Setuptools distribution', element)
288 | return True
289 |
290 | _remove_flat_installation = _no_sandbox(_remove_flat_installation)
291 |
292 | def _after_install(dist):
293 | log.warn('After install bootstrap.')
294 | placeholder = dist.get_command_obj('install').install_purelib
295 | _create_fake_setuptools_pkg_info(placeholder)
296 |
297 | def _create_fake_setuptools_pkg_info(placeholder):
298 | if not placeholder or not os.path.exists(placeholder):
299 | log.warn('Could not find the install location')
300 | return
301 | pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
302 | setuptools_file = 'setuptools-%s-py%s.egg-info' % \
303 | (SETUPTOOLS_FAKED_VERSION, pyver)
304 | pkg_info = os.path.join(placeholder, setuptools_file)
305 | if os.path.exists(pkg_info):
306 | log.warn('%s already exists', pkg_info)
307 | return
308 |
309 | log.warn('Creating %s', pkg_info)
310 | f = open(pkg_info, 'w')
311 | try:
312 | f.write(SETUPTOOLS_PKG_INFO)
313 | finally:
314 | f.close()
315 |
316 | pth_file = os.path.join(placeholder, 'setuptools.pth')
317 | log.warn('Creating %s', pth_file)
318 | f = open(pth_file, 'w')
319 | try:
320 | f.write(os.path.join(os.curdir, setuptools_file))
321 | finally:
322 | f.close()
323 |
324 | _create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info)
325 |
326 | def _patch_egg_dir(path):
327 | # let's check if it's already patched
328 | pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
329 | if os.path.exists(pkg_info):
330 | if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
331 | log.warn('%s already patched.', pkg_info)
332 | return False
333 | _rename_path(path)
334 | os.mkdir(path)
335 | os.mkdir(os.path.join(path, 'EGG-INFO'))
336 | pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
337 | f = open(pkg_info, 'w')
338 | try:
339 | f.write(SETUPTOOLS_PKG_INFO)
340 | finally:
341 | f.close()
342 | return True
343 |
344 | _patch_egg_dir = _no_sandbox(_patch_egg_dir)
345 |
346 | def _before_install():
347 | log.warn('Before install bootstrap.')
348 | _fake_setuptools()
349 |
350 |
351 | def _under_prefix(location):
352 | if 'install' not in sys.argv:
353 | return True
354 | args = sys.argv[sys.argv.index('install')+1:]
355 | for index, arg in enumerate(args):
356 | for option in ('--root', '--prefix'):
357 | if arg.startswith('%s=' % option):
358 | top_dir = arg.split('root=')[-1]
359 | return location.startswith(top_dir)
360 | elif arg == option:
361 | if len(args) > index:
362 | top_dir = args[index+1]
363 | return location.startswith(top_dir)
364 | if arg == '--user' and USER_SITE is not None:
365 | return location.startswith(USER_SITE)
366 | return True
367 |
368 |
369 | def _fake_setuptools():
370 | log.warn('Scanning installed packages')
371 | try:
372 | import pkg_resources
373 | except ImportError:
374 | # we're cool
375 | log.warn('Setuptools or Distribute does not seem to be installed.')
376 | return
377 | ws = pkg_resources.working_set
378 | try:
379 | setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
380 | replacement=False))
381 | except TypeError:
382 | # old distribute API
383 | setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
384 |
385 | if setuptools_dist is None:
386 | log.warn('No setuptools distribution found')
387 | return
388 | # detecting if it was already faked
389 | setuptools_location = setuptools_dist.location
390 | log.warn('Setuptools installation detected at %s', setuptools_location)
391 |
392 | # if --root or --preix was provided, and if
393 | # setuptools is not located in them, we don't patch it
394 | if not _under_prefix(setuptools_location):
395 | log.warn('Not patching, --root or --prefix is installing Distribute'
396 | ' in another location')
397 | return
398 |
399 | # let's see if its an egg
400 | if not setuptools_location.endswith('.egg'):
401 | log.warn('Non-egg installation')
402 | res = _remove_flat_installation(setuptools_location)
403 | if not res:
404 | return
405 | else:
406 | log.warn('Egg installation')
407 | pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
408 | if (os.path.exists(pkg_info) and
409 | _same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
410 | log.warn('Already patched.')
411 | return
412 | log.warn('Patching...')
413 | # let's create a fake egg replacing setuptools one
414 | res = _patch_egg_dir(setuptools_location)
415 | if not res:
416 | return
417 | log.warn('Patched done.')
418 | _relaunch()
419 |
420 |
421 | def _relaunch():
422 | log.warn('Relaunching...')
423 | # we have to relaunch the process
424 | # pip marker to avoid a relaunch bug
425 | if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']:
426 | sys.argv[0] = 'setup.py'
427 | args = [sys.executable] + sys.argv
428 | sys.exit(subprocess.call(args))
429 |
430 |
431 | def _extractall(self, path=".", members=None):
432 | """Extract all members from the archive to the current working
433 | directory and set owner, modification time and permissions on
434 | directories afterwards. `path' specifies a different directory
435 | to extract to. `members' is optional and must be a subset of the
436 | list returned by getmembers().
437 | """
438 | import copy
439 | import operator
440 | from tarfile import ExtractError
441 | directories = []
442 |
443 | if members is None:
444 | members = self
445 |
446 | for tarinfo in members:
447 | if tarinfo.isdir():
448 | # Extract directories with a safe mode.
449 | directories.append(tarinfo)
450 | tarinfo = copy.copy(tarinfo)
451 | tarinfo.mode = 448 # decimal for oct 0700
452 | self.extract(tarinfo, path)
453 |
454 | # Reverse sort directories.
455 | if sys.version_info < (2, 4):
456 | def sorter(dir1, dir2):
457 | return cmp(dir1.name, dir2.name)
458 | directories.sort(sorter)
459 | directories.reverse()
460 | else:
461 | directories.sort(key=operator.attrgetter('name'), reverse=True)
462 |
463 | # Set correct owner, mtime and filemode on directories.
464 | for tarinfo in directories:
465 | dirpath = os.path.join(path, tarinfo.name)
466 | try:
467 | self.chown(tarinfo, dirpath)
468 | self.utime(tarinfo, dirpath)
469 | self.chmod(tarinfo, dirpath)
470 | except ExtractError:
471 | e = sys.exc_info()[1]
472 | if self.errorlevel > 1:
473 | raise
474 | else:
475 | self._dbg(1, "tarfile: %s" % e)
476 |
477 |
478 | def main(argv, version=DEFAULT_VERSION):
479 | """Install or upgrade setuptools and EasyInstall"""
480 | tarball = download_setuptools()
481 | _install(tarball)
482 |
483 |
484 | if __name__ == '__main__':
485 | main(sys.argv[1:])
486 |
--------------------------------------------------------------------------------
/pydashie/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evolvedlight/pydashie/b93f799596b0e86ea970b26f3a7bf5415bb01e55/pydashie/__init__.py
--------------------------------------------------------------------------------
/pydashie/assets/images/dashie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evolvedlight/pydashie/b93f799596b0e86ea970b26f3a7bf5415bb01e55/pydashie/assets/images/dashie.png
--------------------------------------------------------------------------------
/pydashie/assets/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evolvedlight/pydashie/b93f799596b0e86ea970b26f3a7bf5415bb01e55/pydashie/assets/images/favicon.ico
--------------------------------------------------------------------------------
/pydashie/assets/javascripts/app.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
3 | __hasProp = {}.hasOwnProperty,
4 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
5 |
6 | Dashing.Clock = (function(_super) {
7 |
8 | __extends(Clock, _super);
9 |
10 | function Clock() {
11 | this.startTime = __bind(this.startTime, this);
12 | return Clock.__super__.constructor.apply(this, arguments);
13 | }
14 |
15 | Clock.prototype.ready = function() {
16 | return setInterval(this.startTime, 500);
17 | };
18 |
19 | Clock.prototype.startTime = function() {
20 | var h, m, s, today;
21 | today = new Date();
22 | h = today.getHours();
23 | m = today.getMinutes();
24 | s = today.getSeconds();
25 | m = this.formatTime(m);
26 | s = this.formatTime(s);
27 | this.set('time', h + ":" + m + ":" + s);
28 | return this.set('date', today.toDateString());
29 | };
30 |
31 | Clock.prototype.formatTime = function(i) {
32 | if (i < 10) {
33 | return "0" + i;
34 | } else {
35 | return i;
36 | }
37 | };
38 |
39 | return Clock;
40 |
41 | })(Dashing.Widget);
42 |
43 | }).call(this);
44 | (function() {
45 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
46 | __hasProp = {}.hasOwnProperty,
47 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
48 |
49 | Dashing.Comments = (function(_super) {
50 |
51 | __extends(Comments, _super);
52 |
53 | function Comments() {
54 | this.nextComment = __bind(this.nextComment, this);
55 | return Comments.__super__.constructor.apply(this, arguments);
56 | }
57 |
58 | Comments.accessor('quote', function() {
59 | var _ref;
60 | return "“" + ((_ref = this.get('current_comment')) != null ? _ref.body : void 0) + "â€";
61 | });
62 |
63 | Comments.prototype.ready = function() {
64 | this.currentIndex = 0;
65 | this.commentElem = $(this.node).find('.comment-container');
66 | this.nextComment();
67 | return this.startCarousel();
68 | };
69 |
70 | Comments.prototype.onData = function(data) {
71 | return this.currentIndex = 0;
72 | };
73 |
74 | Comments.prototype.startCarousel = function() {
75 | return setInterval(this.nextComment, 8000);
76 | };
77 |
78 | Comments.prototype.nextComment = function() {
79 | var comments,
80 | _this = this;
81 | comments = this.get('comments');
82 | if (comments) {
83 | return this.commentElem.fadeOut(function() {
84 | _this.currentIndex = (_this.currentIndex + 1) % comments.length;
85 | _this.set('current_comment', comments[_this.currentIndex]);
86 | return _this.commentElem.fadeIn();
87 | });
88 | }
89 | };
90 |
91 | return Comments;
92 |
93 | })(Dashing.Widget);
94 |
95 | }).call(this);
96 | (function() {
97 | var __hasProp = {}.hasOwnProperty,
98 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
99 |
100 | Dashing.Graph = (function(_super) {
101 |
102 | __extends(Graph, _super);
103 |
104 | function Graph() {
105 | return Graph.__super__.constructor.apply(this, arguments);
106 | }
107 |
108 | Graph.accessor('current', function() {
109 | var points;
110 | if (this.get('displayedValue')) {
111 | return this.get('displayedValue');
112 | }
113 | points = this.get('points');
114 | if (points) {
115 | return points[points.length - 1].y;
116 | }
117 | });
118 |
119 | Graph.prototype.ready = function() {
120 | var container, height, width, x_axis, y_axis;
121 | container = $(this.node).parent();
122 | width = (Dashing.widget_base_dimensions[0] * container.data("sizex")) + Dashing.widget_margins[0] * 2 * (container.data("sizex") - 1);
123 | height = Dashing.widget_base_dimensions[1] * container.data("sizey");
124 | this.graph = new Rickshaw.Graph({
125 | element: this.node,
126 | width: width,
127 | height: height,
128 | series: [
129 | {
130 | color: "#fff",
131 | data: [
132 | {
133 | x: 0,
134 | y: 0
135 | }
136 | ]
137 | }
138 | ]
139 | });
140 | if (this.get('points')) {
141 | this.graph.series[0].data = this.get('points');
142 | }
143 | x_axis = new Rickshaw.Graph.Axis.Time({
144 | graph: this.graph
145 | });
146 | y_axis = new Rickshaw.Graph.Axis.Y({
147 | graph: this.graph,
148 | tickFormat: Rickshaw.Fixtures.Number.formatKMBT
149 | });
150 | return this.graph.render();
151 | };
152 |
153 | Graph.prototype.onData = function(data) {
154 | if (this.graph) {
155 | this.graph.series[0].data = data.points;
156 | return this.graph.render();
157 | }
158 | };
159 |
160 | return Graph;
161 |
162 | })(Dashing.Widget);
163 |
164 | }).call(this);
165 | (function() {
166 | var __hasProp = {}.hasOwnProperty,
167 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
168 |
169 | Dashing.Iframe = (function(_super) {
170 |
171 | __extends(Iframe, _super);
172 |
173 | function Iframe() {
174 | return Iframe.__super__.constructor.apply(this, arguments);
175 | }
176 |
177 | Iframe.prototype.ready = function() {};
178 |
179 | Iframe.prototype.onData = function(data) {};
180 |
181 | return Iframe;
182 |
183 | })(Dashing.Widget);
184 |
185 | }).call(this);
186 | (function() {
187 | var __hasProp = {}.hasOwnProperty,
188 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
189 |
190 | Dashing.Image = (function(_super) {
191 |
192 | __extends(Image, _super);
193 |
194 | function Image() {
195 | return Image.__super__.constructor.apply(this, arguments);
196 | }
197 |
198 | Image.prototype.ready = function() {};
199 |
200 | Image.prototype.onData = function(data) {};
201 |
202 | return Image;
203 |
204 | })(Dashing.Widget);
205 |
206 | }).call(this);
207 | (function() {
208 | var __hasProp = {}.hasOwnProperty,
209 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
210 |
211 | Dashing.List = (function(_super) {
212 |
213 | __extends(List, _super);
214 |
215 | function List() {
216 | return List.__super__.constructor.apply(this, arguments);
217 | }
218 |
219 | List.prototype.ready = function() {
220 | if (this.get('unordered')) {
221 | return $(this.node).find('ol').remove();
222 | } else {
223 | return $(this.node).find('ul').remove();
224 | }
225 | };
226 |
227 | return List;
228 |
229 | })(Dashing.Widget);
230 |
231 | }).call(this);
232 | (function() {
233 | var __hasProp = {}.hasOwnProperty,
234 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
235 |
236 | Dashing.Meter = (function(_super) {
237 |
238 | __extends(Meter, _super);
239 |
240 | Meter.accessor('value', Dashing.AnimatedValue);
241 |
242 | function Meter() {
243 | Meter.__super__.constructor.apply(this, arguments);
244 | this.observe('value', function(value) {
245 | return $(this.node).find(".meter").val(value).trigger('change');
246 | });
247 | }
248 |
249 | Meter.prototype.ready = function() {
250 | var meter;
251 | meter = $(this.node).find(".meter");
252 | meter.attr("data-bgcolor", meter.css("background-color"));
253 | meter.attr("data-fgcolor", meter.css("color"));
254 | return meter.knob();
255 | };
256 |
257 | return Meter;
258 |
259 | })(Dashing.Widget);
260 |
261 | }).call(this);
262 | (function() {
263 | var __hasProp = {}.hasOwnProperty,
264 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
265 |
266 | Dashing.Number = (function(_super) {
267 |
268 | __extends(Number, _super);
269 |
270 | function Number() {
271 | return Number.__super__.constructor.apply(this, arguments);
272 | }
273 |
274 | Number.accessor('current', Dashing.AnimatedValue);
275 |
276 | Number.accessor('difference', function() {
277 | var current, diff, last;
278 | if (this.get('last')) {
279 | last = parseInt(this.get('last'));
280 | current = parseInt(this.get('current'));
281 | if (last !== 0) {
282 | diff = Math.abs(Math.round((current - last) / last * 100));
283 | return "" + diff + "%";
284 | }
285 | } else {
286 | return "";
287 | }
288 | });
289 |
290 | Number.accessor('arrow', function() {
291 | if (this.get('last')) {
292 | if (parseInt(this.get('current')) > parseInt(this.get('last'))) {
293 | return 'icon-arrow-up';
294 | } else {
295 | return 'icon-arrow-down';
296 | }
297 | }
298 | });
299 |
300 | Number.accessor('needsAttention', function() {
301 | return this.get('status') === 'warning' || this.get('status') === 'danger';
302 | });
303 |
304 | Number.prototype.onData = function(data) {
305 | if (data.status) {
306 | return $(this.get('node')).addClass("status-" + data.status);
307 | }
308 | };
309 |
310 | return Number;
311 |
312 | })(Dashing.Widget);
313 |
314 | }).call(this);
315 | (function() {
316 | var __hasProp = {}.hasOwnProperty,
317 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
318 |
319 | Dashing.Text = (function(_super) {
320 |
321 | __extends(Text, _super);
322 |
323 | function Text() {
324 | return Text.__super__.constructor.apply(this, arguments);
325 | }
326 |
327 | return Text;
328 |
329 | })(Dashing.Widget);
330 |
331 | }).call(this);
332 | (function() {
333 |
334 | console.log("Yeah! The dashboard has started!");
335 |
336 | Dashing.on('ready', function() {
337 | var contentWidth;
338 | Dashing.widget_margins || (Dashing.widget_margins = [5, 5]);
339 | Dashing.widget_base_dimensions || (Dashing.widget_base_dimensions = [300, 360]);
340 | Dashing.numColumns || (Dashing.numColumns = 4);
341 | contentWidth = (Dashing.widget_base_dimensions[0] + Dashing.widget_margins[0] * 2) * Dashing.numColumns;
342 | return Batman.setImmediate(function() {
343 | $('.gridster').width(contentWidth);
344 | return $('.gridster ul:first').gridster({
345 | widget_margins: Dashing.widget_margins,
346 | widget_base_dimensions: Dashing.widget_base_dimensions,
347 | avoid_overlapped_widgets: !Dashing.customGridsterLayout,
348 | draggable: {
349 | stop: Dashing.showGridsterInstructions
350 | }
351 | });
352 | });
353 | });
354 |
355 | }).call(this);
356 |
--------------------------------------------------------------------------------
/pydashie/assets/javascripts/application.coffee:
--------------------------------------------------------------------------------
1 | console.log("Yeah! The dashboard has started!")
2 |
3 | Dashing.on 'ready', ->
4 | Dashing.widget_margins ||= [5, 5]
5 | Dashing.widget_base_dimensions ||= [300, 360]
6 | Dashing.numColumns ||= 4
7 |
8 | contentWidth = (Dashing.widget_base_dimensions[0] + Dashing.widget_margins[0] * 2) * Dashing.numColumns
9 |
10 | Batman.setImmediate ->
11 | $('.gridster').width(contentWidth)
12 | $('.gridster ul:first').gridster
13 | widget_margins: Dashing.widget_margins
14 | widget_base_dimensions: Dashing.widget_base_dimensions
15 | avoid_overlapped_widgets: !Dashing.customGridsterLayout
16 | draggable:
17 | stop: Dashing.showGridsterInstructions
18 | start: -> Dashing.currentWidgetPositions = Dashing.getWidgetPositions()
19 |
--------------------------------------------------------------------------------
/pydashie/assets/javascripts/dashing.coffee:
--------------------------------------------------------------------------------
1 | #= require jquery
2 | #= require es5-shim
3 | #= require batman
4 | #= require batman.jquery
5 |
6 |
7 | #Batman.Filters.prettyNumber = (num) ->
8 | # num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") unless isNaN(num)
9 | #
10 | #Batman.Filters.dashize = (str) ->
11 | # dashes_rx1 = /([A-Z]+)([A-Z][a-z])/g;
12 | # dashes_rx2 = /([a-z\d])([A-Z])/g;
13 | #
14 | # return str.replace(dashes_rx1, '$1_$2').replace(dashes_rx2, '$1_$2').replace('_', '-').toLowerCase()
15 | #
16 | #Batman.Filters.shortenedNumber = (num) ->
17 | # return num if isNaN(num)
18 | # if num >= 1000000000
19 | # (num / 1000000000).toFixed(1) + 'B'
20 | # else if num >= 1000000
21 | # (num / 1000000).toFixed(1) + 'M'
22 | # else if num >= 1000
23 | # (num / 1000).toFixed(1) + 'K'
24 | # else
25 | # num
26 |
27 | #class window.Dashing extends Batman.App
28 | # @root ->
29 | #Dashing.params = Batman.URI.paramsFromQuery(window.location.search.slice(1));
30 | #
31 | #class Dashing.Widget extends Batman.View
32 | # constructor: ->
33 | # # Set the view path
34 | # @constructor::source = Batman.Filters.underscore(@constructor.name)
35 | # super
36 | #
37 | # @mixin($(@node).data())
38 | # Dashing.widgets[@id] ||= []
39 | # Dashing.widgets[@id].push(@)
40 | # @mixin(Dashing.lastEvents[@id]) # in case the events from the server came before the widget was rendered
41 | #
42 | # type = Batman.Filters.dashize(@view)
43 | # $(@node).addClass("widget widget-#{type} #{@id}")
44 | #
45 | # @accessor 'updatedAtMessage', ->
46 | # if updatedAt = @get('updatedAt')
47 | # timestamp = updatedAt.toString().match(/\d*:\d*/)[0]
48 | # "Last updated at #{timestamp}"
49 | #
50 | # @::on 'ready', ->
51 | # Dashing.Widget.fire 'ready'
52 | #
53 | # receiveData: (data) =>
54 | # @mixin(data)
55 | # @onData(data)
56 | #
57 | # onData: (data) =>
58 | # # Widgets override this to handle incoming data
59 | #
60 |
61 | Dashing.AnimatedValue =
62 | get: Batman.Property.defaultAccessor.get
63 | set: (k, to) ->
64 | if !to? || isNaN(to)
65 | @[k] = to
66 | else
67 | timer = "interval_#{k}"
68 | num = if (!isNaN(@[k]) && @[k]?) then @[k] else 0
69 | unless @[timer] || num == to
70 | to = parseFloat(to)
71 | num = parseFloat(num)
72 | up = to > num
73 | num_interval = Math.abs(num - to) / 90
74 | @[timer] =
75 | setInterval =>
76 | num = if up then Math.ceil(num+num_interval) else Math.floor(num-num_interval)
77 | if (up && num > to) || (!up && num < to)
78 | num = to
79 | clearInterval(@[timer])
80 | @[timer] = null
81 | delete @[timer]
82 | @[k] = num
83 | @set k, to
84 | , 10
85 | @[k] = num
86 |
87 | Dashing.widgets = widgets = {}
88 | Dashing.lastEvents = lastEvents = {}
89 | Dashing.debugMode = false
90 |
91 | source = new EventSource('/events')
92 | source.addEventListener 'open', (e) ->
93 | console.log("Connection opened")
94 |
95 | source.addEventListener 'error', (e)->
96 | console.log("Connection error")
97 | if (e.readyState == EventSource.CLOSED)
98 | console.log("Connection closed")
99 |
100 | source.addEventListener 'message', (e) =>
101 | data = JSON.parse(e.data)
102 | if Dashing.debugMode
103 | console.log("Received data for #{data.id}", data)
104 | lastEvents[data.id] = data
105 | if widgets[data.id]?.length > 0
106 | for widget in widgets[data.id]
107 | widget.receiveData(data)
108 |
109 |
110 | $(document).ready ->
111 | Dashing.run()
112 |
--------------------------------------------------------------------------------
/pydashie/assets/javascripts/dashing.gridster.coffee:
--------------------------------------------------------------------------------
1 | #= require_directory ./gridster
2 |
3 | # This file enables gridster integration (http://gridster.net/)
4 | # Delete it if you'd rather handle the layout yourself.
5 | # You'll miss out on a lot if you do, but we won't hold it against you.
6 |
7 | Dashing.gridsterLayout = (positions) ->
8 | Dashing.customGridsterLayout = true
9 | positions = positions.replace(/^"|"$/g, '')
10 | positions = $.parseJSON(positions)
11 | widgets = $("[data-row^=]")
12 | for widget, index in widgets
13 | $(widget).attr('data-row', positions[index].row)
14 | $(widget).attr('data-col', positions[index].col)
15 |
16 | Dashing.showGridsterInstructions = ->
17 | data = $(".gridster ul:first").gridster().data('gridster').serialize();
18 | $('#save-gridster').slideDown();
19 | return $('#gridster-code').text(" ")
20 |
21 | $ ->
22 | $('#save-gridster').leanModal()
23 |
24 | $('#save-gridster').click ->
25 | $('#save-gridster').slideUp()
26 |
--------------------------------------------------------------------------------
/pydashie/assets/javascripts/es5-shim.js:
--------------------------------------------------------------------------------
1 | // vim: ts=4 sts=4 sw=4 expandtab
2 | // -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License
3 | // -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)
4 | // -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA
5 | // -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License
6 | // -- Gozala Irakli Gozalishvili Copyright (C) 2010 MIT License
7 | // -- kitcambridge Kit Cambridge Copyright (C) 2011 MIT License
8 | // -- kossnocorp Sasha Koss XXX TODO License or CLA
9 | // -- bryanforbes Bryan Forbes XXX TODO License or CLA
10 | // -- killdream Quildreen Motta Copyright (C) 2011 MIT Licence
11 | // -- michaelficarra Michael Ficarra Copyright (C) 2011 3-clause BSD License
12 | // -- sharkbrainguy Gerard Paapu Copyright (C) 2011 MIT License
13 | // -- bbqsrc Brendan Molloy XXX TODO License or CLA
14 | // -- iwyg XXX TODO License or CLA
15 | // -- DomenicDenicola Domenic Denicola XXX TODO License or CLA
16 | // -- xavierm02 Montillet Xavier XXX TODO License or CLA
17 | // -- Raynos Raynos XXX TODO License or CLA
18 | // -- samsonjs Sami Samhuri XXX TODO License or CLA
19 | // -- rwldrn Rick Waldron Copyright (C) 2011 MIT License
20 | // -- lexer Alexey Zakharov XXX TODO License or CLA
21 |
22 | /*!
23 | Copyright (c) 2009, 280 North Inc. http://280north.com/
24 | MIT License. http://github.com/280north/narwhal/blob/master/README.md
25 | */
26 |
27 | // Module systems magic dance
28 | (function (definition) {
29 | // RequireJS
30 | if (typeof define == "function") {
31 | define(definition);
32 | // CommonJS and
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 |