Skip to content

Commit

Permalink
Delete core and lib directories during uninstallation, Add imachug's …
Browse files Browse the repository at this point in the history
…ZeroNet Cmd Lib under Tools directory
  • Loading branch information
Christian Seibold committed May 20, 2018
1 parent 22884a9 commit 778f295
Show file tree
Hide file tree
Showing 17 changed files with 1,227 additions and 1 deletion.
Binary file modified Output/ZeroNetInstaller.exe
Binary file not shown.
2 changes: 2 additions & 0 deletions Tools/ZeroNet-cmd-lib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
/config.json
Empty file.
2 changes: 2 additions & 0 deletions Tools/ZeroNet-cmd-lib/lib/args.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import sys
argv = sys.argv[1:]
193 changes: 193 additions & 0 deletions Tools/ZeroNet-cmd-lib/lib/callable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import sys, inspect

def classAsFunction(cls):
if not isinstance(cls, type):
return cls

class Class(cls):
def __new__(cls, args):
instance = super(Callable, cls).__new__(cls)
return instance.__init__(args)

return Class

@classAsFunction
class Callable(object):
class SubCommand(Exception):
pass
class Redirect(Exception):
pass
class Error(Exception):
pass

def __init__(self, args):
return self.call("", args)

def call(self, cmd, args):
cmd = cmd.strip()

try:
handler = getattr(self, "action" + "".join(map(lambda part: part[0].upper() + part[1:] if part != "" else "", cmd.split(" "))))
except AttributeError:
all_commands = [name[6].lower() + name[7:] for name in dir(self) if name.startswith("action") and len(name) > 6]
raise Callable.Error("Unknown command '%s'. Allowed commands are: %s" % (cmd, ", ".join(all_commands)))

self.checkCall(cmd, handler, args)

try:
return self.callArgs(handler, args)
except Callable.SubCommand as e:
if len(args) == 0:
raise Callable.Error("'%s' command is not a command but has subcommands." % cmd)

if len(tuple(e)) == 0:
# Remove first argument and call it
return self.call("%s %s" % (cmd, args[0]), args[1:])
else:
# Remove first argument and call given command
return self.call(tuple(e)[0], args[1:])
except Callable.Redirect as e:
if len(tuple(e)) == 0:
# Remove first argument and call it (as SubCommand)
if len(args) == 0:
raise Callable.Error("'%s' command is not a command but has subcommands." % cmd)
return self.call("%s %s" % (cmd, args[0]), args[1:])
elif len(tuple(e)) == 1:
# Call given value
return self.call(tuple(e)[0], args)
else:
# Call given value and arguments
return self.call(tuple(e)[0], tuple(e)[1])

def checkCall(self, cmd, func, argv):
import inspect

expected_args = inspect.getargspec(func).args[1:] # Split "self"
defaults = inspect.getargspec(func).defaults or tuple()

if self.checkArgs(cmd, func, argv):
return True

if len(defaults) > 0:
default_args = reversed(zip(reversed(expected_args), reversed(defaults)))
default_args = map(lambda arg: "%s=%s" % arg, default_args)
expected_args = expected_args[:-len(default_args)] + default_args

raise Callable.Error("Allowed arguments: %s" % ", ".join(expected_args))

def checkArgs(self, cmd, func, argv):
args, kwargs = self.parseArgs(argv)

import inspect

expected_args = inspect.getargspec(func).args[1:] # Split "self"
varargs = inspect.getargspec(func).varargs
keywords = inspect.getargspec(func).keywords
defaults = inspect.getargspec(func).defaults or tuple()

resulting_args = dict()
if varargs is not None:
resulting_args[varargs] = []
if keywords is not None:
resulting_args[keywords] = {}

# Positional arguments
for cnt, value in enumerate(args):
if cnt < len(expected_args):
# Passed just as argument
resulting_args[expected_args[cnt]] = value
else:
# Passed to *args
if varargs is None:
raise Callable.Error("Too many positional arguments passed to '%s': expected at most %s, got %s." % (cmd, len(expected_args), len(args)))
else:
resulting_args[varargs].append(value)

# Named arguments
handled_kwargs = []
for name, value in kwargs.iteritems():
if name in handled_kwargs:
raise Callable.Error("'%s' was passed to '%s' as named argument several times." % (name, cmd))

handled_kwargs.append(name)

if name in expected_args:
# Passed just as argument
if name in resulting_args:
raise Callable.Error("'%s' was passed to '%s' as both positional argument and named." % (name, cmd))

resulting_args[name] = value
else:
# Passed to **kwargs
if keywords is None:
raise Callable.Error("Unknown named argument '%s' passed to '%s'." % (name, cmd))
else:
resulting_args[keywords][name] = value

