Reset sync_reasoner inferences - python

I am using the owlready2 python module on a local ontology.
I have connected an API endpoint, to submit queries on this ontology.
I need to submit some queries on the original ontology and some other on the updated (with the inferences) ontology.
When I use the sync_reasoner() function, the ontology is updated with the inferences made by HermiT (i.e. the default reasoner).
My issue is, that the inferences made by the reasoner persist among different calls to the attached function.
Is there a workaround to force reset the inferred properties?
def function():
onto = get_ontology("file:///path/file.owl").load()
namespace = onto.get_namespace("http://namespace")
do_operations_with_original_ontology()
with namespace:
sync_reasoner()
do_operations_with_UPDATED_ontology()
return None
Thank you for considering my question,
Argyris

Though I did not use extensively the reasoner functionalities of owlready2 I believe this is the same as for any ontology update using owlready2.
Basically in owlready2, to separate different ontologies or different versions of the same ontology (potentially making use of different namespaces) you need to put them in different "worlds". The syntax is described here.
Here is some code based on the documentation examples to give you an idea of the syntax
from owlready2 import *
world = World()
onto = world.get_ontology("http://test.org/onto.owl")
with onto:
class Drug(Thing):
pass
class ActivePrinciple(Thing):
pass
class has_for_active_principle(Drug >> ActivePrinciple):
pass
class someActivePrinciple(ActivePrinciple):
pass
class MyDrug(Drug):
has_for_active_principle = [someActivePrinciple] #this one has some property restriction
# let's separate the worlds
world2 = World()
onto2 = world2.get_ontology("http://test.org/onto.owl")
with onto2:
class Drug(Thing):
pass
class ActivePrinciple(Thing):
pass
class has_for_active_principle(Drug >> ActivePrinciple):
pass
class someActivePrinciple(ActivePrinciple):
pass
class MyDrug(Thing): # not a subClass of Drug
pass # missing the has_for_active_principle restriction
# now we can save without mixing the ontologies
onto.save(file=r"c:\temp\owlready.rdf", format="rdfxml")
onto2.save(file=r"c:\temp\owlready2.rdf", format="rdfxml")
Note that there is currently a bug which prevents from directly saving the "worlds", only the ontology can be saved, but the bug was already corrected in the development version. See the owlready forum relevant discussion

Related

Python #property Mapper 'mapped class User->user' has no property 'member_groups

Context: For my work, I'm running a script populate.py where we populate a database. It fails at a certain advanced stage (let's just say step 9) as I'm trying to add a new many to many association table.
I made some changes to correspond to a similar entity that works. Specifically I added some #property and #x.setter methods because I thought that would solve it or at least be good practice. Now I get a failure at an earlier stage that was working before (let's say step 4).
I'm not looking for a solution to either of these issues but an understanding of how there could be such an error as logged with respect to how python is designed to work.
The error is:
`sqlalchemy.exc.InvalidRequestError: Mapper 'mapped class User->user' has no property 'member_groups'`
I did change a class attribute from
member_groups
to
_member_groups
But I also added the following code
#property
def member_groups(self) -> List[MemberGroup]:
return self._member_groups
#member_groups.setter
def member_groups(self, new_member_groups):
'''
Now, what do we do with you?
'''
self._member_groups = new_member_groups
I thought the whole point of the #property decorator in python was for this very use case- that I could call the class attribute _foobar as long as I had the decorator grabbing and setting it correctly..
#property
def member_groups(self):
return self._foobar
..and that it shouldn't make any difference what the class attribute is called as long as we give what we want the user to access it through the property descriptor. I thought that was the whole purpose or at least a major point of this pythonic api, specifically to create pseudo private variables and not have it make a difference or be breaking with existing code, but it shows that mapped class has no property.
I just want the theory, not a code solution per se, although I'll take ideas if you have them. I just want to understand Python better.

"Updater" design pattern, as opposed to "Builder"

