Merge branch 'development'
Conflicts: setup.py src/jsoninspector/jsoninspector.py
This commit is contained in:
commit
9e323703a5
17 changed files with 2006 additions and 688 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -7,6 +7,8 @@
|
|||
*.o
|
||||
*.so
|
||||
*.pyc
|
||||
*.egg
|
||||
*.egg-info
|
||||
|
||||
# Packages #
|
||||
############
|
||||
|
@ -42,6 +44,9 @@ Thumbs.db
|
|||
# Vim swap files
|
||||
*.swp
|
||||
|
||||
# png files
|
||||
*.png
|
||||
|
||||
# Virtualenv ignore
|
||||
bin/
|
||||
lib/
|
||||
|
|
|
@ -1,481 +0,0 @@
|
|||
#!python
|
||||
"""Bootstrap distribute installation
|
||||
|
||||
If you want to use setuptools in your package's setup.py, just include this
|
||||
file in the same directory with it, and add this to the top of your setup.py::
|
||||
|
||||
from distribute_setup import use_setuptools
|
||||
use_setuptools()
|
||||
|
||||
If you want to require a specific version of setuptools, set a download
|
||||
mirror, or use an alternate download directory, you can do so by supplying
|
||||
the appropriate options to ``use_setuptools()``.
|
||||
|
||||
This file can also be run as a script to install or upgrade setuptools.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import fnmatch
|
||||
import tempfile
|
||||
import tarfile
|
||||
from distutils import log
|
||||
|
||||
try:
|
||||
from site import USER_SITE
|
||||
except ImportError:
|
||||
USER_SITE = None
|
||||
|
||||
try:
|
||||
import subprocess
|
||||
|
||||
def _python_cmd(*args):
|
||||
args = (sys.executable,) + args
|
||||
return subprocess.call(args) == 0
|
||||
|
||||
except ImportError:
|
||||
# will be used for python 2.3
|
||||
def _python_cmd(*args):
|
||||
args = (sys.executable,) + args
|
||||
# quoting arguments if windows
|
||||
if sys.platform == 'win32':
|
||||
def quote(arg):
|
||||
if ' ' in arg:
|
||||
return '"%s"' % arg
|
||||
return arg
|
||||
args = [quote(arg) for arg in args]
|
||||
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||
|
||||
DEFAULT_VERSION = "0.6.12"
|
||||
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||
|
||||
SETUPTOOLS_PKG_INFO = """\
|
||||
Metadata-Version: 1.0
|
||||
Name: setuptools
|
||||
Version: %s
|
||||
Summary: xxxx
|
||||
Home-page: xxx
|
||||
Author: xxx
|
||||
Author-email: xxx
|
||||
License: xxx
|
||||
Description: xxx
|
||||
""" % SETUPTOOLS_FAKED_VERSION
|
||||
|
||||
|
||||
def _install(tarball):
|
||||
# extracting the tarball
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
log.warn('Extracting in %s', tmpdir)
|
||||
old_wd = os.getcwd()
|
||||
try:
|
||||
os.chdir(tmpdir)
|
||||
tar = tarfile.open(tarball)
|
||||
_extractall(tar)
|
||||
tar.close()
|
||||
|
||||
# going in the directory
|
||||
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||
os.chdir(subdir)
|
||||
log.warn('Now working in %s', subdir)
|
||||
|
||||
# installing
|
||||
log.warn('Installing Distribute')
|
||||
if not _python_cmd('setup.py', 'install'):
|
||||
log.warn('Something went wrong during the installation.')
|
||||
log.warn('See the error message above.')
|
||||
finally:
|
||||
os.chdir(old_wd)
|
||||
|
||||
|
||||
def _build_egg(egg, tarball, to_dir):
|
||||
# extracting the tarball
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
log.warn('Extracting in %s', tmpdir)
|
||||
old_wd = os.getcwd()
|
||||
try:
|
||||
os.chdir(tmpdir)
|
||||
tar = tarfile.open(tarball)
|
||||
_extractall(tar)
|
||||
tar.close()
|
||||
|
||||
# going in the directory
|
||||
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||
os.chdir(subdir)
|
||||
log.warn('Now working in %s', subdir)
|
||||
|
||||
# building an egg
|
||||
log.warn('Building a Distribute egg in %s', to_dir)
|
||||
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||
|
||||
finally:
|
||||
os.chdir(old_wd)
|
||||
# returning the result
|
||||
log.warn(egg)
|
||||
if not os.path.exists(egg):
|
||||
raise IOError('Could not build the egg.')
|
||||
|
||||
|
||||
def _do_download(version, download_base, to_dir, download_delay):
|
||||
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||
% (version, sys.version_info[0], sys.version_info[1]))
|
||||
if not os.path.exists(egg):
|
||||
tarball = download_setuptools(version, download_base,
|
||||
to_dir, download_delay)
|
||||
_build_egg(egg, tarball, to_dir)
|
||||
sys.path.insert(0, egg)
|
||||
import setuptools
|
||||
setuptools.bootstrap_install_from = egg
|
||||
|
||||
|
||||
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||
# making sure we use the absolute path
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
was_imported = 'pkg_resources' in sys.modules or \
|
||||
'setuptools' in sys.modules
|
||||
try:
|
||||
try:
|
||||
import pkg_resources
|
||||
if not hasattr(pkg_resources, '_distribute'):
|
||||
if not no_fake:
|
||||
_fake_setuptools()
|
||||
raise ImportError
|
||||
except ImportError:
|
||||
return _do_download(version, download_base, to_dir, download_delay)
|
||||
try:
|
||||
pkg_resources.require("distribute>="+version)
|
||||
return
|
||||
except pkg_resources.VersionConflict:
|
||||
e = sys.exc_info()[1]
|
||||
if was_imported:
|
||||
sys.stderr.write(
|
||||
"The required version of distribute (>=%s) is not available,\n"
|
||||
"and can't be installed while this script is running. Please\n"
|
||||
"install a more recent version first, using\n"
|
||||
"'easy_install -U distribute'."
|
||||
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||
sys.exit(2)
|
||||
else:
|
||||
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||
return _do_download(version, download_base, to_dir,
|
||||
download_delay)
|
||||
except pkg_resources.DistributionNotFound:
|
||||
return _do_download(version, download_base, to_dir,
|
||||
download_delay)
|
||||
finally:
|
||||
if not no_fake:
|
||||
_create_fake_setuptools_pkg_info(to_dir)
|
||||
|
||||
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||
to_dir=os.curdir, delay=15):
|
||||
"""Download distribute from a specified location and return its filename
|
||||
|
||||
`version` should be a valid distribute version number that is available
|
||||
as an egg for download under the `download_base` URL (which should end
|
||||
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||
`delay` is the number of seconds to pause before an actual download
|
||||
attempt.
|
||||
"""
|
||||
# making sure we use the absolute path
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib2 import urlopen
|
||||
tgz_name = "distribute-%s.tar.gz" % version
|
||||
url = download_base + tgz_name
|
||||
saveto = os.path.join(to_dir, tgz_name)
|
||||
src = dst = None
|
||||
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||
try:
|
||||
log.warn("Downloading %s", url)
|
||||
src = urlopen(url)
|
||||
# Read/write all in one block, so we don't create a corrupt file
|
||||
# if the download is interrupted.
|
||||
data = src.read()
|
||||
dst = open(saveto, "wb")
|
||||
dst.write(data)
|
||||
finally:
|
||||
if src:
|
||||
src.close()
|
||||
if dst:
|
||||
dst.close()
|
||||
return os.path.realpath(saveto)
|
||||
|
||||
def _no_sandbox(function):
|
||||
def __no_sandbox(*args, **kw):
|
||||
try:
|
||||
from setuptools.sandbox import DirectorySandbox
|
||||
if not hasattr(DirectorySandbox, '_old'):
|
||||
def violation(*args):
|
||||
pass
|
||||
DirectorySandbox._old = DirectorySandbox._violation
|
||||
DirectorySandbox._violation = violation
|
||||
patched = True
|
||||
else:
|
||||
patched = False
|
||||
except ImportError:
|
||||
patched = False
|
||||
|
||||
try:
|
||||
return function(*args, **kw)
|
||||
finally:
|
||||
if patched:
|
||||
DirectorySandbox._violation = DirectorySandbox._old
|
||||
del DirectorySandbox._old
|
||||
|
||||
return __no_sandbox
|
||||
|
||||
@_no_sandbox
|
||||
def _patch_file(path, content):
|
||||
"""Will backup the file then patch it"""
|
||||
existing_content = open(path).read()
|
||||
if existing_content == content:
|
||||
# already patched
|
||||
log.warn('Already patched.')
|
||||
return False
|
||||
log.warn('Patching...')
|
||||
_rename_path(path)
|
||||
f = open(path, 'w')
|
||||
try:
|
||||
f.write(content)
|
||||
finally:
|
||||
f.close()
|
||||
return True
|
||||
|
||||
|
||||
def _same_content(path, content):
|
||||
return open(path).read() == content
|
||||
|
||||
def _rename_path(path):
|
||||
new_name = path + '.OLD.%s' % time.time()
|
||||
log.warn('Renaming %s into %s', path, new_name)
|
||||
os.rename(path, new_name)
|
||||
return new_name
|
||||
|
||||
@_no_sandbox
|
||||
def _remove_flat_installation(placeholder):
|
||||
if not os.path.isdir(placeholder):
|
||||
log.warn('Unkown installation at %s', placeholder)
|
||||
return False
|
||||
found = False
|
||||
for file in os.listdir(placeholder):
|
||||
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
log.warn('Could not locate setuptools*.egg-info')
|
||||
return
|
||||
|
||||
log.warn('Removing elements out of the way...')
|
||||
pkg_info = os.path.join(placeholder, file)
|
||||
if os.path.isdir(pkg_info):
|
||||
patched = _patch_egg_dir(pkg_info)
|
||||
else:
|
||||
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||
|
||||
if not patched:
|
||||
log.warn('%s already patched.', pkg_info)
|
||||
return False
|
||||
# now let's move the files out of the way
|
||||
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||
element = os.path.join(placeholder, element)
|
||||
if os.path.exists(element):
|
||||
_rename_path(element)
|
||||
else:
|
||||
log.warn('Could not find the %s element of the '
|
||||
'Setuptools distribution', element)
|
||||
return True
|
||||
|
||||
|
||||
def _after_install(dist):
|
||||
log.warn('After install bootstrap.')
|
||||
placeholder = dist.get_command_obj('install').install_purelib
|
||||
_create_fake_setuptools_pkg_info(placeholder)
|
||||
|
||||
@_no_sandbox
|
||||
def _create_fake_setuptools_pkg_info(placeholder):
|
||||
if not placeholder or not os.path.exists(placeholder):
|
||||
log.warn('Could not find the install location')
|
||||
return
|
||||
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||
if os.path.exists(pkg_info):
|
||||
log.warn('%s already exists', pkg_info)
|
||||
return
|
||||
|
||||
log.warn('Creating %s', pkg_info)
|
||||
f = open(pkg_info, 'w')
|
||||
try:
|
||||
f.write(SETUPTOOLS_PKG_INFO)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||
log.warn('Creating %s', pth_file)
|
||||
f = open(pth_file, 'w')
|
||||
try:
|
||||
f.write(os.path.join(os.curdir, setuptools_file))
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
@_no_sandbox
|
||||
def _patch_egg_dir(path):
|
||||
# let's check if it's already patched
|
||||
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||
if os.path.exists(pkg_info):
|
||||
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||
log.warn('%s already patched.', pkg_info)
|
||||
return False
|
||||
_rename_path(path)
|
||||
os.mkdir(path)
|
||||
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||
f = open(pkg_info, 'w')
|
||||
try:
|
||||
f.write(SETUPTOOLS_PKG_INFO)
|
||||
finally:
|
||||
f.close()
|
||||
return True
|
||||
|
||||
|
||||
def _before_install():
|
||||
log.warn('Before install bootstrap.')
|
||||
_fake_setuptools()
|
||||
|
||||
|
||||
def _under_prefix(location):
|
||||
if 'install' not in sys.argv:
|
||||
return True
|
||||
args = sys.argv[sys.argv.index('install')+1:]
|
||||
for index, arg in enumerate(args):
|
||||
for option in ('--root', '--prefix'):
|
||||
if arg.startswith('%s=' % option):
|
||||
top_dir = arg.split('root=')[-1]
|
||||
return location.startswith(top_dir)
|
||||
elif arg == option:
|
||||
if len(args) > index:
|
||||
top_dir = args[index+1]
|
||||
return location.startswith(top_dir)
|
||||
elif option == '--user' and USER_SITE is not None:
|
||||
return location.startswith(USER_SITE)
|
||||
return True
|
||||
|
||||
|
||||
def _fake_setuptools():
|
||||
log.warn('Scanning installed packages')
|
||||
try:
|
||||
import pkg_resources
|
||||
except ImportError:
|
||||
# we're cool
|
||||
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||
return
|
||||
ws = pkg_resources.working_set
|
||||
try:
|
||||
setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
|
||||
replacement=False))
|
||||
except TypeError:
|
||||
# old distribute API
|
||||
setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
|
||||
|
||||
if setuptools_dist is None:
|
||||
log.warn('No setuptools distribution found')
|
||||
return
|
||||
# detecting if it was already faked
|
||||
setuptools_location = setuptools_dist.location
|
||||
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||
|
||||
# if --root or --preix was provided, and if
|
||||
# setuptools is not located in them, we don't patch it
|
||||
if not _under_prefix(setuptools_location):
|
||||
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||
' in another location')
|
||||
return
|
||||
|
||||
# let's see if its an egg
|
||||
if not setuptools_location.endswith('.egg'):
|
||||
log.warn('Non-egg installation')
|
||||
res = _remove_flat_installation(setuptools_location)
|
||||
if not res:
|
||||
return
|
||||
else:
|
||||
log.warn('Egg installation')
|
||||
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||
if (os.path.exists(pkg_info) and
|
||||
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||
log.warn('Already patched.')
|
||||
return
|
||||
log.warn('Patching...')
|
||||
# let's create a fake egg replacing setuptools one
|
||||
res = _patch_egg_dir(setuptools_location)
|
||||
if not res:
|
||||
return
|
||||
log.warn('Patched done.')
|
||||
_relaunch()
|
||||
|
||||
|
||||
def _relaunch():
|
||||
log.warn('Relaunching...')
|
||||
# we have to relaunch the process
|
||||
args = [sys.executable] + sys.argv
|
||||
sys.exit(subprocess.call(args))
|
||||
|
||||
|
||||
def _extractall(self, path=".", members=None):
|
||||
"""Extract all members from the archive to the current working
|
||||
directory and set owner, modification time and permissions on
|
||||
directories afterwards. `path' specifies a different directory
|
||||
to extract to. `members' is optional and must be a subset of the
|
||||
list returned by getmembers().
|
||||
"""
|
||||
import copy
|
||||
import operator
|
||||
from tarfile import ExtractError
|
||||
directories = []
|
||||
|
||||
if members is None:
|
||||
members = self
|
||||
|
||||
for tarinfo in members:
|
||||
if tarinfo.isdir():
|
||||
# Extract directories with a safe mode.
|
||||
directories.append(tarinfo)
|
||||
tarinfo = copy.copy(tarinfo)
|
||||
tarinfo.mode = 448 # decimal for oct 0700
|
||||
self.extract(tarinfo, path)
|
||||
|
||||
# Reverse sort directories.
|
||||
if sys.version_info < (2, 4):
|
||||
def sorter(dir1, dir2):
|
||||
return cmp(dir1.name, dir2.name)
|
||||
directories.sort(sorter)
|
||||
directories.reverse()
|
||||
else:
|
||||
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||
|
||||
# Set correct owner, mtime and filemode on directories.
|
||||
for tarinfo in directories:
|
||||
dirpath = os.path.join(path, tarinfo.name)
|
||||
try:
|
||||
self.chown(tarinfo, dirpath)
|
||||
self.utime(tarinfo, dirpath)
|
||||
self.chmod(tarinfo, dirpath)
|
||||
except ExtractError:
|
||||
e = sys.exc_info()[1]
|
||||
if self.errorlevel > 1:
|
||||
raise
|
||||
else:
|
||||
self._dbg(1, "tarfile: %s" % e)
|
||||
|
||||
|
||||
def main(argv, version=DEFAULT_VERSION):
|
||||
"""Install or upgrade setuptools and EasyInstall"""
|
||||
tarball = download_setuptools()
|
||||
_install(tarball)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
332
ez_setup.py
Normal file
332
ez_setup.py
Normal file
|
@ -0,0 +1,332 @@
|
|||
#!/usr/bin/env python
|
||||
"""Bootstrap setuptools installation
|
||||
|
||||
To use setuptools in your package's setup.py, include this
|
||||
file in the same directory and add this to the top of your setup.py::
|
||||
|
||||
from ez_setup import use_setuptools
|
||||
use_setuptools()
|
||||
|
||||
To require a specific version of setuptools, set a download
|
||||
mirror, or use an alternate download directory, simply supply
|
||||
the appropriate options to ``use_setuptools()``.
|
||||
|
||||
This file can also be run as a script to install or upgrade setuptools.
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import zipfile
|
||||
import optparse
|
||||
import subprocess
|
||||
import platform
|
||||
import textwrap
|
||||
import contextlib
|
||||
|
||||
from distutils import log
|
||||
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib2 import urlopen
|
||||
|
||||
try:
|
||||
from site import USER_SITE
|
||||
except ImportError:
|
||||
USER_SITE = None
|
||||
|
||||
DEFAULT_VERSION = "5.4.1"
|
||||
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
|
||||
|
||||
def _python_cmd(*args):
|
||||
"""
|
||||
Return True if the command succeeded.
|
||||
"""
|
||||
args = (sys.executable,) + args
|
||||
return subprocess.call(args) == 0
|
||||
|
||||
|
||||
def _install(archive_filename, install_args=()):
|
||||
with archive_context(archive_filename):
|
||||
# installing
|
||||
log.warn('Installing Setuptools')
|
||||
if not _python_cmd('setup.py', 'install', *install_args):
|
||||
log.warn('Something went wrong during the installation.')
|
||||
log.warn('See the error message above.')
|
||||
# exitcode will be 2
|
||||
return 2
|
||||
|
||||
|
||||
def _build_egg(egg, archive_filename, to_dir):
|
||||
with archive_context(archive_filename):
|
||||
# building an egg
|
||||
log.warn('Building a Setuptools egg in %s', to_dir)
|
||||
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||
# returning the result
|
||||
log.warn(egg)
|
||||
if not os.path.exists(egg):
|
||||
raise IOError('Could not build the egg.')
|
||||
|
||||
|
||||
class ContextualZipFile(zipfile.ZipFile):
|
||||
"""
|
||||
Supplement ZipFile class to support context manager for Python 2.6
|
||||
"""
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.close()
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
"""
|
||||
Construct a ZipFile or ContextualZipFile as appropriate
|
||||
"""
|
||||
if hasattr(zipfile.ZipFile, '__exit__'):
|
||||
return zipfile.ZipFile(*args, **kwargs)
|
||||
return super(ContextualZipFile, cls).__new__(cls)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def archive_context(filename):
|
||||
# extracting the archive
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
log.warn('Extracting in %s', tmpdir)
|
||||
old_wd = os.getcwd()
|
||||
try:
|
||||
os.chdir(tmpdir)
|
||||
with ContextualZipFile(filename) as archive:
|
||||
archive.extractall()
|
||||
|
||||
# going in the directory
|
||||
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||
os.chdir(subdir)
|
||||
log.warn('Now working in %s', subdir)
|
||||
yield
|
||||
|
||||
finally:
|
||||
os.chdir(old_wd)
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
|
||||
def _do_download(version, download_base, to_dir, download_delay):
|
||||
egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg'
|
||||
% (version, sys.version_info[0], sys.version_info[1]))
|
||||
if not os.path.exists(egg):
|
||||
archive = download_setuptools(version, download_base,
|
||||
to_dir, download_delay)
|
||||
_build_egg(egg, archive, to_dir)
|
||||
sys.path.insert(0, egg)
|
||||
|
||||
# Remove previously-imported pkg_resources if present (see
|
||||
# https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
|
||||
if 'pkg_resources' in sys.modules:
|
||||
del sys.modules['pkg_resources']
|
||||
|
||||
import setuptools
|
||||
setuptools.bootstrap_install_from = egg
|
||||
|
||||
|
||||
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||
to_dir=os.curdir, download_delay=15):
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
rep_modules = 'pkg_resources', 'setuptools'
|
||||
imported = set(sys.modules).intersection(rep_modules)
|
||||
try:
|
||||
import pkg_resources
|
||||
except ImportError:
|
||||
return _do_download(version, download_base, to_dir, download_delay)
|
||||
try:
|
||||
pkg_resources.require("setuptools>=" + version)
|
||||
return
|
||||
except pkg_resources.DistributionNotFound:
|
||||
return _do_download(version, download_base, to_dir, download_delay)
|
||||
except pkg_resources.VersionConflict as VC_err:
|
||||
if imported:
|
||||
msg = textwrap.dedent("""
|
||||
The required version of setuptools (>={version}) is not available,
|
||||
and can't be installed while this script is running. Please
|
||||
install a more recent version first, using
|
||||
'easy_install -U setuptools'.
|
||||
|
||||
(Currently using {VC_err.args[0]!r})
|
||||
""").format(VC_err=VC_err, version=version)
|
||||
sys.stderr.write(msg)
|
||||
sys.exit(2)
|
||||
|
||||
# otherwise, reload ok
|
||||
del pkg_resources, sys.modules['pkg_resources']
|
||||
return _do_download(version, download_base, to_dir, download_delay)
|
||||
|
||||
def _clean_check(cmd, target):
|
||||
"""
|
||||
Run the command to download target. If the command fails, clean up before
|
||||
re-raising the error.
|
||||
"""
|
||||
try:
|
||||
subprocess.check_call(cmd)
|
||||
except subprocess.CalledProcessError:
|
||||
if os.access(target, os.F_OK):
|
||||
os.unlink(target)
|
||||
raise
|
||||
|
||||
def download_file_powershell(url, target):
|
||||
"""
|
||||
Download the file at url to target using Powershell (which will validate
|
||||
trust). Raise an exception if the command cannot complete.
|
||||
"""
|
||||
target = os.path.abspath(target)
|
||||
ps_cmd = (
|
||||
"[System.Net.WebRequest]::DefaultWebProxy.Credentials = "
|
||||
"[System.Net.CredentialCache]::DefaultCredentials; "
|
||||
"(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)"
|
||||
% vars()
|
||||
)
|
||||
cmd = [
|
||||
'powershell',
|
||||
'-Command',
|
||||
ps_cmd,
|
||||
]
|
||||
_clean_check(cmd, target)
|
||||
|
||||
def has_powershell():
|
||||
if platform.system() != 'Windows':
|
||||
return False
|
||||
cmd = ['powershell', '-Command', 'echo test']
|
||||
with open(os.path.devnull, 'wb') as devnull:
|
||||
try:
|
||||
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
download_file_powershell.viable = has_powershell
|
||||
|
||||
def download_file_curl(url, target):
|
||||
cmd = ['curl', url, '--silent', '--output', target]
|
||||
_clean_check(cmd, target)
|
||||
|
||||
def has_curl():
|
||||
cmd = ['curl', '--version']
|
||||
with open(os.path.devnull, 'wb') as devnull:
|
||||
try:
|
||||
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
download_file_curl.viable = has_curl
|
||||
|
||||
def download_file_wget(url, target):
|
||||
cmd = ['wget', url, '--quiet', '--output-document', target]
|
||||
_clean_check(cmd, target)
|
||||
|
||||
def has_wget():
|
||||
cmd = ['wget', '--version']
|
||||
with open(os.path.devnull, 'wb') as devnull:
|
||||
try:
|
||||
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
download_file_wget.viable = has_wget
|
||||
|
||||
def download_file_insecure(url, target):
|
||||
"""
|
||||
Use Python to download the file, even though it cannot authenticate the
|
||||
connection.
|
||||
"""
|
||||
src = urlopen(url)
|
||||
try:
|
||||
# Read all the data in one block.
|
||||
data = src.read()
|
||||
finally:
|
||||
src.close()
|
||||
|
||||
# Write all the data in one block to avoid creating a partial file.
|
||||
with open(target, "wb") as dst:
|
||||
dst.write(data)
|
||||
|
||||
download_file_insecure.viable = lambda: True
|
||||
|
||||
def get_best_downloader():
|
||||
downloaders = (
|
||||
download_file_powershell,
|
||||
download_file_curl,
|
||||
download_file_wget,
|
||||
download_file_insecure,
|
||||
)
|
||||
viable_downloaders = (dl for dl in downloaders if dl.viable())
|
||||
return next(viable_downloaders, None)
|
||||
|
||||
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||
to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader):
|
||||
"""
|
||||
Download setuptools from a specified location and return its filename
|
||||
|
||||
`version` should be a valid setuptools version number that is available
|
||||
as an egg for download under the `download_base` URL (which should end
|
||||
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||
`delay` is the number of seconds to pause before an actual download
|
||||
attempt.
|
||||
|
||||
``downloader_factory`` should be a function taking no arguments and
|
||||
returning a function for downloading a URL to a target.
|
||||
"""
|
||||
# making sure we use the absolute path
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
zip_name = "setuptools-%s.zip" % version
|
||||
url = download_base + zip_name
|
||||
saveto = os.path.join(to_dir, zip_name)
|
||||
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||
log.warn("Downloading %s", url)
|
||||
downloader = downloader_factory()
|
||||
downloader(url, saveto)
|
||||
return os.path.realpath(saveto)
|
||||
|
||||
def _build_install_args(options):
|
||||
"""
|
||||
Build the arguments to 'python setup.py install' on the setuptools package
|
||||
"""
|
||||
return ['--user'] if options.user_install else []
|
||||
|
||||
def _parse_args():
|
||||
"""
|
||||
Parse the command line for options
|
||||
"""
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option(
|
||||
'--user', dest='user_install', action='store_true', default=False,
|
||||
help='install in user site package (requires Python 2.6 or later)')
|
||||
parser.add_option(
|
||||
'--download-base', dest='download_base', metavar="URL",
|
||||
default=DEFAULT_URL,
|
||||
help='alternative URL from where to download the setuptools package')
|
||||
parser.add_option(
|
||||
'--insecure', dest='downloader_factory', action='store_const',
|
||||
const=lambda: download_file_insecure, default=get_best_downloader,
|
||||
help='Use internal, non-validating downloader'
|
||||
)
|
||||
parser.add_option(
|
||||
'--version', help="Specify which version to download",
|
||||
default=DEFAULT_VERSION,
|
||||
)
|
||||
options, args = parser.parse_args()
|
||||
# positional arguments are ignored
|
||||
return options
|
||||
|
||||
def main():
|
||||
"""Install or upgrade setuptools and EasyInstall"""
|
||||
options = _parse_args()
|
||||
archive = download_setuptools(
|
||||
version=options.version,
|
||||
download_base=options.download_base,
|
||||
downloader_factory=options.downloader_factory,
|
||||
)
|
||||
return _install(archive, _build_install_args(options))
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
BIN
locale/es.mo
Normal file
BIN
locale/es.mo
Normal file
Binary file not shown.
80
locale/es.po
Normal file
80
locale/es.po
Normal file
|
@ -0,0 +1,80 @@
|
|||
# Spanish translations for PACKAGE package
|
||||
# Traducciones al español para el paquete PACKAGE.
|
||||
# Copyright (C) 2014 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# José Carlos Cuevas <reset@localhost>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-07-14 12:52+0200\n"
|
||||
"PO-Revision-Date: 2014-07-14 12:54+0100\n"
|
||||
"Last-Translator: José Carlos Cuevas <reset@localhost>\n"
|
||||
"Language-Team: Spanish\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
|
||||
#: jsoninspector.py:81
|
||||
msgid "Open JSON text file"
|
||||
msgstr "Abrir archivo de texto JSON"
|
||||
|
||||
#: jsoninspector.py:104
|
||||
msgid "No JSON loaded."
|
||||
msgstr "No se ha cargado JSON."
|
||||
|
||||
#: jsoninspector.py:152
|
||||
msgid "Loaded from the clipboard."
|
||||
msgstr "Cargado desde el portapapeles."
|
||||
|
||||
#: jsoninspector.py:194
|
||||
msgid "Not valid JSON!\n"
|
||||
msgstr "JSON no válido!\n"
|
||||
|
||||
#: jsoninspector.py:210
|
||||
msgid "Not valid JSON"
|
||||
msgstr "JSON no válido"
|
||||
|
||||
#: jsoninspector.glade.h:1
|
||||
msgid "About"
|
||||
msgstr "Acerca de"
|
||||
|
||||
#: jsoninspector.glade.h:2
|
||||
msgid "Enter JSON Text"
|
||||
msgstr "Introduzca texto JSON"
|
||||
|
||||
#: jsoninspector.glade.h:3
|
||||
msgid "JSON Inspector"
|
||||
msgstr "JSON Inspector"
|
||||
|
||||
#: jsoninspector.glade.h:4
|
||||
msgid "_File"
|
||||
msgstr "_Archivo"
|
||||
|
||||
#: jsoninspector.glade.h:5
|
||||
msgid "Cop_y JSON"
|
||||
msgstr "_Copiar JSON"
|
||||
|
||||
#: jsoninspector.glade.h:6
|
||||
msgid "_Help"
|
||||
msgstr "A_yuda"
|
||||
|
||||
#: jsoninspector.glade.h:7
|
||||
msgid "Node"
|
||||
msgstr "Nodo"
|
||||
|
||||
#: jsoninspector.glade.h:8
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#: jsoninspector.glade.h:9
|
||||
msgid "Type"
|
||||
msgstr "Tipo"
|
||||
|
||||
#: jsoninspector.glade.h:10
|
||||
msgid "No JSON loaded"
|
||||
msgstr "No se ha cargado JSON"
|
78
locale/messages.pot
Normal file
78
locale/messages.pot
Normal file
|
@ -0,0 +1,78 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-07-14 12:52+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: jsoninspector.py:81
|
||||
msgid "Open JSON text file"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.py:104
|
||||
msgid "No JSON loaded."
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.py:152
|
||||
msgid "Loaded from the clipboard."
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.py:194
|
||||
msgid "Not valid JSON!\n"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.py:210
|
||||
msgid "Not valid JSON"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:1
|
||||
msgid "About"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:2
|
||||
msgid "Enter JSON Text"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:3
|
||||
msgid "JSON Inspector"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:4
|
||||
msgid "_File"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:5
|
||||
msgid "Cop_y JSON"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:6
|
||||
msgid "_Help"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:7
|
||||
msgid "Node"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:8
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:9
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: jsoninspector.glade.h:10
|
||||
msgid "No JSON loaded"
|
||||
msgstr ""
|
BIN
locale/po/es/LC_MESSAGES/jsoninspector.mo
Normal file
BIN
locale/po/es/LC_MESSAGES/jsoninspector.mo
Normal file
Binary file not shown.
15
res/get_sizes.sh
Executable file
15
res/get_sizes.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
SIZES=( 16x16 22x22 24x24 32x32 36x36 48x48 64x64 72x72 96x96 128x128 192x192 256x256 )
|
||||
|
||||
# If we can't find the svg, cd into res, we're
|
||||
# probably being called from the root of
|
||||
# the source tree
|
||||
if [ ! -e jsoninspector.svg ]; then
|
||||
cd res
|
||||
fi
|
||||
|
||||
for s in "${SIZES[@]}"; do
|
||||
echo "Creating $s image from svg" ;
|
||||
convert -background none jsoninspector.svg -resize $s jsoninspector$s.png
|
||||
done
|
7
res/jsoninspector.desktop
Normal file
7
res/jsoninspector.desktop
Normal file
|
@ -0,0 +1,7 @@
|
|||
[Desktop Entry]
|
||||
Comment=Lightweight JSON utility to inspect JSON documents
|
||||
Terminal=false
|
||||
Name=JSON Inspector
|
||||
Exec=jsoninspector
|
||||
Type=Application
|
||||
Icon=jsoninspector
|
|
@ -1,7 +1,165 @@
|
|||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="2.16"/>
|
||||
<!-- interface-naming-policy project-wide -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.16.1 -->
|
||||
<interface domain="jsoninspector">
|
||||
<requires lib="gtk+" version="3.6"/>
|
||||
<object class="GtkAboutDialog" id="AboutDialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">About</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window_position">center-on-parent</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="icon_name">jsoninspector</property>
|
||||
<property name="type_hint">normal</property>
|
||||
<property name="deletable">False</property>
|
||||
<property name="gravity">center</property>
|
||||
<property name="has_resize_grip">False</property>
|
||||
<property name="program_name">JSON Inspector</property>
|
||||
<property name="version">v2.0</property>
|
||||
<property name="website">https://github.com/resetreboot/jsoninspector</property>
|
||||
<property name="website_label">https://github.com/resetreboot/jsoninspector</property>
|
||||
<property name="authors">José Carlos Cuevas Albadalejo</property>
|
||||
<property name="translator_credits">José Carlos Cuevas Albadalejo</property>
|
||||
<property name="logo_icon_name">jsoninspector</property>
|
||||
<property name="license_type">gpl-3-0</property>
|
||||
<signal name="close" handler="onAboutDialogClose" swapped="no"/>
|
||||
<signal name="delete-event" handler="onAboutDialogDeleteEvent" swapped="no"/>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="aboutdialog-vbox1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="aboutdialog-action_area1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="TextWindow">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Enter JSON Text</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="default_width">200</property>
|
||||
<property name="default_height">180</property>
|
||||
<property name="icon_name">jsoninspector</property>
|
||||
<signal name="delete-event" handler="onCopyJSONDelete" swapped="no"/>
|
||||
<signal name="destroy" handler="onCopyJSONDestroy" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkBox" id="box2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="textview1">
|
||||
<property name="width_request">200</property>
|
||||
<property name="height_request">140</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="wrap_mode">char</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button2">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="onCopyJSONCancelClicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button1">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="onCopyJSONAcceptClicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
<property name="page_size">10</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment2">
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
<property name="page_size">10</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-copy</property>
|
||||
</object>
|
||||
<object class="GtkTreeSelection" id="treeselection1"/>
|
||||
<object class="GtkTreeStore" id="treestore1">
|
||||
<columns>
|
||||
<!-- column-name key_val -->
|
||||
|
@ -15,53 +173,65 @@
|
|||
<object class="GtkWindow" id="MainWindow">
|
||||
<property name="width_request">400</property>
|
||||
<property name="height_request">400</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">JSON Inspector</property>
|
||||
<property name="window_position">center</property>
|
||||
<signal name="delete_event" handler="onMainWindowDelete"/>
|
||||
<property name="icon_name">jsoninspector</property>
|
||||
<signal name="delete-event" handler="onMainWindowDelete" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox1">
|
||||
<object class="GtkBox" id="box1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkMenuBar" id="menubar1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="menuitem1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Archivo</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">_File</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu" id="menu1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="imagemenuitem2">
|
||||
<property name="label">gtk-open</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="onOpenMenuClicked"/>
|
||||
<signal name="activate" handler="onOpenMenuClicked" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="imagemenuitem1">
|
||||
<property name="label">Copiar JSON</property>
|
||||
<property name="label" translatable="yes">Cop_y JSON</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="image">image1</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="onCopyJSONClicked"/>
|
||||
<signal name="activate" handler="onCopyJSONClicked" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="imagemenuitem5">
|
||||
<property name="label">gtk-quit</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="onExitMenuClicked"/>
|
||||
<signal name="activate" handler="onExitMenuClicked" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -71,17 +241,21 @@
|
|||
<child>
|
||||
<object class="GtkMenuItem" id="menuitem4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Ay_uda</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">_Help</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu" id="menu3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="imagemenuitem10">
|
||||
<property name="label">gtk-about</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="onAboutMenuActivate" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -91,6 +265,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
@ -100,26 +275,26 @@
|
|||
<property name="can_focus">True</property>
|
||||
<property name="hadjustment">adjustment1</property>
|
||||
<property name="vadjustment">adjustment2</property>
|
||||
<property name="hscrollbar_policy">automatic</property>
|
||||
<property name="vscrollbar_policy">automatic</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="treeview1">
|
||||
<property name="width_request">300</property>
|
||||
<property name="height_request">300</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="model">treestore1</property>
|
||||
<property name="hadjustment">adjustment1</property>
|
||||
<property name="vadjustment">adjustment2</property>
|
||||
<property name="model">treestore1</property>
|
||||
<property name="headers_clickable">False</property>
|
||||
<property name="expander_column">treeviewcolumn1</property>
|
||||
<property name="search_column">0</property>
|
||||
<property name="level_indentation">1</property>
|
||||
<property name="enable_grid_lines">both</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
|
||||
<property name="resizable">True</property>
|
||||
<property name="title">Nodo</property>
|
||||
<property name="title" translatable="yes">Node</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="clickable">True</property>
|
||||
<property name="sort_column_id">0</property>
|
||||
|
@ -128,14 +303,14 @@
|
|||
<child>
|
||||
<object class="GtkTreeViewColumn" id="treeviewcolumn2">
|
||||
<property name="resizable">True</property>
|
||||
<property name="title">Valor</property>
|
||||
<property name="title" translatable="yes">Value</property>
|
||||
<property name="expand">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="treeviewcolumn3">
|
||||
<property name="resizable">True</property>
|
||||
<property name="title">Tipo</property>
|
||||
<property name="title" translatable="yes">Type</property>
|
||||
<property name="expand">True</property>
|
||||
</object>
|
||||
</child>
|
||||
|
@ -143,125 +318,39 @@
|
|||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStatusbar" id="statusbar1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="StatusLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">No hay JSON cargado</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">No JSON loaded</property>
|
||||
<attributes>
|
||||
<attribute name="gravity" value="west"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
<property name="page_size">10</property>
|
||||
</object>
|
||||
<object class="GtkTreeSelection" id="treeselection1"/>
|
||||
<object class="GtkAdjustment" id="adjustment2">
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
<property name="page_size">10</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="TextWindow">
|
||||
<property name="title" translatable="yes">Introducir texto JSON</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="default_width">200</property>
|
||||
<property name="default_height">180</property>
|
||||
<signal name="destroy" handler="onCopyJSONDestroy"/>
|
||||
<signal name="delete_event" handler="onCopyJSONDelete"/>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="textview1">
|
||||
<property name="width_request">200</property>
|
||||
<property name="height_request">140</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="wrap_mode">char</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button1">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="onCopyJSONAcceptClicked"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button2">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="onCopyJSONCancelClicked"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-copy</property>
|
||||
</object>
|
||||
</interface>
|
1004
res/jsoninspector.svg
Normal file
1004
res/jsoninspector.svg
Normal file
File diff suppressed because it is too large
Load diff
After Width: | Height: | Size: 290 KiB |
108
setup.py
108
setup.py
|
@ -1,27 +1,103 @@
|
|||
import ez_setup
|
||||
import ez_setup, sys, shutil, os, os.path, subprocess
|
||||
ez_setup.use_setuptools()
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
setup(
|
||||
name = "jsoninspector",
|
||||
version = "1.5",
|
||||
packages = find_packages('src', exclude=['distribute_setup']),
|
||||
scripts = ['src/jsoninspector.py','src/jsoninspector.glade'],
|
||||
entry_points = {
|
||||
'gui_scripts': [
|
||||
'jsoninspector = jsoninspector:MainApp.start',
|
||||
]
|
||||
},
|
||||
package_data = {
|
||||
# If any package contains *.glade files, include them:
|
||||
'': ['*.glade'],
|
||||
},
|
||||
from setuptools.command.install import install
|
||||
from distutils.dir_util import copy_tree
|
||||
|
||||
class CustomInstall(install):
|
||||
"""
|
||||
We subclass the install command to add some more mojo
|
||||
"""
|
||||
def run(self):
|
||||
install.run(self) # Do the usual setuptools magic
|
||||
# Now we do our own magic
|
||||
if sys.platform != 'win32' and sys.platform != 'darwin':
|
||||
try:
|
||||
print "Creating shared directory..."
|
||||
os.mkdir("/usr/local/share/jsoninspector", 0755)
|
||||
|
||||
except:
|
||||
if not os.path.exists("/usr/local/share/jsoninspector"):
|
||||
print "Warning: Couldn't create /usr/local/share/jsoninspector"
|
||||
|
||||
# Copy the translations
|
||||
try:
|
||||
print "Installing translations..."
|
||||
copy_tree('locale/po/', '/usr/share/locale/')
|
||||
|
||||
except:
|
||||
print "Warning: error copying translation files."
|
||||
|
||||
# Generate the icons
|
||||
try:
|
||||
result = subprocess.call(['./res/get_sizes.sh'])
|
||||
|
||||
except:
|
||||
result = 1
|
||||
|
||||
if result != 0:
|
||||
print "Warning: Error generating icons"
|
||||
|
||||
# Copy the icons
|
||||
print "Installing application icons..."
|
||||
for icon_size in ['{sz}x{sz}'.format(sz = x) for x in ['16', '22','24', '32', '36', '48', '64', '72', '96', '128', '192']]:
|
||||
try:
|
||||
shutil.copyfile('res/jsoninspector' + icon_size + ".png",
|
||||
'/usr/share/icons/hicolor/' + icon_size + "/apps/jsoninspector.png")
|
||||
|
||||
except:
|
||||
print "Warning: error copying icon {size}.".format(size = icon_size)
|
||||
|
||||
try:
|
||||
shutil.copyfile('res/jsoninspector48x48.png', '/usr/share/pixmaps/jsoninspector.png')
|
||||
|
||||
except:
|
||||
print "Warning: error copying icon to pixmaps directory."
|
||||
|
||||
try:
|
||||
shutil.copyfile('res/jsoninspector.svg' ,'/usr/share/icons/hicolor/scalable/apps/jsoninspector.svg')
|
||||
|
||||
except:
|
||||
print "Warning: error copying svg to scalable."
|
||||
|
||||
print "Updating icon cache..."
|
||||
|
||||
try:
|
||||
result = subprocess.call(['/usr/bin/gtk-update-icon-cache /usr/share/icons/hicolor/'])
|
||||
|
||||
except:
|
||||
result = 1
|
||||
|
||||
if result != 0:
|
||||
print "Warning: Error updating hicolor icon cache."
|
||||
|
||||
try:
|
||||
print "Installing glade file..."
|
||||
shutil.copyfile('res/jsoninspector.glade', '/usr/local/share/jsoninspector/jsoninspector.glade')
|
||||
|
||||
except:
|
||||
print "Warning: error copying .glade file."
|
||||
|
||||
try:
|
||||
print "Installing desktop entry..."
|
||||
shutil.copyfile('res/jsoninspector.desktop', '/usr/share/applications/jsoninspector.desktop')
|
||||
|
||||
except:
|
||||
print "Warning: error copying .desktop entry."
|
||||
|
||||
setup(
|
||||
name = "Jsoninspector",
|
||||
version = "2.0",
|
||||
packages = find_packages('src', exclude = ['ez_setup']),
|
||||
entry_points = { 'gui_scripts' : [ 'jsoninspector = jsoninspector:main_start' ] },
|
||||
package_dir = { '' : 'src' },
|
||||
# metadata for upload to PyPI
|
||||
author = "Jose Carlos Cuevas",
|
||||
author_email = "reset.reboot@gmail.com",
|
||||
description = "JSON Inspector is a simple application to study JSON code",
|
||||
license = "GPLv3",
|
||||
keywords = "json inspect gtk gnome",
|
||||
url = "", # project home page, if any
|
||||
url = "https://github.com/resetreboot/jsoninspector", # project home page, if any
|
||||
cmdclass = { 'install' : CustomInstall }
|
||||
)
|
||||
|
|
74
setup_windows.py
Normal file
74
setup_windows.py
Normal file
|
@ -0,0 +1,74 @@
|
|||
# This was borrowed from
|
||||
# https://wiki.gnome.org/Projects/PyGObject#Building_on_Win32_with_cx_freeze
|
||||
# Thanks to Gian Mario Tagliaretti
|
||||
|
||||
import os, site, sys
|
||||
from cx_Freeze import setup, Executable
|
||||
|
||||
## Get the site-package folder, not everybody will install
|
||||
## Python into C:\PythonXX
|
||||
site_dir = site.getsitepackages()[1]
|
||||
include_dll_path = os.path.join(site_dir, "gtk")
|
||||
|
||||
## Collect the list of missing dll when cx_freeze builds the app
|
||||
missing_dll = ['libgtk-3-0.dll',
|
||||
'libgdk-3-0.dll',
|
||||
'libatk-1.0-0.dll',
|
||||
'libcairo-gobject-2.dll',
|
||||
'libgdk_pixbuf-2.0-0.dll',
|
||||
'libjpeg-8.dll',
|
||||
'libpango-1.0-0.dll',
|
||||
'libpangocairo-1.0-0.dll',
|
||||
'libpangoft2-1.0-0.dll',
|
||||
'libpangowin32-1.0-0.dll',
|
||||
'libgnutls-26.dll',
|
||||
'libgcrypt-11.dll',
|
||||
'libp11-kit-0.dll'
|
||||
]
|
||||
|
||||
## We also need to add the glade folder, cx_freeze will walk
|
||||
## into it and copy all the necessary files
|
||||
glade_folder = 'res'
|
||||
|
||||
## We need to add all the libraries too (for themes, etc..)
|
||||
gtk_libs = ['etc', 'lib', 'share']
|
||||
|
||||
## Create the list of includes as cx_freeze likes
|
||||
include_files = []
|
||||
for dll in missing_dll:
|
||||
include_files.append((os.path.join(include_dll_path, dll), dll))
|
||||
|
||||
## Let's add glade folder and files
|
||||
include_files.append((glade_folder, glade_folder))
|
||||
|
||||
## Let's add gtk libraries folders and files
|
||||
for lib in gtk_libs:
|
||||
include_files.append((os.path.join(include_dll_path, lib), lib))
|
||||
|
||||
base = None
|
||||
|
||||
## Lets not open the console while running the app
|
||||
if sys.platform == "win32":
|
||||
base = "Win32GUI"
|
||||
|
||||
executables = [
|
||||
Executable("jsoninspector.py",
|
||||
base = base
|
||||
)
|
||||
]
|
||||
|
||||
buildOptions = dict(
|
||||
compressed = False,
|
||||
includes = ["gi"],
|
||||
packages = ["gi"],
|
||||
include_files = include_files
|
||||
)
|
||||
|
||||
setup(
|
||||
name = "JSONInspector",
|
||||
author = "Jose Carlos Cuevas Albadalejo",
|
||||
version = "2.0",
|
||||
description = "JSON Inspection tool",
|
||||
options = dict(build_exe = buildOptions),
|
||||
executables = executables
|
||||
)
|
13
src/jsoninspector/__init__.py
Normal file
13
src/jsoninspector/__init__.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from jsoninspector import LogicObject, MainWindowMethods
|
||||
|
||||
def main_start():
|
||||
"""
|
||||
So setuptools makes a nice startup script
|
||||
"""
|
||||
logicObject = LogicObject()
|
||||
|
||||
mainWindow = MainWindowMethods(logicObject)
|
||||
mainWindow.run(None)
|
|
@ -1,86 +1,104 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from pkg_resources import resource_filename
|
||||
from gi.repository import Gtk, Gio
|
||||
|
||||
import json
|
||||
import sys
|
||||
import pygtk
|
||||
import json, sys, os.path
|
||||
|
||||
try:
|
||||
pygtk.require("2.0")
|
||||
except:
|
||||
print "Versión de PyGTK incorrecta!\n"
|
||||
sys.exit(1)
|
||||
# Internationalization support
|
||||
import gettext
|
||||
import locale
|
||||
|
||||
import gtk
|
||||
APP = "jsoninspector"
|
||||
|
||||
class MainWindowMethods(object):
|
||||
if os.path.exists('../locale/po') and os.path.exists('../../res'):
|
||||
# We're in the development tree
|
||||
DIR = "../../locale/po/"
|
||||
RESOURCES = "../../res/"
|
||||
|
||||
elif sys.platform != 'win32' and sys.platform != 'darwin':
|
||||
DIR = "/usr/share/locale/"
|
||||
RESOURCES = "/usr/local/share/jsoninspector"
|
||||
|
||||
else:
|
||||
DIR = "po"
|
||||
RESOURCES = "res/"
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
|
||||
gettext.bindtextdomain(APP, DIR)
|
||||
locale.bindtextdomain(APP, DIR)
|
||||
|
||||
|
||||
gettext.textdomain(APP)
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class MainWindowMethods(Gtk.Application):
|
||||
"""
|
||||
Clase que contiene los métodos de la ventana principal
|
||||
Main Application object with the main window signals
|
||||
"""
|
||||
def __init__(self, logic):
|
||||
"""
|
||||
Carga y conecta el XML de gtkBuilder, además de mostrar la ventana
|
||||
principal
|
||||
"""
|
||||
self.builder = gtk.Builder()
|
||||
try:
|
||||
self.builder.add_from_file(resource_filename(__name__,'../../src/jsoninspector.glade'))
|
||||
Gtk.Application.__init__(self, application_id = "apps.gnome.jsoninspector",
|
||||
flags = Gio.ApplicationFlags.FLAGS_NONE)
|
||||
|
||||
except:
|
||||
self.builder.add_from_file(resource_filename(__name__,'jsoninspector.glade'))
|
||||
# We store the reference to the app logic
|
||||
self.logicObj = logic
|
||||
|
||||
self.connect("activate", self.on_app_start)
|
||||
|
||||
def on_app_start(self, data = None):
|
||||
"""
|
||||
Loads the MainWindow widgets, shows it up and starts the main loop
|
||||
"""
|
||||
self.builder = Gtk.Builder()
|
||||
self.builder.set_translation_domain(APP)
|
||||
self.builder.add_from_file(os.path.join(RESOURCES, 'jsoninspector.glade'))
|
||||
self.builder.connect_signals(self)
|
||||
|
||||
# Prepara los renderizados de columna y las asigna a los valores
|
||||
cell = gtk.CellRendererText()
|
||||
# Prepares the renders of columns and assigns the values
|
||||
cell = Gtk.CellRendererText()
|
||||
columns = self.builder.get_object("treeviewcolumn1")
|
||||
columns.pack_start(cell)
|
||||
columns.pack_start(cell, True)
|
||||
columns.add_attribute(cell, 'text', 0)
|
||||
treeview = self.builder.get_object("treeview1")
|
||||
# Esta columna es la que tiene los nodos de apertura y cierre
|
||||
# This column has the open and collapse nodes
|
||||
treeview.set_expander_column(columns)
|
||||
|
||||
cell = gtk.CellRendererText()
|
||||
cell = Gtk.CellRendererText()
|
||||
columns = self.builder.get_object("treeviewcolumn2")
|
||||
columns.pack_start(cell)
|
||||
columns.pack_start(cell, True)
|
||||
columns.add_attribute(cell, 'text', 1)
|
||||
|
||||
cell = gtk.CellRendererText()
|
||||
cell = Gtk.CellRendererText()
|
||||
columns = self.builder.get_object("treeviewcolumn3")
|
||||
columns.pack_start(cell)
|
||||
columns.pack_start(cell, True)
|
||||
columns.add_attribute(cell, 'text', 2)
|
||||
|
||||
# Obtenemos la ventana y la mostramos completamente
|
||||
# We get the window and show it
|
||||
self.window = self.builder.get_object("MainWindow")
|
||||
self.add_window(self.window)
|
||||
self.window.show_all()
|
||||
|
||||
# Obtenemos un enlace al objeto de lógica de aplicación
|
||||
self.logicObj = logic
|
||||
|
||||
def onOpenMenuClicked(self, event):
|
||||
"""
|
||||
El usuario ha presionado Abrir en el menu
|
||||
User has pressed Open in the menu
|
||||
"""
|
||||
# Creamos el dialogo de abrir fichero
|
||||
chooser = gtk.FileChooserDialog(title=None,
|
||||
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
buttons=(gtk.STOCK_CANCEL,
|
||||
gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OPEN,
|
||||
gtk.RESPONSE_OK))
|
||||
chooser.set_default_response(gtk.RESPONSE_OK)
|
||||
# Create the FileChooser Dialog
|
||||
chooser = Gtk.FileChooserDialog(_("Open JSON text file"), self.window,
|
||||
Gtk.FileChooserAction.OPEN,
|
||||
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
|
||||
|
||||
# Lo lanzamos
|
||||
# Launch it
|
||||
response = chooser.run()
|
||||
|
||||
# Si hemos seleccionado un fichero, lo cargamos
|
||||
if response == gtk.RESPONSE_OK:
|
||||
# If we choose a file, we load it
|
||||
if response == Gtk.ResponseType.OK:
|
||||
filename = chooser.get_filename()
|
||||
label = self.builder.get_object("StatusLabel")
|
||||
|
||||
# Según todo haya ido, actualizamos la barra de estado
|
||||
# We update the statusbar accordingly to what has happened
|
||||
if self.logicObj.loadjson(filename):
|
||||
|
||||
label.set_text(filename)
|
||||
|
@ -90,22 +108,22 @@ class MainWindowMethods(object):
|
|||
|
||||
else:
|
||||
|
||||
label.set_text("No hay JSON cargado")
|
||||
label.set_text(_("No JSON loaded."))
|
||||
|
||||
# Nos deshacemos del dialogo
|
||||
# We finish the dialog
|
||||
chooser.destroy()
|
||||
|
||||
def onCopyJSONClicked(self, widget):
|
||||
"""
|
||||
Se ha pulsado Copiar JSON
|
||||
User asked to paste a JSON code
|
||||
"""
|
||||
# Mostrar la ventana de texto
|
||||
# Show up the TextWindow
|
||||
textWindow = self.builder.get_object("TextWindow")
|
||||
textWindow.show_all()
|
||||
|
||||
def onCopyJSONDelete(self, widget, event):
|
||||
"""
|
||||
Se ha dado a cerrar la ventana de copiar texto
|
||||
We've been told to close the CopyJSON Window
|
||||
"""
|
||||
textWindow = self.builder.get_object("TextWindow")
|
||||
textWindow.hide()
|
||||
|
@ -114,7 +132,7 @@ class MainWindowMethods(object):
|
|||
|
||||
def onCopyJSONDestroy(self, widget):
|
||||
"""
|
||||
Se ha cerrado la ventana
|
||||
We've been tasked with removing the CopyJSON window
|
||||
"""
|
||||
textWindow = self.builder.get_object("TextWindow")
|
||||
textWindow.hide()
|
||||
|
@ -123,12 +141,12 @@ class MainWindowMethods(object):
|
|||
|
||||
def onCopyJSONAcceptClicked(self, widget):
|
||||
"""
|
||||
Se ha aceptado el código
|
||||
The input is finished and accepted.
|
||||
"""
|
||||
textView = self.builder.get_object("textview1")
|
||||
jsonBuffer = textView.get_buffer()
|
||||
jsonText = jsonBuffer.get_text(jsonBuffer.get_start_iter(),
|
||||
jsonBuffer.get_end_iter())
|
||||
jsonBuffer.get_end_iter(), True)
|
||||
|
||||
textWindow = self.builder.get_object("TextWindow")
|
||||
textWindow.hide()
|
||||
|
@ -138,29 +156,41 @@ class MainWindowMethods(object):
|
|||
if self.logicObj.loadJSONText(jsonText):
|
||||
|
||||
status_label = self.builder.get_object("StatusLabel")
|
||||
status_label.set_text("Cargado desde portapapeles.")
|
||||
status_label.set_text(_("Loaded from the clipboard."))
|
||||
self.logicObj.loadTree(treestore)
|
||||
|
||||
def onCopyJSONCancelClicked(self, widget):
|
||||
"""
|
||||
Se ha cancelado
|
||||
The user changed its mind and pressed cancel
|
||||
"""
|
||||
textWindow = self.builder.get_object("TextWindow")
|
||||
textWindow.hide()
|
||||
|
||||
def onExitMenuClicked(self, widget):
|
||||
"""
|
||||
Se ha pulsado salir
|
||||
Menu option Exit has been clicked
|
||||
"""
|
||||
gtk.main_quit()
|
||||
sys.exit(0)
|
||||
self.quit()
|
||||
|
||||
def onAboutMenuActivate(self, widget):
|
||||
"""
|
||||
About option clicked
|
||||
"""
|
||||
about_dialog = self.builder.get_object("AboutDialog")
|
||||
about_dialog.run()
|
||||
about_dialog.hide()
|
||||
|
||||
def onMainWindowDelete(self, widget, event):
|
||||
"""
|
||||
Se ha destruido o mandado cerrar la ventana principal
|
||||
Our MainWindow has been deleted or closed
|
||||
"""
|
||||
gtk.main_quit()
|
||||
sys.exit(0)
|
||||
pass
|
||||
|
||||
def onAboutDialogClose(self, widget, event = None):
|
||||
pass
|
||||
|
||||
def onAboutDialogDeleteEvent(self, widget, event = None):
|
||||
pass
|
||||
|
||||
|
||||
class LogicObject(object):
|
||||
|
@ -179,7 +209,7 @@ class LogicObject(object):
|
|||
try:
|
||||
self.json = json.loads(f.read())
|
||||
except ValueError:
|
||||
print "JSON no válido!\n"
|
||||
print _("Not valid JSON!\n")
|
||||
self.json = None
|
||||
f.close()
|
||||
|
||||
|
@ -195,7 +225,7 @@ class LogicObject(object):
|
|||
try:
|
||||
self.json = json.loads(text)
|
||||
except ValueError:
|
||||
print "JSON no válido"
|
||||
print _("Not valid JSON")
|
||||
self.json = None
|
||||
|
||||
return False
|
||||
|
@ -256,21 +286,12 @@ class LogicObject(object):
|
|||
unicode(type(node))])
|
||||
|
||||
|
||||
class MainApp(object):
|
||||
"""
|
||||
Clase principal
|
||||
"""
|
||||
@staticmethod
|
||||
def start():
|
||||
logicObject = LogicObject()
|
||||
mainWindow = MainWindowMethods(logicObject)
|
||||
|
||||
gtk.main()
|
||||
|
||||
|
||||
# Ejecucion del programa principal
|
||||
|
||||
# Main procedure
|
||||
if __name__ == "__main__":
|
||||
|
||||
app = MainApp()
|
||||
app.start()
|
||||
logicObject = LogicObject()
|
||||
|
||||
mainWindow = MainWindowMethods(logicObject)
|
||||
mainWindow.run(None)
|
5
util/gen_pot.sh
Executable file
5
util/gen_pot.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
intltool-extract --type="gettext/glade" *.glade
|
||||
xgettext -k_ -kN_ -o messages.pot *.py *.h
|
||||
|
Loading…
Reference in a new issue