# Defaults
if len(defaults) > 0:
for cnt, name in enumerate(expected_args[-len(defaults):]):
if name not in resulting_args:
resulting_args[name] = defaults[cnt]

# Check that all the arguments were passed
for name in expected_args:
if name not in resulting_args:
raise Callable.Error("Argument '%s' was not passed to '%s'." % (name, cmd))

return True

def parseArgs(self, argv):
args = []
kwargs = {}

kwname = None

for arg in argv:
if arg.startswith("--"):
if kwname is not None:
kwargs[kwname] = True

kwname = arg[2:]
else:
if kwname is None:
args.append(arg)
else:
kwargs[kwname] = arg
kwname = None

if kwname is not None:
kwargs[kwname] = True

return args, kwargs

def callArgs(self, handler, argv):
args, kwargs = self.parseArgs(argv)
return handler(*args, **kwargs)

def action(self, *args, **kwargs):
raise Callable.SubCommand

class WithHelp(Callable):
def actionHelp(self, *cmd):
if cmd in [[], [""], tuple(), ("",)]:
# Print info about the class
print inspect.cleandoc(self.__doc__)
return

try:
handler = getattr(self, "action" + "".join(map(lambda part: part[0].upper() + part[1:], cmd)))
if handler.__doc__ is not None:
print inspect.cleandoc(handler.__doc__)
return
except AttributeError:
pass

if cmd == ["help"] or cmd == ("help",):
# Unable to find info on topic 'help' - no __doc__ in 'help' method or no 'help' method, use default help
print inspect.cleandoc(self.__doc__)
return

print "Unknown topic '%s'" % " ".join(cmd)

Callable.WithHelp = WithHelp
139 changes: 139 additions & 0 deletions Tools/ZeroNet-cmd-lib/lib/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import os, json

def recursiveDir(obj, prefix=""):
result = []
for name in obj:
absolute = "%s.%s" % (prefix, name) if prefix != "" else name
if isinstance(obj[name], dict):
result += recursiveDir(obj[name], absolute)
else:
result.append(absolute)
return result

class Config(object):
class AttributeError(AttributeError):
pass

def __init__(self, path):
self.__dict__["path"] = path

# Read single value
def __getattr__(self, name):
try:
with open(self.path, "r") as f:
config = json.loads(f.read())
return config[name]
except (KeyError, AttributeError):
raise Config.AttributeError("No '%s' config variable" % name)
except IOError:
raise Config.AttributeError("No config file and therefore no '%s' attribute" % name)
def __getitem__(self, name):
return self.__getattr__(name)

# Read value recursively
def get(self, name, default=None):
name = name.split(".")

try:
val = self[name[0]]
for part in name[1:]:
val = val[part]

return val
except (KeyError, AttributeError, Config.AttributeError):
return default

# Write single value
def __setattr__(self, name, value):
try:
with open(self.path, "r") as f:
config = json.loads(f.read())
except IOError:
config = dict()

config[name] = value

with open(self.path, "w") as f:
f.write(json.dumps(config))
def __setitem__(self, name, value):
self.__setattr__(name, value)

# Write value recursively
def set(self, name, value):
try:
with open(self.path, "r") as f:
config = json.loads(f.read())
except IOError:
config = dict()

current = config
for part in name.split(".")[:-1]:
try:
current = current[part]
except KeyError:
current[part] = dict()
current = current[part]

current[name.split(".")[-1]] = value

with open(self.path, "w") as f:
f.write(json.dumps(config))

# Delete variable
def __delattr__(self, name):
try:
with open(self.path, "r") as f:
config = json.loads(f.read())
except IOError:
config = dict()

del config[name]

with open(self.path, "w") as f:
f.write(json.dumps(config))
def __delitem__(self, name, value):
self.__delattr__(name, value)

# Delete variable recursively
def remove(self, name):
try:
with open(self.path, "r") as f:
config = json.loads(f.read())
except IOError:
config = dict()

current = config
for part in name.split(".")[:-1]:
try:
current = current[part]
except KeyError:
current[part] = dict()
current = current[part]

del current[name.split(".")[-1]]

with open(self.path, "w") as f:
f.write(json.dumps(config))

# Get data list
def __dir__(self):
try:
with open(self.path, "r") as f:
config = json.loads(f.read())
return dir(config)
except IOError:
return []

# Get data list recursively
def list(self):
try:
with open(self.path, "r") as f:
config = json.loads(f.read())
except IOError:
return []

return recursiveDir(config)

current_dir = os.path.dirname(os.path.abspath(__file__))
config_json = os.path.abspath(os.path.join(current_dir, "../config.json"))
config = Config(config_json)
2 changes: 2 additions & 0 deletions Tools/ZeroNet-cmd-lib/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
psutil
websocket
Loading

0 comments on commit 778f295

Please sign in to comment.