fix doctests after removal of knowledge.setup.SetupManager
This commit is contained in:
parent
a4968e76d6
commit
0e56543900
17 changed files with 105 additions and 63 deletions
|
@ -27,7 +27,7 @@ configuration):
|
|||
>>> concepts, resources, views = t.setup()
|
||||
|
||||
>>> len(concepts), len(resources)
|
||||
(20, 0)
|
||||
(15, 0)
|
||||
|
||||
Let's now add an external collection that reads in a set of resources
|
||||
from external files so we have something to work with.
|
||||
|
|
|
@ -24,7 +24,7 @@ from loops.integrator.collection import DirectoryCollectionProvider
|
|||
from loops.integrator.collection import ExternalCollectionAdapter
|
||||
from loops.integrator.interfaces import IExternalCollection, IExternalCollectionProvider
|
||||
from loops.organize.setup import SetupManager as OrganizeSetupManager
|
||||
from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
|
||||
#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
|
||||
from loops.knowledge.knowledge import Person
|
||||
from loops.knowledge.interfaces import IPerson
|
||||
from loops.setup import SetupManager, addAndConfigureObject
|
||||
|
@ -39,7 +39,7 @@ class TestSite(BaseTestSite):
|
|||
self.site = site
|
||||
|
||||
def setup(self):
|
||||
component.provideAdapter(KnowledgeSetupManager, name='knowledge')
|
||||
#component.provideAdapter(KnowledgeSetupManager, name='knowledge')
|
||||
component.provideAdapter(OrganizeSetupManager, name='organize')
|
||||
concepts, resources, views = self.baseSetup()
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ configuration):
|
|||
>>> concepts, resources, views = t.setup()
|
||||
|
||||
>>> len(concepts) + len(resources)
|
||||
33
|
||||
37
|
||||
|
||||
>>> loopsRoot = site['loops']
|
||||
|
||||
|
@ -47,19 +47,19 @@ Type- and text-based queries
|
|||
>>> from loops.expert import query
|
||||
>>> qu = query.Title('ty*')
|
||||
>>> list(qu.apply())
|
||||
[0, 1, 47]
|
||||
[0, 1, 68]
|
||||
|
||||
>>> qu = query.Type('loops:*')
|
||||
>>> len(list(qu.apply()))
|
||||
33
|
||||
37
|
||||
|
||||
>>> qu = query.Type('loops:concept:predicate')
|
||||
>>> len(list(qu.apply()))
|
||||
7
|
||||
8
|
||||
|
||||
>>> qu = query.Type('loops:concept:predicate') & query.Title('t*')
|
||||
>>> list(qu.apply())
|
||||
[1, 43]
|
||||
[1, 29]
|
||||
|
||||
State-based queries
|
||||
-------------------
|
||||
|
|
|
@ -66,13 +66,13 @@ zcml in real life:
|
|||
|
||||
>>> t = searchView.typesForSearch()
|
||||
>>> len(t)
|
||||
14
|
||||
16
|
||||
>>> t.getTermByToken('loops:resource:*').title
|
||||
'Any Resource'
|
||||
|
||||
>>> t = searchView.conceptTypesForSearch()
|
||||
>>> len(t)
|
||||
11
|
||||
13
|
||||
>>> t.getTermByToken('loops:concept:*').title
|
||||
'Any Concept'
|
||||
|
||||
|
@ -91,7 +91,7 @@ a controller attribute for the search view.
|
|||
|
||||
>>> searchView.submitReplacing('1.results', '1.search.form', pageView)
|
||||
'submitReplacing("1.results", "1.search.form",
|
||||
"http://127.0.0.1/loops/views/page/.target80/@@searchresults.html");...'
|
||||
"http://127.0.0.1/loops/views/page/.target99/@@searchresults.html");...'
|
||||
|
||||
Basic (text/title) search
|
||||
-------------------------
|
||||
|
@ -177,7 +177,7 @@ of the concepts' titles:
|
|||
>>> request = TestRequest(form=form)
|
||||
>>> view = Search(page, request)
|
||||
>>> view.listConcepts()
|
||||
u"{identifier: 'id', items: [{label: 'Zope (Topic)', name: 'Zope', id: '85'}, {label: 'Zope 2 (Topic)', name: 'Zope 2', id: '87'}, {label: 'Zope 3 (Topic)', name: 'Zope 3', id: '89'}]}"
|
||||
u"{identifier: 'id', items: [{label: 'Zope (Thema)', name: 'Zope', id: '104'}, {label: 'Zope 2 (Thema)', name: 'Zope 2', id: '106'}, {label: 'Zope 3 (Thema)', name: 'Zope 3', id: '108'}]}"
|
||||
|
||||
Preset Concept Types on Search Forms
|
||||
------------------------------------
|
||||
|
@ -219,13 +219,13 @@ and thus include the customer type in the preset search types.
|
|||
|
||||
>>> searchView.conceptsForType('loops:concept:customer')
|
||||
[{'token': 'none', 'title': u'not selected'},
|
||||
{'token': '58', 'title': u'Customer 1'},
|
||||
{'token': '60', 'title': u'Customer 2'},
|
||||
{'token': '62', 'title': u'Customer 3'}]
|
||||
{'token': '77', 'title': u'Customer 1'},
|
||||
{'token': '79', 'title': u'Customer 2'},
|
||||
{'token': '81', 'title': u'Customer 3'}]
|
||||
|
||||
Let's use this new search option for querying:
|
||||
|
||||
>>> form = {'search.4.text_selected': u'58'}
|
||||
>>> form = {'search.4.text_selected': u'77'}
|
||||
>>> resultsView = SearchResults(page, TestRequest(form=form))
|
||||
>>> results = list(resultsView.results)
|
||||
>>> results[0].title
|
||||
|
|
|
@ -14,7 +14,8 @@ from loops.expert.setup import SetupManager as ExpertSetupManager
|
|||
from loops.resource import Resource
|
||||
from loops.knowledge.interfaces import IPerson
|
||||
from loops.knowledge.knowledge import Person
|
||||
from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
|
||||
#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
|
||||
from loops.knowledge.tests import importData
|
||||
from loops.setup import SetupManager, addObject
|
||||
from loops.tests.setup import TestSite as BaseTestSite
|
||||
from loops.type import ConceptType, ResourceType, TypeConcept
|
||||
|
@ -32,10 +33,11 @@ class TestSite(BaseTestSite):
|
|||
|
||||
component.provideAdapter(Person, provides=IPerson)
|
||||
|
||||
component.provideAdapter(KnowledgeSetupManager, name='knowledge')
|
||||
#component.provideAdapter(KnowledgeSetupManager, name='knowledge')
|
||||
component.provideAdapter(ExpertSetupManager, name='expert')
|
||||
setup = SetupManager(loopsRoot)
|
||||
concepts, resources, views = setup.setup()
|
||||
importData(loopsRoot)
|
||||
|
||||
tType = concepts.getTypeConcept()
|
||||
tDomain = concepts['domain']
|
||||
|
|
8
external/README.txt
vendored
8
external/README.txt
vendored
|
@ -17,7 +17,7 @@ Let's set up a loops site with basic and example concepts and resources.
|
|||
>>> concepts, resources, views = t.setup()
|
||||
>>> loopsRoot = site['loops']
|
||||
>>> len(concepts), len(resources), len(views)
|
||||
(30, 3, 1)
|
||||
(34, 3, 1)
|
||||
|
||||
|
||||
Importing loops Objects
|
||||
|
@ -44,7 +44,7 @@ Creating the corresponding objects
|
|||
>>> loader = Loader(loopsRoot)
|
||||
>>> loader.load(elements)
|
||||
>>> len(concepts), len(resources), len(views)
|
||||
(31, 3, 1)
|
||||
(35, 3, 1)
|
||||
|
||||
>>> from loops.common import adapted
|
||||
>>> adMyquery = adapted(concepts['myquery'])
|
||||
|
@ -118,7 +118,7 @@ Extracting elements
|
|||
>>> extractor = Extractor(loopsRoot, os.path.join(dataDirectory, 'export'))
|
||||
>>> elements = list(extractor.extract())
|
||||
>>> len(elements)
|
||||
52
|
||||
67
|
||||
|
||||
Writing object information to the external storage
|
||||
--------------------------------------------------
|
||||
|
@ -130,6 +130,7 @@ Writing object information to the external storage
|
|||
>>> writer = PyWriter()
|
||||
>>> writer.write(elements, output)
|
||||
>>> print output.getvalue()
|
||||
type(u'task', ...)...
|
||||
type(u'country', u'Country', viewName=u'', typeInterface=u''..., options=u''...)...
|
||||
type(u'query', u'Query', viewName=u'', typeInterface='loops.expert.concept.IQueryConcept'..., options=u''...)...
|
||||
concept(u'myquery', u'My Query', u'query', options=u'option1\noption2',
|
||||
|
@ -171,6 +172,7 @@ corresponding extractor adapter.
|
|||
>>> PyWriter().write(extractor.extract(), output)
|
||||
|
||||
>>> print output.getvalue()
|
||||
type(u'task', ...)...
|
||||
type(u'country', u'Country', viewName=u'', typeInterface=u''..., options=u''...)...
|
||||
concept(u'myquery', u'My Query', u'query', options=u'option1\noption2',
|
||||
viewName=u'mystuff.html')[
|
||||
|
|
|
@ -18,15 +18,15 @@ ZCML setup):
|
|||
>>> from loops.interfaces import ILoops, IConcept
|
||||
>>> from loops.concept import Concept
|
||||
>>> from loops.setup import ISetupManager
|
||||
>>> from loops.knowledge.setup import SetupManager
|
||||
>>> component.provideAdapter(SetupManager, (ILoops,), ISetupManager,
|
||||
... name='knowledge')
|
||||
|
||||
>>> from loops.tests.setup import TestSite
|
||||
>>> t = TestSite(site)
|
||||
>>> concepts, resources, views = t.setup()
|
||||
>>> loopsRoot = site['loops']
|
||||
|
||||
>>> from loops.knowledge.tests import importData
|
||||
>>> importData(loopsRoot)
|
||||
|
||||
>>> from loops.knowledge.knowledge import Topic
|
||||
>>> component.provideAdapter(Topic)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ configuration):
|
|||
>>> concepts, resources, views = t.setup()
|
||||
|
||||
>>> len(concepts) + len(resources)
|
||||
18
|
||||
11
|
||||
|
||||
>>> loopsRoot = site['loops']
|
||||
>>> #loopsRoot.options = ['useVersioning:rev']
|
||||
|
|
|
@ -18,7 +18,7 @@ from loops.resource import Resource, FileAdapter, ExternalFileAdapter
|
|||
from loops.integrator.interfaces import IExternalSourceInfo, IExternalCollection
|
||||
from loops.integrator.interfaces import IOfficeFile
|
||||
from loops.integrator.office.base import OfficeFile
|
||||
from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
|
||||
#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
|
||||
from loops.setup import SetupManager, addAndConfigureObject
|
||||
from loops.tests.setup import TestSite as BaseTestSite
|
||||
from loops.versioning.versionable import VersionableResource
|
||||
|
@ -32,7 +32,7 @@ class TestSite(BaseTestSite):
|
|||
self.site = site
|
||||
|
||||
def setup(self):
|
||||
component.provideAdapter(KnowledgeSetupManager, name='knowledge')
|
||||
#component.provideAdapter(KnowledgeSetupManager, name='knowledge')
|
||||
concepts, resources, views = self.baseSetup()
|
||||
|
||||
component.provideAdapter(FileAdapter, provides=IFile)
|
||||
|
|
|
@ -9,11 +9,9 @@ type(u'task', u'Aufgabe', viewName=u'',
|
|||
type(u'topic', u'Thema', viewName=u'',
|
||||
typeInterface=u'loops.knowledge.interfaces.ITopic',
|
||||
options=u'action.portlet:createTopic,editTopic')
|
||||
type(u'training_event', u'Schulung', viewName=u'',
|
||||
type(u'training', u'Schulung', viewName=u'',
|
||||
typeInterface=u'loops.organize.interfaces.ITask',
|
||||
options=u'action.portlet:edit_concept')
|
||||
type(u'training_offer', u'Schulungsangebot', viewName=u'',
|
||||
typeInterface=u'', options=u'action.portlet:create_subtype,edit_concept')
|
||||
options=u'action.portlet:create_subtype,edit_concept')
|
||||
|
||||
concept(u'general', u'Allgemein', u'domain')
|
||||
concept(u'system', u'System', u'domain')
|
||||
|
@ -36,15 +34,11 @@ child(u'provides', u'general', u'standard')
|
|||
child(u'requires', u'general', u'standard')
|
||||
child(u'task', u'general', u'standard')
|
||||
child(u'topic', u'general', u'standard')
|
||||
child(u'training_event', u'general', u'standard')
|
||||
child(u'training_offer', u'general', u'standard')
|
||||
child(u'training', u'general', u'standard')
|
||||
|
||||
child(u'issubtype', u'system', u'standard')
|
||||
|
||||
child(u'training_event', u'competence', u'issubtype',
|
||||
usePredicate=u'provides')
|
||||
child(u'training_offer', u'competence', u'issubtype',
|
||||
usePredicate=u'provides')
|
||||
child(u'training', u'competence', u'issubtype', usePredicate=u'provides')
|
||||
|
||||
# records
|
||||
records(u'qualification', u'loops.knowledge.qualification.QualificationRecord')
|
||||
|
|
|
@ -38,9 +38,37 @@ from loops.organize.work.base import WorkItem, WorkItems
|
|||
@implementer(IStatesDefinition)
|
||||
def qualificationStates():
|
||||
return StatesDefinition('qualification',
|
||||
State('new', 'new',
|
||||
('plan', 'accept', 'start', 'work', 'finish', 'delegate', 'cancel'),
|
||||
color='red'),)
|
||||
State('open', 'open',
|
||||
('register', 'pass', 'fail', 'cancel', 'modify'),
|
||||
color='red'),
|
||||
State('registered', 'registered',
|
||||
('register', 'pass', 'fail', 'unregister', 'cancel', 'modify'),
|
||||
color='yellow'),
|
||||
State('passed', 'passed',
|
||||
('cancel', 'close', 'modify', 'open', 'expire'),
|
||||
color='green'),
|
||||
State('failed', 'failed',
|
||||
('register', 'cancel', 'modify', 'open'),
|
||||
color='green'),
|
||||
State('expired', 'expired',
|
||||
('register', 'cancel', 'modify', 'open'),
|
||||
color='red'),
|
||||
State('cancelled', 'cancelled', ('modify', 'open'),
|
||||
color='grey'),
|
||||
State('closed', 'closed', ('modify', 'open'),
|
||||
color='lightblue'),
|
||||
# not directly reachable states:
|
||||
State('open_x', 'open', ('modify',), color='red'),
|
||||
State('registered_x', 'registered', ('modify',), color='yellow'),
|
||||
# transitions:
|
||||
Transition('register', 'register', 'registered'),
|
||||
Transition('pass', 'pass', 'passed'),
|
||||
Transition('fail', 'fail', 'failed'),
|
||||
Transition('unregister', 'unregister', 'open'),
|
||||
Transition('cancel', 'cancel', 'cancelled'),
|
||||
Transition('close', 'close', 'closed'),
|
||||
Transition('open', 'open', 'open'),
|
||||
initialState='open')
|
||||
|
||||
|
||||
class QualificationRecord(WorkItem):
|
||||
|
@ -48,8 +76,16 @@ class QualificationRecord(WorkItem):
|
|||
implements(IQualificationRecord)
|
||||
|
||||
typeName = 'QualificationRecord'
|
||||
typeInterface = IQualificationRecord
|
||||
statesDefinition = 'knowledge.qualification'
|
||||
|
||||
def doAction(self, action, userName, **kw):
|
||||
new = self.createNew(action, userName, **kw)
|
||||
new.userName = self.userName
|
||||
new.doTransition(action)
|
||||
new.reindex()
|
||||
return new
|
||||
|
||||
|
||||
class QualificationRecords(WorkItems):
|
||||
""" A tracking storage adapter managing qualification records.
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
# tests.py - loops.knowledge package
|
||||
|
||||
import os
|
||||
import unittest, doctest
|
||||
from zope.testing.doctestunit import DocFileSuite
|
||||
from zope.app.testing import ztapi
|
||||
from zope.interface.verify import verifyClass
|
||||
from loops.organize.party import Person
|
||||
from loops.setup import importData as baseImportData
|
||||
|
||||
|
||||
def importData(loopsRoot):
|
||||
importPath = os.path.join(os.path.dirname(__file__), 'data')
|
||||
baseImportData(loopsRoot, importPath, 'loops_knowledge_de.dmp')
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
"Basic tests for the knowledge sub-package."
|
||||
|
|
|
@ -260,7 +260,7 @@ Automatic security settings on persons
|
|||
|
||||
>>> from zope.traversing.api import getName
|
||||
>>> list(sorted(getName(c) for c in concepts['person'].getChildren()))
|
||||
[u'jim', u'john', u'martha', u'person.newuser']
|
||||
[u'general', u'jim', u'john', u'martha', u'person.newuser']
|
||||
|
||||
Person objects that have a user assigned to them receive this user
|
||||
(principal) as their owner.
|
||||
|
@ -358,7 +358,7 @@ Task view with edit action
|
|||
>>> from loops.organize.browser.task import TaskView
|
||||
>>> view = TaskView(task01, TestRequest())
|
||||
>>> list(view.getActions('portlet'))
|
||||
[]
|
||||
[...]
|
||||
|
||||
OK, the action is not provided automatically any more by the TaskView
|
||||
but has to be entered as a type option.
|
||||
|
@ -404,7 +404,7 @@ Send Email to Members
|
|||
>>> form.subject
|
||||
u"loops Notification from '$site'"
|
||||
>>> form.mailBody
|
||||
u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.97\n\n'
|
||||
u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.116\n\n'
|
||||
|
||||
|
||||
Show Presence of Other Users
|
||||
|
|
|
@ -18,7 +18,7 @@ Let's set up a loops site with basic and example concepts and resources.
|
|||
>>> concepts, resources, views = t.setup()
|
||||
>>> loopsRoot = site['loops']
|
||||
>>> len(concepts), len(resources), len(views)
|
||||
(30, 3, 1)
|
||||
(34, 3, 1)
|
||||
|
||||
>>> from cybertools.tracking.btree import TrackingStorage
|
||||
>>> from loops.system.job import JobRecord
|
||||
|
|
|
@ -26,14 +26,12 @@ configuration):
|
|||
>>> t = TestSite(site)
|
||||
>>> concepts, resources, views = t.setup()
|
||||
|
||||
>>> #sorted(concepts)
|
||||
>>> #sorted(resources)
|
||||
>>> len(concepts) + len(resources)
|
||||
23
|
||||
|
||||
>>> loopsRoot = site['loops']
|
||||
>>> loopsRoot.options = ['useVersioning']
|
||||
|
||||
>>> len(concepts) + len(resources)
|
||||
16
|
||||
|
||||
|
||||
Version Information
|
||||
===================
|
||||
|
|
|
@ -33,7 +33,7 @@ from loops.config.base import LoopsOptions
|
|||
from loops.interfaces import ILoopsObject, IConcept
|
||||
from loops.resource import Resource
|
||||
from loops.resource import IndexAttributes as ResourceIndexAttributes
|
||||
from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
|
||||
#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
|
||||
from loops.setup import SetupManager, addObject
|
||||
from loops.type import ConceptType, ResourceType, TypeConcept
|
||||
from loops.versioning.versionable import cleanupVersions
|
||||
|
@ -74,7 +74,7 @@ class TestSite(object):
|
|||
|
||||
loopsRoot = site['loops'] = Loops()
|
||||
|
||||
component.provideAdapter(KnowledgeSetupManager, name='knowledge')
|
||||
#component.provideAdapter(KnowledgeSetupManager, name='knowledge')
|
||||
setup = SetupManager(loopsRoot)
|
||||
concepts, resources, views = setup.setup()
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@ ZCML setup):
|
|||
>>> from loops.setup import addObject
|
||||
>>> from loops.organize.setup import SetupManager as OrganizeSetupManager
|
||||
>>> component.provideAdapter(OrganizeSetupManager, name='organize')
|
||||
>>> from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
|
||||
>>> component.provideAdapter(KnowledgeSetupManager, name='knowledge')
|
||||
>>> from loops.tests.setup import TestSite
|
||||
>>> t = TestSite(site)
|
||||
>>> concepts, resources, views = t.setup()
|
||||
|
@ -31,10 +29,13 @@ ZCML setup):
|
|||
>>> loopsRoot = site['loops']
|
||||
>>> loopsId = util.getUidForObject(loopsRoot)
|
||||
|
||||
>>> from loops.knowledge.tests import importData
|
||||
>>> importData(loopsRoot)
|
||||
|
||||
Let's look what setup has provided us with:
|
||||
|
||||
>>> len(concepts)
|
||||
18
|
||||
23
|
||||
|
||||
Now let's add a few more concepts:
|
||||
|
||||
|
@ -71,10 +72,11 @@ note that the 'hasType' predicate is not shown as it should not be
|
|||
applied in an explicit assignment.
|
||||
|
||||
>>> sorted(t['name'] for t in xrf.getConceptTypes())
|
||||
[u'customer', u'domain', u'file', u'note', u'person', u'predicate',
|
||||
u'task', u'textdocument', u'topic', u'type']
|
||||
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
|
||||
u'predicate', u'task', u'textdocument', u'topic', u'training', u'type']
|
||||
>>> sorted(t['name'] for t in xrf.getPredicates())
|
||||
[u'depends', u'knows', u'ownedby', u'provides', u'requires', u'standard']
|
||||
[u'depends', u'issubtype', u'knows', u'ownedby', u'provides', u'requires',
|
||||
u'standard']
|
||||
|
||||
We can also retrieve a certain object by its id or its name:
|
||||
|
||||
|
@ -93,8 +95,8 @@ All methods that retrieve one object also returns its children and parents:
|
|||
>>> ch[0]['name']
|
||||
u'hasType'
|
||||
>>> sorted(c['name'] for c in ch[0]['objects'])
|
||||
[u'customer', u'domain', u'file', u'note', u'person', u'predicate',
|
||||
u'task', u'textdocument', u'topic', u'type']
|
||||
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
|
||||
u'predicate', u'task', u'textdocument', u'topic', u'training', u'type']
|
||||
|
||||
>>> pa = defaultPred['parents']
|
||||
>>> len(pa)
|
||||
|
@ -112,8 +114,8 @@ We can also retrieve children and parents explicitely:
|
|||
>>> ch[0]['name']
|
||||
u'hasType'
|
||||
>>> sorted(c['name'] for c in ch[0]['objects'])
|
||||
[u'customer', u'domain', u'file', u'note', u'person', u'predicate',
|
||||
u'task', u'textdocument', u'topic', u'type']
|
||||
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
|
||||
u'predicate', u'task', u'textdocument', u'topic', u'training', u'type']
|
||||
|
||||
>>> pa = xrf.getParents('6')
|
||||
>>> len(pa)
|
||||
|
@ -172,14 +174,14 @@ Updating the concept map
|
|||
|
||||
>>> topicId = xrf.getObjectByName('topic')['id']
|
||||
>>> xrf.createConcept(topicId, u'zope2', u'Zope 2')
|
||||
{'description': u'', 'title': u'Zope 2', 'type': '22', 'id': '54',
|
||||
{'description': u'', 'title': u'Zope 2', 'type': '36', 'id': '75',
|
||||
'name': u'zope2'}
|
||||
|
||||
The name of the concept is checked by a name chooser; if the corresponding
|
||||
parameter is empty, the name will be generated from the title.
|
||||
|
||||
>>> xrf.createConcept(topicId, u'', u'Python')
|
||||
{'description': u'', 'title': u'Python', 'type': '22', 'id': '56',
|
||||
{'description': u'', 'title': u'Python', 'type': '36', 'id': '77',
|
||||
'name': u'python'}
|
||||
|
||||
If we try to deassign a ``hasType`` relation nothing will happen; a
|
||||
|
|
Loading…
Add table
Reference in a new issue