Skip to content

Commit

Permalink
[plugins] clean up golden path
Browse files Browse the repository at this point in the history
- removePlugin to remove newline also
  • Loading branch information
saulpw committed Feb 21, 2019
1 parent 663b5e2 commit 94ab4e3
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 61 deletions.
2 changes: 1 addition & 1 deletion dev/deploy_plugins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
aws=${aws:-echo aws}

cd plugins
for p in `find . -type d` ; do ( cd $p && zip -r $p.zip . ) ; done
for p in `find . -type d` ; do ( cd $p && zip -r $p-`cat VERSION`.zip . ) ; done
cd ..

$aws s3 cp --profile saulpw --acl public-read plugins/plugins.tsv s3://visidata.org/plugins/
Expand Down
2 changes: 1 addition & 1 deletion plugins/plugins.tsv
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
name plugin_ver release_date author visidata_ver description requirements
name latest_ver latest_release author visidata_ver description requirements
vfake 0.9 2019-02-08 Saul Pwanson <[email protected]> 1.6 replace column with fake values Faker
1 change: 1 addition & 0 deletions plugins/vfake/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.9
24 changes: 13 additions & 11 deletions plugins/vfake/__init__.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
# install the faker module: pip3 install Faker
# copy this file into .visidata/fake.py
# add "import fake" to .visidatarc

# to anonymize a column in vd: do "setcol-fake" with e.g. 'name' 'isbn10' or any of the functions on Faker()

from visidata import vd, Column, Sheet, option, options, asyncthread, Progress, undoEditCells

Sheet.addCommand(None, 'setcol-fake', 'cursorCol.setValuesFromFaker(input("faketype: ", type="faketype"), selectedRows or rows)', undo=undoEditCells)
__version__ = '0.9'

option('locale', 'en_US', 'default locale to use for Faker', replay=True)

vd.newvals = {None: None}
vd.fakeMap = {}

@Column.api
@asyncthread
def setValuesFromFaker(col, faketype, rows):
import faker
fake = faker.Faker(options.locale)
fakefunc = getattr(fake, faketype)
fakefunc = getattr(fake, faketype, None) or error('no such faker function')

vd.fakeMap[None] = None
vd.fakeMap[options.null_value] = options.null_value

vd.newvals[options.null_value] = options.null_value
for r in Progress(rows):
v = col.getValue(r)
if v in vd.newvals:
newv = vd.newvals[v]
if v in vd.fakeMap:
newv = vd.fakeMap[v]
else:
newv = fakefunc()
vd.newvals[v] = newv
vd.fakeMap[v] = newv
col.setValue(r, newv)


Sheet.addCommand(None, 'setcol-fake', 'cursorCol.setValuesFromFaker(input("faketype: ", type="faketype"), selectedRows or rows)', undo=undoEditCells)
Sheet.addCommand(None, 'reset-fake', 'vd.fakeMap.clear()')
129 changes: 82 additions & 47 deletions visidata/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,66 +3,101 @@

from visidata import *

#option('plugins_url', 'https://visidata.org/plugins/', 'source of plugins sheet')
option('plugins_url', 'file:///home/saul/git/visidata/plugins/', 'plugins url ')

globalCommand(None, 'open-plugins', 'openPlugins()')
option('plugins_url', 'https://visidata.org/plugins/', 'source of plugins sheet')

def openPlugins():
vs = openSource(urlcache(options.plugins_url+"plugins.tsv", 0))
vs.name = 'visidata.org/plugins'
vs.rowtype = "plugins"
vs.addCommand('a', 'add-plugin', 'installPlugin(cursorRow)')
vs.addCommand('d', 'delete-plugin', 'confirm("remove plugin? ") and removePlugin(cursorRow)')
vd.push(vs)
@VisiData.api
def openPlugins(vd):
return openSource(urlcache(options.plugins_url+"plugins.tsv", 0), filetype="plugins")

def plugin_url(pluginname):
return options.plugins_url+pluginname+".zip"
def open_plugins(p):
'Support the "plugins" phony filetype as PluginsSheet'
return PluginsSheet('visidata.org/plugins', source=p)

def plugin_path(pluginname):
return Path(os.path.join(options.visidata_dir, "plugins", pluginname))
def _plugin_zip(plugin):
return "%s%s-%s.zip" % (options.plugins_url, plugin.name, plugin.plugin_ver)

def plugin_import(pluginname):
return "import plugins."+pluginname
def _plugin_path(plugin):
return Path(os.path.join(options.visidata_dir, "plugins", plugin.name))

