Type Provider not seen by reflection - reflection

I'm trying to write my first type provider and am wondering if someone could point where I am going wrong.
I've used the freebase sample to work from. I've tried to sift thru the essential bits to get something very basic instantiated but obviously missed something or not got it quite right (perhaps in relation to the namespace). I'm simply trying to get this line working
type tp = MyFirstTypeProvider.DataProvider<username="username",password="password",product=prodId>
Intellisense is seeing the DataProvider, but I'm getting squiggly saying that a reference to the type can be found the type could not be found in the assembly.
namespace MyFirstProvider
type internal MyFirstRuntimeInfo(config: TypeProviderConfig) =
let runtimeAssembly = Assembly.LoadFrom(config.RuntimeAssembly)
member val DataContextType = runtimeAssembly.GetType("MyFirstProvider.Runtime.DataContext")
member this.RuntimeAssembly = runtimeAssembly
// This type defines the type provider. When compiled to a DLL, it can be added
// as a reference to an F# command-line compilation, script, or project.
[<TypeProvider>]
type public Types(config: TypeProviderConfig) as this =
inherit TypeProviderForNamespaces()
let bfRuntimeInfo = MyFirstRuntimeInfo(config)
let rootNamespace = "MyFirstProvider"
let defaultUsername = "xxxxxxxxxxx"
let defaultPassword = "yyyyyyyyyy"
let defaultProductId = -1
let defaultToken = "none"
let createDataContext = bfRuntimeInfo.DataContextType.GetMethod("_Create")
let createTypes(username, password, productId, rootTypeName) = let bf = new MyFirstProvider.Requests.Queries(defaultToken)
let schema = new MyFirstProvider.Schema.SchemaConnection(bf)
let rootType = ProvidedTypeDefinition(bfRuntimeInfo.RuntimeAssembly,rootNamespace,rootTypeName,baseType=Some typeof<obj>, HideObjectMethods=true)
let theServiceType = ProvidedTypeDefinition("Service",baseType=Some bfRuntimeInfo.DataContextType, HideObjectMethods=true)
let theServiceTypesClass = ProvidedTypeDefinition("ServiceTypes",baseType=Some typeof<obj>,HideObjectMethods=true)
theServiceTypesClass.AddMembers [ theServiceType ]
rootType.AddMembers [ theServiceTypesClass ]
rootType.AddMembersDelayed (fun () ->
[ yield ProvidedMethod ("GetDataContext", [], theServiceType, IsStaticMethod=true,
InvokeCode = (fun _args -> Expr.Call(createDataContext, [ Expr.Value defaultUsername; Expr.Value defaultPassword; Expr.Value defaultProductId ])))
])
rootType
let MyFirstType = createTypes(defaultUsername, defaultPassword, defaultProductId, "Data")
let paramMyFirstType = ProvidedTypeDefinition(bfRuntimeInfo.RuntimeAssembly, rootNamespace, "DataProvider", Some(typeof<obj>), HideObjectMethods = true)
let usernameParam = ProvidedStaticParameter("username", typeof<string>, defaultUsername)
let passwordParam = ProvidedStaticParameter("password", typeof<string>, defaultPassword)
let productIdParam = ProvidedStaticParameter("productId", typeof<int>, defaultProductId)
do paramMyFirstType.DefineStaticParameters([usernameParam;passwordParam;productIdParam], fun typeName providerArgs ->
let username = (providerArgs.[0] :?> string)
let password = (providerArgs.[1] :?> string)
let productId = (providerArgs.[2] :?> int)
createTypes(username, password, productId, typeName))
do
this.AddNamespace(rootNamespace, [MyFirstType ] )
this.AddNamespace(rootNamespace, [paramMyFirstType ] )
[<assembly:TypeProviderAssembly>]
do()
Many thx in advance.

When I try compiling your type provider and reference it in a script file, the reference #r "provider.dll" is underlined with a red squiggly that says:
The type provider 'MyFirstProvider.Types' reproted an error: The type provider constructor has thrown an exception: Object reference not set to an instance of an object.
You can debug such errors by starting a second instance of Visual Studio, and attaching the debugger to another instance (Debug -> Attach to Process) and opening the script file in the instance being debugged.
In the sample you posted here, the null reference exception occurs on this line:
let createDataContext = bfRuntimeInfo.DataContextType.GetMethod("_Create")
This is trying to access method that does not exist. I think the Freebase sample is relatively complicated starting point (here, it is using an object to represent the "data context" - you might want to follow that pattern, but I think it is easier to build it from scratch rather than adapting an existing code). I think a good starting point might be the Hello World type provider which is a lot simpler and just shows how to generate new types, properties and methods.

I would suggest, if you are looking for a simple example of type provider, to look at the File System type provider This is a good place to start as it has no state and no dependency management to take care of.
As to why this one has a dll it can not find, I think it is because this dll has to be seen from where your type provider's dll is. That is, for instance, in the same directory. (You can try to set "copy local" in the build process?)

Related

Is there a way to save nested entities in gcloud-python?