This is actually language agnostic, but I always prefer Python.
The builder design pattern is used to validate that a configuration is valid prior to creating an object, via delegation of the creation process.
Some code to clarify:
class A():
def __init__(self, m1, m2): # obviously more complex in life
self._m1 = m1
self._m2 = m2
class ABuilder():
def __init__():
self._m1 = None
self._m2 = None
def set_m1(self, m1):
self._m1 = m1
return self
def set_m2(self, m1):
self._m2 = m2
return self
def _validate(self):
# complicated validations
assert self._m1 < 1000
assert self._m1 < self._m2
def build(self):
self._validate()
return A(self._m1, self._m2)
My problem is similar, with an extra constraint that I can't re-create the object each time due to to performance limitations.
Instead, I want to only update an existing object.
Bad solutions I came up with:
I could do as suggested here and just use setters like so
class A():
...
set_m1(self, m1):
self._m1 = m1
# and so on
But this is bad because using setters
Beats the purpose of encapsulation
Beats the purpose of the buillder (now updater), which is supposed to validate that some complex configuration is preserved after the creation, or update in this case.
As I mentioned earlier, I can't recreate the object every time, as this is expensive and I only want to update some fields, or sub-fields, and still validate or sub-validate.
I could add update and validation methods to A and call those, but this beats the purpose of delegating the responsibility of updates, and is intractable in the number of fields.
class A():
...
def update1(m1):
pass # complex_logic1
def update2(m2):
pass # complex_logic2
def update12(m1, m2):
pass # complex_logic12
I could just force to update every single field in A in a method with optional parameters
class A():
...
def update("""list of all fields of A"""):
pass
Which again is not tractable, as this method will soon become a god method due to the many combinations possible.
Forcing the method to always accept changes in A, and validating in the Updater also can't work, as the Updater will need to look at A's internal state to make a descision, causing a circular dependency.
How can I delegate updating fields in my object A
in a way that
Doesn't break encapsulation of A
Actually delegates the responsibility of updating to another object
Is tractable as A becomes more complicated
I feel like I am missing something trivial to extend building to updating.
I am not sure I understand all of your concerns, but I want to try and answer your post. From what you have written I assume:
Validation is complex and multiple properties of an object must be checked to decide if any change to the object is valid.
The object must always be in a valid state. Changes that make the object invalid are not permitted.
It is too expensive to copy the object, make the change, validate the object, and then reject the change if the validation fails.
Move the validation logic out of the builder and into a separate class like ModelValidator with a validateModel(model) method
The first option is to use a command pattern.
Create abstract class or interface named Update (I don't think Python abstract classes/interfaces, but that's fine). The Update interface implements two methods, execute() and undo().
A concrete class has a name like UpdateAdress, UpdatePortfolio, or UpdatePaymentInfo.
Each concrete Update object also holds a reference to your model object.
The concrete classes hold the state needed to for a particular kind of update. Imageine these methods exist on the UpdateAddress class:
UpdateAddress
setStreetNumber(...)
setCity(...)
setPostcode(...)
setCountry(...)
The update object needs to hold both the current and new values of a property. Like:
setStreetNumber(aString):
self.oldStreetNumber = model.getStreetNumber
self.newStreetNumber = aString
When the execute method is called, the model is updated:
execute:
model.setStreetNumber(newStreetNumber)
model.setCity(newCity)
# Set postcode and country
if not ModelValidator.isValid(model):
self.undo()
raise ValidationError
and the undo method looks like:
undo:
model.setStreetNumber(oldStreetNumber)
model.setCity(oldCity)
# Set postcode and country
That is a lot of typing, but it would work. Mutating your model object is nicely encapsulated by different kinds of updates. You can execute or undo the changes by calling those methods on the update object. You can even store a list of update objects for multi-level undos and re-tries.
However, it is a lot of typing for the programmer. Consider using persistent data structures. Persistent data structures can be used to copy objects very quickly -- approximately constant time complexity. Here is a python library of persistent data structures.
Let's assume your data was in a persistent data structure version of a dict. The library I referenced calls it a PMap.
The implementation of the update classes can be simpler. Starting with the constructor:
UpdateAddress(pmap)
self.oldPmap = pmap
self.newPmap = pmap
The setters are easier:
setStreetNumber(aString):
self.newPmap = newPmap.set('streetNumber', aString)
Execute passes back a new instance of the model, with all the updates.
execute:
if ModelValidator.isValid(newModel):
return newModel;
else:
raise ValidationError
The original object has not changed at all, thanks to the magic of persistent data structures.
The best thing is to not do any of this. Instead, use an ORM or object database. That is the "enterprise grade" solution. These libraries give you sophisticated tools like transactions and object version history.

Creating Object With A For Loop