@VisiData.api
def installPlugin(vd, plugin):
# pip3 install requirements
outpath = plugin_path(plugin.name)
if outpath.exists():
confirm("plugin path already exists, overwrite? ")
def _plugin_import(plugin):
return "import " + _plugin_import_name(plugin)

def _plugin_import_name(plugin):
return "plugins."+plugin.name


class PluginsSheet(TsvSheet):
rowtype = "plugins"

@asyncthread
def reload(self):
vd.sync(super().reload())

self.addColumn(Column('installed', getter=lambda c,r: c.sheet.installedStatus(r)), index=1)
self.addColumn(Column('loaded', getter=lambda c,r: c.sheet.loadedVersion(r)), index=2)

def installedStatus(self, plugin):
import importlib
return importlib.util.find_spec(_plugin_import_name(plugin))

def loadedVersion(self, plugin):
name = _plugin_import_name(plugin)
if name not in sys.modules:
return None
mod = getattr(__import__(name), name)
return getattr(mod, '__version__', 'unknown version installed')

def installPlugin(self, plugin):
# pip3 install requirements
outpath = _plugin_path(plugin)
if outpath.exists():
confirm("plugin path already exists, overwrite? ")

self._install(plugin)

@asyncthread
def _install(self, plugin):
outpath = _plugin_path(plugin)
with zipfile.ZipFile(urlcache(_plugin_zip(plugin), text=False).open_bytes()) as zf:
zf.extractall(path=outpath.resolve())

p = subprocess.Popen(['pip3', 'install']+plugin.requirements.split())
status(tuple(p.communicate()))

_install(plugin)
with Path(options.config).open_text(mode='a') as fprc:
print(_plugin_import(plugin), file=fprc)

warning("restart visidata to use new plugin")

@asyncthread
def _install(plugin):
outpath = plugin_path(plugin.name)
with zipfile.ZipFile(urlcache(plugin_url(plugin.name), text=False).open_bytes()) as zf:
zf.extractall(path=outpath.resolve())
def removePluginIfExists(self, plugin):
ver = loadedVersion()
if not ver:
warning('plugin is not installed')
return

p = subprocess.Popen(['pip3', 'install']+plugin.requirements.split())
status(tuple(p.communicate()))
confirm("remove plugin? ")
self.removePlugin(plugin)

with Path(options.config).open_text(mode='a') as fprc:
print(plugin_import(plugin.name), file=fprc)
def removePlugin(self, plugin):
vdrc = Path(options.config).resolve()
oldvdrc = vdrc+'.bak'
try:
shutil.copyfile(vdrc, oldvdrc)
vdrc_contents = Path(oldvdrc).read_text().replace('\n'+_plugin_import(plugin), '')

warning("restart visidata to use new plugin")
with Path(options.config).open_text(mode='w') as fprc: # replace without import line
fprc.write(vdrc_contents)
except FileNotFoundError:
warning("no visidatarc file")

try:
shutil.rmtree(_plugin_path(plugin).resolve())
except FileNotFoundError:
warning("%s plugin not installed" % plugin.name)

def removePlugin(plugin):
vdrc = Path(options.config).resolve()
oldvdrc = vdrc+'.bak'
try:
shutil.copyfile(vdrc, oldvdrc)
vdrc_contents = Path(oldvdrc).read_text().replace(plugin_import(plugin.name), '')

with Path(options.config).open_text(mode='w') as fprc: # replace without import line
fprc.write(vdrc_contents)
except FileNotFoundError:
warning("no visidatarc file")
globalCommand(None, 'open-plugins', 'vd.push(openPlugins())')

try:
shutil.rmtree(plugin_path(plugin.name).resolve())
except FileNotFoundError:
warning("%s plugin not installed" % plugin.name)
PluginsSheet.addCommand('a', 'add-plugin', 'installPlugin(cursorRow)')
PluginsSheet.addCommand('d', 'delete-plugin', 'removePluginIfExists(cursorRow)')
2 changes: 1 addition & 1 deletion visidata/urlcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from visidata import __version_info__, Path, options


def urlcache(url, cachesecs=24*60*60):
def urlcache(url, cachesecs=24*60*60, text=True):
'Returns Path object to local cache of url contents.'
p = Path(os.path.join(options.visidata_dir, 'cache', urllib.parse.quote(url, safe='')))
if p.exists():
Expand Down

0 comments on commit 94ab4e3

Please sign in to comment.