How to create relations in owlready2 after the dynamic creation of the property? - properties

Using owlready2 I can create properties for my ontology, as below:
with onto:
class Drug(Thing):
pass
class Ingredient(Thing):
pass
relation_name = "has_for_ingredient"
with onto:
NewProperty = types.new_class(relation_name, (ObjectProperty, FunctionalProperty))
NewProperty.domain = domain
NewProperty.range = range
I can see them using list(onto.properties()).
Now I want to create relations using the code below (in my actual code this will be done dynamically):
my_drug = Drug("my_drug")
acetaminophen = Ingredient("acetaminophen")
my_drug.has_for_ingredient = [acetaminophen]
but I get the error:
AttributeError: 'list' object has no attribute 'storid'
I have also tried to create the property using only ObjectProperty, without FunctionalProperty, but get the error:
AttributeError: 'int' object has no attribute 'namespace'
Using the documentation I could not figure what is the issue...
And also, what is the meaning of using the FunctionalProperty?

with onto:
NewProperty = types.new_class(relation_name, (ObjectProperty, ))
NewProperty.domain = [Drug]
NewProperty.range = [Ingredient]
was the way to go. Whereas:
with onto:
NewProperty = types.new_class(relation_name, (ObjectProperty))
...
thorws the AttributeError: 'list' object has no attribute 'storid'
Apparently a tuple is required to create the property dynamically.

Related

Setting a variable to linq query with no results