Firstly, I do apologise as I'm not quite sure how to word this query within the Python syntax. I've just started learning it today having come from a predominantly PowerShell-based background.
I'm presently trying to obtain a list of projects within our organisation within Google Cloud. I want to display this information in two columns: project name and project number - essentially an object. I then want to be able to query the object to say: where project name is "X", give me the project number.
However, I'm rather having difficulty in creating said object. My code is as follows:
import os
from pprint import pprint
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials
credentials = GoogleCredentials.get_application_default()
service = discovery.build('cloudresourcemanager', 'v1', credentials=credentials)
request = service.projects().list()
response = request.execute()
projects = response.get('projects')
The 'projects' variable then seems to be a list, rather than an object I can explore and run queries against. I've tried running things like:
pprint(projects.name)
projects.get('name')
Both of which return the error:
"AttributeError: 'list' object has no attribute 'name'"
I looked into creating a Class within a For loop as well, which nearly gave me what I wanted, but only displayed one project name and project number at a time, rather than the entire collection I can query against:
projects=[]
for project in response.get('projects', []):
class ProjectClass:
name = project['name']
projectNumber = project['projectNumber']
projects.append(ProjectClass.name)
projects.append(ProjectClass.projectNumber)
I thought if I stored each class in a list it might work, but alas, no such joy! Perhaps I need to have the For loop within the class variables?
Any help with this would be greatly appreciated!
As #Code-Apprentice mentioned in a comment, I think you are missing a critical understanding of object-oriented programming, namely the difference between a class and an object. Think of a class as a "blueprint" for creating objects. I.E. your class ProjectClass tells python that objects of type ProjectClass will have two fields, name and projectNumber. However, ProjectClass itself is just the blueprint, not an object. You then need to create an instance of ProjectClass, which you would do like so:
project_class_1 = ProjectClass()
Great, now you have an object of type ProjectClass, and it will have fields name and projectNumber, which you can reference like so:
project_class_1.name
project_class_1.projectNumber
However, you will notice that all instances of the class that you create will have the same value for name and projectNumber, this just won't do! We need to be able to specify values when we create each instance. Enter init(), a special python method colloquially referred to as the constructor. This function is called by python automatically when we create a new instance of our class as above, and is responsible for setting up all the fields of that class. Another powerful feature of classes and objects is that you can define a collection of different functions that can be called at will.
class ProjectClass:
def __init__(self, name, projectNumber):
self.name = name
self.projectNumber = projectNumber
Much better. But wait, what's that self variable? Well, just as before we were able reference the fields of our instance via the "project_class_1" variable name, we need a way to access the fields of our instance when we're running functions that are a part of that instance, right? Enter self. Self is another python builtin parameter that contains a reference to the current instance of the ProjectClass that is being accessed. That way, we can set fields on the instance of the class that will persist, but not be shared or overwritten by other instances of the ProjectClass. It's important to remember that the first argument passed to any function defined on a class will always be self (except for some edge-cases you don't need to worry about now).
So restructuring your code, you would have something like this:
class ProjectClass:
def __init__(self, name, projectNumber):
self.name = name
self.projectNumber = projectNumber
projects = []
for project in response.get('projects', []):
projects.append(ProjectClass(project["name"], project["projectNumber"])
Hopefully I've explained this well and given you a complete answer on how all these pieces fit together. The hope is for you to be able to write that code on your own and not just give you the answer!

About converting custom functions in models into annotations in custom managers/querysets

Being new to Django, I'm starting to care a bit about performance of my web application.
I'm trying to transform many of my custom functions / properties which were originally in my models to querysets within custom managers.
in my model I have:
class Shape(models.Model):
#property
def nb_color(self):
return 1 if self.colors=='' else int(1+sum(self.colors.upper().count(x) for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
def __str__(self):
return self.name + "-" + self.constraints
#property
def image_url(self):
return format_html(f'{settings.SVG_DIR}/{self}.svg')
#property
def image_src(self):
return format_html('<img src="{url}"|urlencode />'.format(url = self.image_url))
def image_display(self):
return format_html(f'{self.image_src}"')
But I'm not clear on a few points:
1/ is there any pros or cons declaring with the propriety decorator in a django model?
2/ what is the cost of calling a function/property in term of database calls
and therefore, is there an added value to use custom managers / querysets and define annotations to simulate my functions at that level?
3/ how would you suggest me to transform my image & nb_color functions into annotations
Thanks in advance
PS: For the image related functions, I mostly figured it out:
self.annotate(image_url = Concat(Value(join(settings.SVG_DIR,'')), F('fullname'), Value('.svg'), output_field=CharField()),
image_src = Concat(Value('<img src="'), F('image_url'), Value('"|urlencode />'), output_field=CharField()),
image_display = Concat(Value(''),F('image_src'), Value(''), output_field=CharField()),
)
I am however having an issue for the display of image_src
through:
readonly_fields=['image']
def image(self, obj):
return format_html(obj.image_src)
it doesn't seem to find the image while the adress is ok.
If anybody has an idea...
PS: For the image related functions, I mostly figured it out:
self.annotate(image_url = Concat(Value(join(settings.SVG_DIR,'')),
F('fullname'), Value('.svg'), output_field=CharField()),
image_src = Concat(Value(''), output_field=CharField()),
image_display = Concat(Value(''),F('image_src'),
Value(''), output_field=CharField()),
) I am however having an issue for the display of image_src through:
readonly_fields=['image'] def image(self, obj):
return format_html(obj.image_src) it doesn't seem to find the image while the adress is ok.
I figured it up for my image problem: I should simply use a relative path and let Django manage:
self.annotate(image_url = Concat(Value('/static/SVG_shapes/'), F('fullname'), Value('.svg'), output_field=CharField()),)
With now 1.5 years more experience, I'll try to answer my newbie questions for the next ones who may have the same questions poping into their minds.
1/ is there any pros or cons declaring with the propriety decorator in a django model?
No cons that I could see so far.
It allows the data to be retrieved as a property of the model (my_shape.image_url), instead of having to call the corresponding method (my_shape.image_url())
However, for different purposes, one my prefer to have a callable (the method) instead of a property
2/ what is the cost of calling a function/property in term of database calls
No extra calling to the database if the data it needs as input are already available, or are themselves attributes of the instance object (fields / properties / methods that don't require input from outside the instance object)
However, if external data are needed, a database call will be generated for each of them.
For this reason, it can be valuable to cache the result of such a property by using the #cached_property decorator instead of the #property decorator
The only thing needed to use cached properties is the following import:
from django.utils.functional import cached_property
After being called for the first time, the cached property will remain available at no extra cost during all the lifetime of the object instance,
and its content can be manipulated like any other property / variable:
and therefore, is there an added value to use custom managers / querysets and define annotations to simulate my functions at that level?
In my understanding and practice so far, it is not uncommon to replicate the same functionality in both property & managers
The reason is that properties are easily available when we are interested only in one specific object instance,
while when you are interested into comparing / retrieving a given property for a range of objects, it is much more efficient to calculate & annotate this property for the whole queryset, for instance through using model managers
My give-away would be:
For a given model,
(1) try to put all the business logic concerning a single object instance into model methods / properties
(2) and all the business logic concerning a range of objects into model managers
3/ how would you suggest me to transform my image & nb_color functions into annotations
Already answered in previous answer

classes or objects within a class/object

I read related posts but they didn't satisfy me.
Using tkinter i coded a class Musicsheet. Then I wrote classes of notes like wholeNote & halfNote, etc. After instantiaing MusicSheet followed by an instance of WholeNote, it looked ok, with the whole note on the music sheet. However, when I instantiated a half note the whole note had disappeared with just the half note on the sheet;it looks like halfNote had also instantiated ( sub classed?) a new music sheet thus previous notes/objects aren't there. This result in that the latest instance is always the only one on the sheet.
Thanks for the replies. Here are additional info:
class Musicsheet(Frame):
.......TCanvas initialization..
class WholeNote(MusicSheet):
......
class HalfNote(MusicSheet):
def __init__(self,x1,y1,x2,y2)
self.can.create_oval(x1,y1,x2,y2)
.....
more notes classes follow
Based on your current code:
Your note classes are derived from MusicSheet. I suppose you want the notes to be part of the sheet, not an instance of the Sheet. If you derive them from MusicSheet, the init of a Note would create a new instance of MusicSheet, not be added to the MusicSheet.
For Notes i recommend using Tkinter.CanvasItem class for inheritance.
(Type should be polygon for everything that is not a half/full rest or full note)
Using self.can.create_oval should be done in MusicSheet, not in Note Classes, as self.can should refer to the MusicSheet.

Categories