I'm trying to save an object into Cloud Datastore, the object contains a dictionary as a property value:
client = datastore.Client(project_id)
key = client.key('Config', 'config', 'Environment', 'env_name')
env = datastore.entity.Entity(key)
env['prop1'] = dict(foo='bar')
client.put(env)
but it raises
ValueError: Unknown protobuf attr type
Although I'm able to do so using gcloud-node.
Is it possible to save compound object using gcloud-python?
It sounds like you're interested in storing an embedded entity, which I believe is what gcloud-node does automagically.
I think you can do this by setting the field (prop1) to a datastore.Entity containing a sub-property (foo) set to 'bar'.
client = datastore.Client(project_id)
key = client.key('Config', 'config', 'Environment', 'env_name')
env = datastore.Entity(key)
env['prop1'] = datastore.Entity(key=client.key('EmbeddedKind')
env['prop1']['foo'] = 'bar'
client.put(env)
When you get this back, it'll look like...
>>> c.get(env.key)
<Entity[{'kind': u'Config', 'name': u'config'}, {'kind': u'Env', 'name': u'env_name'}] {u'prop1': <Entity[{'kind': u'Embedded'}] {u'foo': 'bar'}>}>

Losing some z3c relation data on restart

I have the following code which is meant to programmatically assign relation values to a custom content type.
publications = # some data
catalog = getToolByName(context, 'portal_catalog')
for pub in publications:
if pub['custom_id']:
results = catalog(custom_id=pub['custom_id'])
if len(results) == 1:
obj = results[0].getObject()
measures = []
for m in pub['measure']:
if m in context.objectIds():
m_id = intids.getId(context[m])
relation = RelationValue(m_id)
measures.append(relation)
obj.measures = measures
obj.reindexObject()
notify(ObjectModifiedEvent(obj))
Snippet of schema for custom content type
measures = RelationList(
title=_(u'Measure(s)'),
required=False,
value_type=RelationChoice(title=_(u'Measure'),
source=ObjPathSourceBinder(object_provides='foo.bar.interfaces.measure.IMeasure')),
)
When I run my script everything looks good. The problem is when my template for the custom content tries to call "pub/from_object/absolute_url" the value is blank - only after a restart. Interestingly, I can get other attributes of pub/from_object after a restart, just not it's URL.
from_object retrieves the referencing object from the relation catalog, but doesn't put the object back in its proper Acquisition chain. See http://docs.plone.org/external/plone.app.dexterity/docs/advanced/references.html#back-references for a way to do it that should work.

Filtering tab completion in input task implementation

I'm currently implementing a SBT plugin for Gatling.
One of its features will be to open the last generated report in a new browser tab from SBT.
As each run can have a different "simulation ID" (basically a simple string), I'd like to offer tab completion on simulation ids.
An example :
Running the Gatling SBT plugin will produce several folders (named from simulationId + date of report generaation) in target/gatling, for example mysim-20140204234534, myothersim-20140203124534 and yetanothersim-20140204234534.
Let's call the task lastReport.
If someone start typing lastReport my, I'd like to filter out tab-completion to only suggest mysim and myothersim.
Getting the simulation ID is a breeze, but how can help the parser and filter out suggestions so that it only suggest an existing simulation ID ?
To sum up, I'd like to do what testOnly do, in a way : I only want to suggest things that make sense in my context.
Thanks in advance for your answers,
Pierre
Edit : As I got a bit stuck after my latest tries, here is the code of my inputTask, in it's current state :
package io.gatling.sbt
import sbt._
import sbt.complete.{ DefaultParsers, Parser }
import io.gatling.sbt.Utils._
object GatlingTasks {
val lastReport = inputKey[Unit]("Open last report in browser")
val allSimulationIds = taskKey[Set[String]]("List of simulation ids found in reports folder")
val allReports = taskKey[List[Report]]("List of all reports by simulation id and timestamp")
def findAllReports(reportsFolder: File): List[Report] = {
val allDirectories = (reportsFolder ** DirectoryFilter.&&(new PatternFilter(reportFolderRegex.pattern))).get
allDirectories.map(file => (file, reportFolderRegex.findFirstMatchIn(file.getPath).get)).map {
case (file, regexMatch) => Report(file, regexMatch.group(1), regexMatch.group(2))
}.toList
}
def findAllSimulationIds(allReports: Seq[Report]): Set[String] = allReports.map(_.simulationId).distinct.toSet
def openLastReport(allReports: List[Report], allSimulationIds: Set[String]): Unit = {
def simulationIdParser(allSimulationIds: Set[String]): Parser[Option[String]] =
DefaultParsers.ID.examples(allSimulationIds, check = true).?
def filterReportsIfSimulationIdSelected(allReports: List[Report], simulationId: Option[String]): List[Report] =
simulationId match {
case Some(id) => allReports.filter(_.simulationId == id)
case None => allReports
}
Def.inputTaskDyn {
val selectedSimulationId = simulationIdParser(allSimulationIds).parsed
val filteredReports = filterReportsIfSimulationIdSelected(allReports, selectedSimulationId)
val reportsSortedByDate = filteredReports.sorted.map(_.path)
Def.task(reportsSortedByDate.headOption.foreach(file => openInBrowser((file / "index.html").toURI)))
}
}
}
Of course, openReport is called using the results of allReports and allSimulationIds tasks.
I think I'm close to a functioning input task but I'm still missing something...
Def.inputTaskDyn returns a value of type InputTask[T] and doesn't perform any side effects. The result needs to be bound to an InputKey, like lastReport. The return type of openLastReport is Unit, which means that openLastReport will construct a value that will be discarded, effectively doing nothing useful. Instead, have:
def openLastReport(...): InputTask[...] = ...
lastReport := openLastReport(...).evaluated
(Or, the implementation of openLastReport can be inlined into the right hand side of :=)
You probably don't need inputTaskDyn, but just inputTask. You only need inputTaskDyn if you need to return a task. Otherwise, use inputTask and drop the Def.task.

What's wrong with my filter query to figure out if a key is a member of a list(db.key) property?

I'm having trouble retrieving a filtered list from google app engine datastore (using python for server side). My data entity is defined as the following
class Course_Table(db.Model):
course_name = db.StringProperty(required=True, indexed=True)
....
head_tags_1=db.ListProperty(db.Key)
So the head_tags_1 property is a list of keys (which are the keys to a different entity called Headings_1).
I'm in the Handler below to spin through my Course_Table entity to filter the courses that have a particular Headings_1 key as a member of the head_tags_1 property. However, it doesn't seem like it is retrieving anything when I know there is data there to fulfill the request since it never displays the logs below when I go back to iterate through the results of my query (below). Any ideas of what I'm doing wrong?
def get(self,level_num,h_key):
path = []
if level_num == "1":
q = Course_Table.all().filter("head_tags_1 =", h_key)
for each in q:
logging.info('going through courses with this heading name')
logging.info("course name filtered is %s ", each.course_name)
MANY MANY THANK YOUS
I assume h_key is key of headings_1, since head_tags_1 is a list, I believe what you need is IN operator. https://developers.google.com/appengine/docs/python/datastore/queries
Note: your indentation inside the for loop does not seem correct.
My bad apparently '=' for list is already check membership. Using = to check membership is working for me, can you make sure h_key is really a datastore key class?
Here is my example, the first get produces result, where the 2nd one is not
import webapp2 from google.appengine.ext import db
class Greeting(db.Model):
author = db.StringProperty()
x = db.ListProperty(db.Key)
class C(db.Model): name = db.StringProperty()
class MainPage(webapp2.RequestHandler):
def get(self):
ckey = db.Key.from_path('C', 'abc')
dkey = db.Key.from_path('C', 'def')
ekey = db.Key.from_path('C', 'ghi')
Greeting(author='xxx', x=[ckey, dkey]).put()
x = Greeting.all().filter('x =',ckey).get()
self.response.write(x and x.author or 'None')
x = Greeting.all().filter('x =',ekey).get()
self.response.write(x and x.author or 'None')
app = webapp2.WSGIApplication([('/', MainPage)],
debug=True)

iPhone CoreData join

this is my core data model:
I'm trying to get all LanguageEntries from a database for a given category.categoryName and languageset.languageSetName e.g.
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"LanguageEntry" inManagedObjectContext:del.managedObjectContext];
[fetchRequest setEntity:entity];
NSString* predicateString = [NSString stringWithFormat:#"Category.categoryName = %# AND LanguageSet.languageSetName = %#",
#"Food", #"English####Spanish"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:predicateString];
NSError *error = nil;
NSArray* objects = [del.managedObjectContext executeFetchRequest:fetchRequest error:&error];
This always returns 0 objects. If I set the predicate string to match on one relationship (e.g. Category.categoryName = Food or languageSet.languageSetName = English####Spanish) it will return data.
This is baffling, can anyone shed some light?
->Ken
Your can't think of Core Data as SQL. There is no such thing as a "join" in Core Data. In this case, your trying to find the intersection of two sets of objects. Close to a join logically but not in the implementation details. And the programming devil is always in the details.
Try using the logical equal "==" like so:
#"Category.categoryName == %# AND LanguageSet.languageSetName == %#"
I believe that will solve your problem.
The data model has a predicate editor hidden way in it. It can help you set up predicates even if you don't embed them in fetches in model itself. Just select an entity, in your case "LanguageEntity", then add a Fetch Request. The edit predicate will appear and you can use the dialog to create the predicate. It will display a textual version of the predicate that you can copy into your code.
The predicate properly wasn't created correctly, you must pass the parameters to predicateWithFormat. It should have been:
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"Category.categoryName = %# AND LanguageSet.languageSetName = %#",
#"Food",
#"English####Spanish"];
In case you were wondering what that does is it puts quotes around the string parameters automatically which are required when using a string in a predicate. When you created the query using NSString's format method that did not put the required quotes in.

Resources