I have a table that holds links to websites about particular theaters. I want to retrieve the first link for a given theater. My code to set the variable:
Dim link As String = TheaterLinks.Where(Function(x) x.TheaterID = TheaterID).FirstOrDefault().Link
If there are no results (some theaters won't have any links), then I get:
Object reference not set to an instance of an object.
How do I do this? I tried:
Dim link As String = Links.Where(Function(x) x.TheaterID = TheaterID.DefaultIfEmpty().First().Link
But I can't figure out what to put inside DefaultIfEmpty(). I tried DefaultIfEmpty("") and DefaultIfEmpty(blankstringvariable) but then I get:
Value of type 'String' cannot be converted to type 'TheaterLink'.
The problem is that FirstOrDefault() is allowed to return null, in which case accessing Link property would throw an exception.
If you use VB.NET 14, add question mark for automatic null checking:
Dim link As String = TheaterLinks.Where(Function(x) x.TheaterID = TheaterID).FirstOrDefault()?.Link
(see ?.Link instead of .Link)
Otherwise, do it in two stages: first, get the object using FirstOrDefault, then null-check it manually with an If statement.
For my original example, I just had to add a question mark:
Dim link As String = Links.Where(Function(x) x.ID = id).FirstOrDefault()?.Link
I tried doing this in my model and got a "Nullable object must have a value" error, so I did the two-stage approach:
Dim eventDate = Events.Where(Function(x) x.ID = id).FirstOrDefault()?.EventDate
If eventDate.HasValue Then
'some code
Else
'some code
End If

How to correct filter fields domain in a model?

I'm getting the following error trying to filter a field by another field value of the same model.
File
"/opt/..../tfutbol/models/partido.py",
line 29, in Partido
figura = fields.Many2one('tfutbol.jugador',domain=[('equipo_id','=',local.id)])
RuntimeError: maximum recursion depth exceeded while calling a Python
object
The line of code trying with the problem is:
figura = fields.Many2one('tfutbol.jugador',domain=[('equipo_id','=',local.id),('equipo_id','=',visitante.id)])
All the relevant code, is above:
class Partido(models.Model):
_name = 'tfutbol.partido'
local = fields.Many2one('tfutbol.equipo')
visitante = fields.Many2one('tfutbol.equipo')
figura = fields.Many2one('tfutbol.jugador',domain=[('equipo_id','=',local.id),('equipo_id','=',visitante.id)])
class Equipo(models.Model):
_name = 'tfutbol.equipo'
name = fields.Char('Nombre')
jugador_ids = fields.One2many('tfutbol.jugador', 'equipo_id', string="Jugadores")
class Jugador(models.Model):
_name = 'tfutbol.jugador'
name = fields.Char('Nombre')
equipo_id = fields.Many2one('tfutbol.equipo')
Thanks for reading!
If you read the docstring on /odoo/fields.py on the Many2one class definition you will see that:
:param domain: an optional domain to set on candidate values on the
client side (domain or string)
That means that you cannot use the dot notation (record.field) to pull in values because this has not been implemented on javascript.
So what you can do to dynamically create a domain like the one you want is:
Create an onchange method that will be invoked every time you set a value on the local and visitante fields and will change the domain on the figura field. For example:
#api.onchange('figura','visitante')
def onchange_method(self):
domain = {}
domain['figura'] = [('equipo_id','=',self.local.id),('equipo_id','=',self.visitante.id)]
return {'domain': domain}
Note: When you do not set an operator in a domain with multiple leafs (parameters) an explicit AND is added, so in your domain you are searching for the equipo_id filed to be equal to self.local.id AND self.visitante.id which will not work, you might want to add an OR like:
['|',('equipo_id','=',self.local.id),('equipo_id','=',self.visitante.id)]

Elm : initialise set in the model

I am new to Elm. What I want to do is I am trying to initialise model with a set instead of a List, but given elm doesn't have any initialisers for sets (which is a shame, it'd be good if it was #{1,2,3}, as in Clojure), it is problematic.
With the code (Elm tutorial code, a little bit modified), I am trying to
main =
App.program
{ init = init "cats"
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ topic : String
, gifUrl : String
, error : String
, history : Set String
}
init : String -> (Model, Cmd Msg)
init topic =
( Model topic "waiting.gif" "" Set.fromList([topic])
, getRandomGif topic
)
Which throws me a compiler error of:
Function `Model` is expecting 4 arguments, but was given 5.
Which is strange because this doesn't throw an error in Elm repl and is a valid code in most cases.
How would I achieve this?
The problem originates from your use of parentheses.
Model topic "waiting.gif" "" Set.fromList([topic])
-- is the same as:
Model topic "waiting.gif" "" Set.fromList [topic]
You don't need to enclose arguments in parentheses in Elm, but you do need to enclose the entire fourth parameter of Set.fromList [topic] so that the compiler knows it's a single parameter. Change it to this and you should be all set:
Model topic "waiting.gif" "" (Set.fromList [topic])

How can I get the value of a variable named after another one in groovy?

I have a variable that contains the name of another variable which I want to retrieve the value, e.g.:
def variable = "finalVariableValue"
def variableName = "variable"
How can I get variable.value as I only know variableName?
I've seen the a Binding could be used but I have a lot of variable that I need to put on this Binding object in order to make it works. Is the only way?
NB: this behaviour is really similar to the ant property extension mechanism.
Thanks,
Michele.
By prefixing it with def you are not registering it in an object you can inspect, like a map; one could argue it is registered in the AST, but that is a rocky road.
My 0.03 are working with a map, with a binding, or with dynamic properties. Drop the def part and choose one of the solutions:
Map
Simply declare the variable as a key in a map:
def map = [:]
map.variable = "finalVariableValue"
def variableName = "variable"
assert map[variableName] == "finalVariableValue"
Binding (with script)
Use the script built-in binding. Note this only works with scripts:
variable = "finalVariableValue"
variableName = "variable"
assert binding[variableName] == "finalVariableValue"
Dynamic properties
Use some dynamic properties mechanism, like an Expando (also, you could use getProperty with setProperty and others):
class Container extends Expando {
def declare() {
variable = "finalVariableValue"
variableName = "variable"
}
}
c = new Container()
c.declare()
assert c[c.variableName] == "finalVariableValue"
You can use the script's scope, simply dropping the Type definition:
variable = 'value'
name = 'variable'
assert 'variable' == this.name
assert 'value' == this[this.name]
or using #Field annotation:
import groovy.transform.Field
#Field def variable = 'value'
#Field def name = 'variable'
assert 'variable' == this.name
assert 'value' == this[this.name]

Pass array has object property from foxpro (to c#)

I'm trying to have a class that hold a array and use that class in some COM calls (I makes using C#).
So, I've got my classes like this:
DEFINE CLASS Logistics_Columns AS Session OLEPUBLIC
DIMENSION COLUMNS_ARRAY[1]
DIMENSION COLUMNS_ARRAY_COMATTRIB(4)
COLUMNS_ARRAY_COMATTRIB(1) = 0
COLUMNS_ARRAY_COMATTRIB(2) = "COLUMNS_ARRAY"
COLUMNS_ARRAY_COMATTRIB(3) = "COLUMNS_ARRAY"
COLUMNS_ARRAY_COMATTRIB(4) = "Array"
ENDDEFINE
DEFINE CLASS Logistics_Column AS Session OLEPUBLIC
COLUMN_NAME = .NULL.
DIMENSION COLUMN_NAME_COMATTRIB(4)
COLUMN_NAME_COMATTRIB(1) = 0
COLUMN_NAME_COMATTRIB(2) = "COLUMN_NAME"
COLUMN_NAME_COMATTRIB(3) = "COLUMN_NAME"
COLUMN_NAME_COMATTRIB(4) = "Character"
COLUMN_TYPE = .NULL.
DIMENSION COLUMN_TYPE_COMATTRIB(4)
COLUMN_TYPE_COMATTRIB(1) = 0
COLUMN_TYPE_COMATTRIB(2) = "COLUMN_TYPE"
COLUMN_TYPE_COMATTRIB(3) = "COLUMN_TYPE"
COLUMN_TYPE_COMATTRIB(4) = "Character"
COLUMN_WIDTH = .NULL.
DIMENSION COLUMN_WIDTH_COMATTRIB(4)
COLUMN_WIDTH_COMATTRIB(1) = 0
COLUMN_WIDTH_COMATTRIB(2) = "COLUMN_WIDTH"
COLUMN_WIDTH_COMATTRIB(3) = "COLUMN_WIDTH"
COLUMN_WIDTH_COMATTRIB(4) = "Integer"
COLUMN_PRECISION = .NULL.
DIMENSION COLUMN_PRECISION_COMATTRIB(4)
COLUMN_PRECISION_COMATTRIB(1) = 0
COLUMN_PRECISION_COMATTRIB(2) = "COLUMN_PRECISION"
COLUMN_PRECISION_COMATTRIB(3) = "COLUMN_PRECISION"
COLUMN_PRECISION_COMATTRIB(4) = "Integer"
ENDDEFINE
In C# for the Logistics_Columns class, COLUMNS_ARRAY is not seen as an array.
Yet or the Logistics_Column class all 4 properties are correctly seen as string or integer.
I guess "Array" (COLUMNS_ARRAY_COMATTRIB(4) = "Array")isn't the right literal value to indicate an array.
But then, what is?
As planned I created a custom collection wrapper.
It's basically a foxpro class of type Session OLEPUBLIC which store a Collection and wraps its methods.
Regarding the performance I think it adds some noticeable overhead, but it's the best method I could eventually come with.