Unverified Commit caa2aea9 authored by Michele Pasin's avatar Michele Pasin Committed by GitHub

Merge pull request #54 from lambdamusic/merging-ontodocs

Merging ontodocs
parents 7670ce7e 8462c152
......@@ -58,6 +58,14 @@ If you’re upgrading from an older version, make sure you use the -U flag:
pip install ontospy -U
```
**Gerating Documentation**
If you want to use ontospy to automatically create some [HTML documentation](<(#generating-ontology-documentation)>) for an ontology, you need to install the HTML extension too:
```
pip install ontospy[HTML]
```
## Quick example
If used as a Python package, the basic workflow is the following: load a graph by instantiating the `Ontospy` class with a file containing RDFS, OWL or SKOS definitions; you get back an object that lets you interrogate the ontology. That's all!
......@@ -197,7 +205,7 @@ This is due to the new [System Integrity Protection](https://support.apple.com/e
Ontospy can be used to generate HTML ontology documentation pretty easily.
This functionality relies on another library called [OntoDocs](https://github.com/lambdamusic/Ontodocs) but I'm currenlty working on bringing it back within Ontospy as an add-on, essentially because it's easier to maintain.
This functionality relies on a module called _ontodocs_ that used to be maintained as a separate library but is noe merged with ontospy (essentially because it's easier to maintain it this way).
**Examples**
......@@ -208,11 +216,13 @@ That's the kind of documentation OntoDocs can generate out-of-the-box. For even
**Installation**
By default the libraries needed by this module (Django and Pygments) are not installed, so you have to add them like this:
```
pip install ontodocs -U
pip install ontospy[HTML] -U
```
Ontodocs allows to generate documentation for an RDF vocabulary, using visualization algorithms that create simple HTML pages, Markdown files, or more complex javascript interactive charts based on D3.js.
Ontospy allows to generate documentation for an RDF vocabulary, using visualization algorithms that create simple HTML pages, Markdown files, or more complex javascript interactive charts based on D3.js.
```
> ontospy viz -h
......@@ -237,7 +247,7 @@ This is how you would invoke a visualization from a script:
```
import ontospy
from ontodocs.viz.viz_html_single import *
from ontospy.ontodocs.viz.viz_html_single import *
g = ontospy.Ontospy("http://cohere.open.ac.uk/ontology/cohere.owl#")
......
......@@ -8,6 +8,8 @@ Summary of changes.
- fixed issue with serialization print
- comments all go to sterr by default
=> eg now easier to to `ontospy serialize foaf.rdf json-ld > ~/foaf.json`
- embedded ontodocs plugin within main source code
- requires install with [HTML] flag
## November 12, 2018: v1.9.6
......
......@@ -7,8 +7,6 @@ All rights reserved.
"""
from __future__ import print_function
import sys
import os
import time
......@@ -64,7 +62,7 @@ CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
#
##################
#
# 2018-08-23: trying to restructure the cli using command groups
# 2018-08-23: restructuring the cli using command groups
# http://click.pocoo.org/6/commands/
# test with python -m ontospy.cli library
......@@ -82,7 +80,7 @@ CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
@click.pass_context
def main_cli(ctx, verbose=False):
"""
Ontospy is a command line inspector for RDF/OWL models. Use --help option with one of the commands listed below to find out more. Or visit <http://lambdamusic.github.io/Ontospy/>.
Ontospy is a command line inspector for RDF/OWL models. Use the --help option with one of the commands listed below to find out more, or visit http://lambdamusic.github.io/Ontospy
"""
sTime = time.time()
if ctx.obj is None: # Fix for bug (as of 3.0)
......@@ -364,7 +362,7 @@ if __name__ == '__main__':
@click.option(
'--showthemes', is_flag=True, help='Show the available CSS theme choices.')
@click.pass_context
def docs(ctx, source=None, outputpath="", title="", theme="",
def html(ctx, source=None, outputpath="", title="", theme="",
showthemes=False):
"""Generate documentation for an ontology in html or markdown format
"""
......@@ -374,14 +372,17 @@ def docs(ctx, source=None, outputpath="", title="", theme="",
'labels': verbose,
}
# from .ontodocs import *
from .ontodocs.builder import action_visualize
try:
import ontodocs
from ontodocs.core.builder import action_visualize
# check that we have the required dependencies
import django
except:
click.secho(
"WARNING: the ontodocs library is required for this functionality.",
"WARNING: this functionality requires the Django package and other extra dependecies.",
fg="red")
click.secho("Install with `pip install ontodocs -U`")
click.secho("Install with `pip install ontospy[HTML] -U`")
sys.exit(0)
if showthemes:
......
......@@ -145,7 +145,7 @@ def action_listlocal(all_details=True):
"------------------\nSelect a model by typing its number: (enter=quit)",
"important")
var = input()
if var == "":
if var == "" or var == "q":
return None
else:
try:
......
#!/usr/bin/python
# -*- coding: utf-8 -*-
VISUALIZATIONS_LIST = {
"Visualizations":
[{
"ID": "html-simple",
"Title": "Html: single-page",
"Description": "@todo",
} , {
"ID": "html-complex",
"Title": "Html: multi-page",
"Description": "@todo",
} , {
"ID": "markdown",
"Title": "Markdown: multi-page",
"Description": "@todo",
} , {
"ID": "d3-tree",
"Title": "D3 Dendogram",
"Description": "@todo",
}
]
}
BOOTSWATCH_THEMES = ['cerulean' , 'flatly' , 'lumen' , 'sandstone' , 'spacelab' , 'yeti' , 'cosmo' , 'darkly' , 'paper' , 'simplex' , 'superhero' , 'readable' , 'slate' , 'united']
BOOTSWATCH_THEME_DEFAULT = "simplex"
# 'cyborg' , 'journal'
# !/usr/bin/env python
# -*- coding: UTF-8 -*-
\ No newline at end of file
# !/usr/bin/env python
# -*- coding: UTF-8 -*-
#
#
# VIZ MODULE : util to visualize an ontology as html or similar
#
#
import click
import os
from shutil import copyfile
# Fix Python 2.x.
try:
input = raw_input
except NameError:
pass
# django loading requires different steps based on version
# https://docs.djangoproject.com/en/dev/releases/1.7/#standalone-scripts
import django
# http://stackoverflow.com/questions/1714027/version-number-comparison
from distutils.version import StrictVersion
from ..core import actions as ontospy_actions
from ..core import manager as ontospy_manager
from ..core.utils import *
from .. import *
_dirname, _filename = os.path.split(os.path.abspath(__file__))
ONTODOCS_VIZ_TEMPLATES = _dirname + "/media/templates/"
ONTODOCS_VIZ_STATIC = _dirname + "/media/static/"
if StrictVersion(django.get_version()) > StrictVersion('1.7'):
from django.conf import settings
from django.template import Context, Template
settings.configure()
django.setup()
settings.TEMPLATES = [
{
'BACKEND':
'django.template.backends.django.DjangoTemplates',
'DIRS': [
# insert your TEMPLATE_DIRS here
ONTODOCS_VIZ_TEMPLATES + "html-single",
ONTODOCS_VIZ_TEMPLATES + "html-multi",
ONTODOCS_VIZ_TEMPLATES + "markdown",
ONTODOCS_VIZ_TEMPLATES + "d3",
ONTODOCS_VIZ_TEMPLATES + "misc",
],
'APP_DIRS':
True,
'OPTIONS': {
'context_processors': [
# Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
# list if you haven't customized them:
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
],
},
},
]
else:
from django.conf import settings
from django.template import Context, Template
settings.configure()
try:
from .CONFIG import VISUALIZATIONS_LIST, BOOTSWATCH_THEMES, BOOTSWATCH_THEME_DEFAULT
VISUALIZATIONS_LIST = VISUALIZATIONS_LIST['Visualizations']
except: # Mother of all exceptions
click.secho("Visualizations configuration file not found.", fg="red")
raise
def show_themes():
for t in BOOTSWATCH_THEMES:
printDebug(t, "green")
def random_theme():
return random.choice(BOOTSWATCH_THEMES)
def validate_theme(theme_try, default=BOOTSWATCH_THEME_DEFAULT):
# print theme_try
if not theme_try:
return default
if theme_try in BOOTSWATCH_THEMES:
return theme_try
else:
printDebug("Warning: theme not found", "red")
return default
def ask_visualization():
"""
ask user which viz output to use
"""
printDebug(
"Please choose an output format for the ontology visualization: (q=quit)\n",
"important")
while True:
text = ""
for viz in VISUALIZATIONS_LIST:
text += "%d) %s\n" % (VISUALIZATIONS_LIST.index(viz) + 1,
viz['Title'])
var = input(text + ">")
if var == "q":
return ""
else:
try:
n = int(var) - 1
test = VISUALIZATIONS_LIST[
n] # throw exception if number wrong
return n
except:
printDebug("Invalid selection. Please try again.", "red")
continue
# MAIN METHOD
def action_visualize(args,
fromshell=False,
path=None,
title="",
theme="",
verbose=False):
"""
export model into another format eg html, d3 etc...
<fromshell> : the local name is being passed from ontospy shell
"""
# get argument
if not (args):
ontouri = ontospy_actions.action_listlocal(all_details=False)
if ontouri:
islocal = True
else:
raise SystemExit(1)
elif fromshell:
ontouri = args
islocal = True
else:
ontouri = args[0]
islocal = False
# select a visualization
viztype = ask_visualization()
if viztype == "":
return None
# raise SystemExit, 1
# 2017-01-23: bypass pickled stuff as it has wrong counts etc..
USE_CACHE = False
# get ontospy graph
if islocal and USE_CACHE:
g = get_pickled_ontology(ontouri)
if not g:
g = do_pickle_ontology(ontouri)
else:
printDebug("Loading graph...", dim=True)
if islocal:
g = Ontospy(
os.path.join(ontospy_manager.get_home_location(), ontouri),
verbose=verbose)
else:
g = Ontospy(ontouri, verbose=verbose)
# put in home folder by default: <ontouri>/<viztype>/files..
if not path:
from os.path import expanduser
home = expanduser("~")
onto_path = slugify(unicode(ontouri))
viz_path = slugify(unicode(VISUALIZATIONS_LIST[viztype]['Title']))
path = os.path.join(home, "ontospy-viz/" + onto_path + "/" + viz_path)
if not os.path.exists(path):
os.makedirs(path)
# url = build_viz(ontouri, g, viztype, path)
printDebug("Building visualization...", dim=True)
url = build_visualization(ontouri, g, viztype, path, title, theme)
return url
# ===========
# VIZ SELECTION FUNCTION
# ===========
def build_visualization(ontouri, g, viz_index, path=None, title="", theme=""):
"""
2017-01-20: new verion, less clever but also simpler
:param g:
:param viz_index:
:param main_entity:
:return:
"""
this_viz = VISUALIZATIONS_LIST[viz_index]
if this_viz['ID'] == "html-simple":
from .viz.viz_html_single import HTMLVisualizer
v = HTMLVisualizer(g, title)
elif this_viz['ID'] == "html-complex":
from .viz.viz_html_multi import KompleteViz
v = KompleteViz(g, title, theme)
elif this_viz['ID'] == "markdown":
from .viz.viz_markdown import MarkdownViz
v = MarkdownViz(g, title)
elif this_viz['ID'] == "d3-tree":
from .viz.viz_d3tree import D3TreeViz
v = D3TreeViz(g, title)
else:
return False
url = v.build(path)
return url
# ?LEGACY
def saveVizGithub(contents, ontouri):
"""
DEPRECATED on 2016-11-16
Was working but had a dependecies on package 'uritemplate.py' which caused problems at installation time
"""
title = "OntoSpy: ontology export"
readme = """This ontology documentation was automatically generated with OntoSpy (https://github.com/lambdamusic/OntoSpy).
The graph URI is: %s""" % str(ontouri)
files = {
'index.html': {
'content': contents
},
'README.txt': {
'content': readme
},
'LICENSE.txt': {
'content':
"""The MIT License (MIT)
Copyright (c) 2016 OntoSpy project [http://ontospy.readthedocs.org/]
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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."""
}
}
urls = save_anonymous_gist(title, files)
return urls
### Note
This folder contains local copies of static files used by ontospy viz e.g. css and js libraries
### Important
Setuptools has an issue with package_folder data including folder with dots.
Eg `chart.js-2.4.0`
See also
http://stackoverflow.com/questions/3712033/python-distutils-error-directory-doesnt-exist-or-not-a-regular-file
Not sure how to solve it.. so renamed all folders accordingly!
/*CSS FOR FAMILY TREE http://thecodeplayer.com/experiment/css3-family-tree/2 */
.tree-container {
width: 3000px;
overflow-x: auto;
white-space: nowrap;
}
.tree {
width: 3000em;
margin: 10px 0px 30px -20px;
padding: 0;
display: inline-block;}
.tree ul {
padding-top: 20px; position: relative;
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}
.tree li {
float: left; text-align: center;
list-style-type: none;
position: relative;
padding: 20px 5px 0 5px;
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}
/*We will use ::before and ::after to draw the connectors*/
.tree li::before, .tree li::after{
content: '';
position: absolute; top: 0; right: 50%;
border-top: 1px solid #ccc;
width: 50%; height: 20px;
}
.tree li::after{
right: auto; left: 50%;
border-left: 1px solid #ccc;
}
/*We need to remove left-right connectors from elements without
any siblings*/
.tree li:only-child::after, .tree li:only-child::before {
display: none;
}
/*Remove space from the top of single children*/
.tree li:only-child{ padding-top: 0;}
/*Remove left connector from first child and
right connector from last child*/
.tree li:first-child::before, .tree li:last-child::after{
border: 0 none;
}
/*Adding back the vertical connector to the last nodes*/
.tree li:last-child::before{
border-right: 1px solid #ccc;
border-radius: 0 5px 0 0;
-webkit-border-radius: 0 5px 0 0;
-moz-border-radius: 0 5px 0 0;
}
.tree li:first-child::after{
border-radius: 5px 0 0 0;
-webkit-border-radius: 5px 0 0 0;
-moz-border-radius: 5px 0 0 0;
}
/*Time to add downward connectors from parents*/
.tree ul ul::before{
content: '';
position: absolute; top: 0; left: 50%;
border-left: 1px solid #ccc;
width: 0; height: 20px;
}
.tree li a {
border: 1px solid #ccc;
padding: 5px 10px;
text-decoration: none;
color: #666;
font-family: arial, verdana, tahoma;
font-size: 11px;
display: inline-block;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}
/*Time for some hover effects*/
/*We will apply the hover effect the the lineage of the element also*/
.tree li a:hover, .tree li a:hover+ul li a {
background: #c8e4f8; color: #000; border: 1px solid #94a0b4;
}
/*Connector styles on hover*/
.tree li a:hover+ul li::after,
.tree li a:hover+ul li::before,
.tree li a:hover+ul::before,
.tree li a:hover+ul ul::before{
border-color: #94a0b4;
}
/*Thats all. I hope you enjoyed it.
Thanks :)*/