z3c.forms dynamic sources provider returns empty dictionary as a context object - plone

I'm using Plone 4.1.4 and I'm trying to get dynamic sources for a schema.Choice to work, I need to populate country list which in turn depends on the context object.
I'm using this example:
http://plone.org/products/dexterity/documentation/manual/developer-manual/advanced/vocabularies
For IContextSourceBinder, example, an empty dictionary instead of actual context object is returned:
from zope import interface
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
from zope.schema.interfaces import IContextSourceBinder
import zope.schema
from z3c.form import form
class CountryGenerator(object):
interface.implements(IContextSourceBinder)
def __call__(self, context):
#context is == {}
import pdb; pdb.set_trace()
return SimpleVocabulary([
SimpleTerm(value="not_selected", title=_("Country Not Selected"))
])
class IStep(interface.Interface):
region = schema.Choice(title=_("Select your country"),
required=True,
source=CountryGenerator,
default="not_selected")
class Step(form.Form):
fields = field.Fields(IStep)
label = _("Step")
description = _("Select your country")
When debugging point is hit inside CountryGenerator.__call__() method and I examine context object, the latter turn out to be just an empty dictionary.
When I try to use named utility example in the article mentioned above, and the similar thing happens, context there is also {}.
Could anyone point me to what I might be doing wrong?
UPDATE
ZCML for the form wrapper that calls the form is
<browser:page
name="view"
for="Products.oldproduct.MyFolderishClass"
class=".file.RegionClass"
permission="zope2.View"
/>
Where RegionClass inherits from Form wrapper, could it be permission or traversal issue?

Because your source is a class, you need to instantiate it:
class IStep(interface.Interface):
region = schema.Choice(title=_("Select your country"),
required=True,
source=CountryGenerator(),
default="not_selected")
In certain circumstances, such as with using sub forms or complex form widgets (widget within a widget for list selections, etc), you need to follow the __parent__ pointers to a proper outer context for getting back to the Plone context.

Related

Making a minecraft mod in java. Creating and registering an instance

I'm trying to make an uranium ingot that gives players that hold it in their inventory a wither effect. I got some tips from the minecraft forums, they told me to do to make my item give me the wither effect.
Re: 1.10.2 Item has wither « Reply #2 on: Today at 02:29:58 am » QuoteThank You Create a class that extends Item and overrides
Item#onUpdate.
In your override, check if the entityIn argument is an instance of EntityLivingBase. If it is, cast it to EntityLivingBase and call EntityLivingBase#isPotionActive to check if it has the MobEffects.WITHER effect active. If it doesn't, create a PotionEffect and call EntityLivingBase#addPotionEffect to add it.
My Question
Create and register an instance of this class instead of Item.
The last line is what im confused on.
Here is the class i made that he told me to do. Also please inform me if i didnt do something else right in this class
package item;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.MobEffects;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.PotionEffect;
import net.minecraft.world.World;
public class UraniumIngotEffect extends Item{
#Override
public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) {
if(entityIn instanceof EntityLivingBase){
Object EntityLivingBase = ((EntityLivingBase) entityIn).isPotionActive(MobEffects.WITHER);
}else{
Object PotionEffect = new PotionEffect(MobEffects.WITHER);
}
super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected);
}
}
You need to make the item object in your mod hold the onUpdate method.
This means:
have a class that extends Item(your uranium ingot)
Register the item in the item loader
Item myurnanium = new UraniumIngot();
GameRegistry.register(myuranium);
and of course make the proper json files so the item will render properly.
I suggest you read:
http://bedrockminer.jimdo.com/modding-tutorials/basic-modding-1-8/first-item/

Plone- In a dexterity.EditForm why is attempting to disable a widget causing a ConstraintNotSatisfied error?

I'm trying to disable a widget in a dexterity.EditForm, but I'm getting an error .
Here is a part of my interface class with the particular widget I want to disable
class IRestaurant(IPlace):
restaurant_code = schema.TextLine(title=_(u""),
required=False,
)
IPlace is a form.Schema that IRestaurant inherits from. (from plone.directives)
Here is the code I for the dexterity.EditForm class:
class Edit(dexterity.EditForm):
grok.context(IRestaurant)
def updateWidgets(self):
super(Edit, self).updateWidgets()
self.widgets['restaurant_code'].disabled = True
When I go to the edit form, I get an error:
ConstraintNotSatisfied: True
Why is this error occurring and how can I fix this?
Also, the version of Plone I am using is Plone 4.3.5.
Edit: When I tried printing the type of object that self.widgets['restaurant_code'].disabled was, it said it was a NoneType object.
You might have better luck using the mode property.
Try something like this:
from z3c.form.interfaces import HIDDEN_MODE
def updateWidgets(self):
super(Edit, self).updateWidgets()
self.widgets['restaurant_code'].mode = HIDDEN_MODE

Using dexterity behaviors to provide a method

I've been using a schema behavior with no problem, but I want to also have a method that provides some logic. Right now I have
class IMyFoo(form.Schema):
requester = schema.TextLine(title=_(u"Requestor"),
required=False,
)
def foo(self):
""" foo """
alsoProvides(IMyFoo, IFormFieldProvider)
And in the zcml
<plone:behavior
title="My behavior"
description="Some desc"
provides=".behaviors.IMyFoo"
for=".interfaces.ISomeInterface"
/>
I included IMyFoo in the behaviors section of a content type in portal_types. This gives me the schema but not that foo() method. So I tried to add a factory for it from reading http://plone-training.readthedocs.org/en/latest/behaviors2.html with the following code
class MyFoo(object):
def foo(self):
return 'bar'
And in the zcml
<plone:behavior
title="My behavior"
description="Some desc"
provides=".behaviors.IMyFoo"
factory=".behaviors.MyFoo"
for=".interfaces.ISomeInterface"
/>
But this didn't seem to make a difference, or at least, I don't know how to access that method. The closest I've been able to come is the following:
class IMyFoo(Interface):
""" Marker """
class MyFoo(object):
def __init__(self, context):
self.context = context
def foo(self):
return 'bar'
<adapter for=".interfaces.ISomeInterface"
factory=".behaviors.MyFoo"
provides=".behaviors.IMyFoo" />
I put IMyFoo in the behaviors attribute in the fti, and then call it by walking through all behaviors with something like
behavior = resolveDottedName(context.portal_types.getTypeInfo(context.portal_type).behaviors[-1]))
behavior(self).myfoo()
Surely going through the FTI like that is not the proper way to do it. But I'm at a loss at this point. In Archetypes I would just make a mixin class and inherit it with any content type I wanted to use it. I could do the same here, but my understanding is that behaviors are supposed to be a replacement for them, so I'd like to figure out how to use this preferred method.
As you've discovered, the schema class really is just an interface. It can't provide any methods. To provide more functionality, you need to connect your behavior interface to a factory class that adapts a dexterity object to provide your interface.
So, if your behaviors.py looks like this:
# your imports plus:
from plone.dexterity.interfaces import IDexterityContent
from zope.component import adapts
from zope.interface import implements
class IMyFoo(form.Schema):
requester = schema.TextLine(
title=_(u"Requestor"),
required=False,
)
def foo(self):
""" foo """
alsoProvides(IMyFoo, IFormFieldProvider)
class MyFoo(object):
implements(IMyFoo)
adapts(IDexterityContent)
def __init__(self, context):
self.context = context
def foo(self):
return 'bar'
Then your one-and-only zcml declaration would be:
<plone:behavior
title="My behavior name"
description="Behavior description"
provides=".behavior.IMyFoo"
factory=".behavior.MyFoo"
for="plone.dexterity.interfaces.IDexterityContent"
/>
And, you would reach your method with code like:
IMyFoo(myFooishObject).foo()
Note the use of IDexterityContent. You're creating a behavior that could be applied to any Dexterity content. So, the behavior adapter should be for that very general interface.

Is there a way to extend Plone Dexterity's INameFromTitle behavior?

The project I am working on uses Plone's awesome Dexterity plugin. A couple of my custom content types have very specific names that must be computed. The way I had originally accomplished this before was by adding plone.app.content.interfaces.INameFromTitle as a behavior in the object's generic setup entry, per the manual's directions:
<?xml version="1.0"?>
<object name="avrc.aeh.cycle" meta_type="Dexterity FTI">
...
<property name="schema">myproject.mytype.IMyType</property>
<property name="klass">plone.dexterity.content.Item</property>
...
<property name="behaviors">
<element value="plone.app.content.interfaces.INameFromTitle" />
</property>
...
</object>
Then I created an adapter that would provide INameFromTitle:
from five import grok
from zope.interface import Interface
import zope.schema
from plone.app.content.interfaces import INameFromTitle
class IMyType(Interface):
foo = zope.schema.TextLine(
title=u'Foo'
)
class NameForMyType(grok.Adapter):
grok.context(IMyType)
grok.provides(INameFromTitle)
#property
def title(self):
return u'Custom Title %s' % self.context.foo
This method is very similar to that suggested in this blog post:
http://davidjb.com/blog/2010/04/plone-and-dexterity-working-with-computed-fields
Unfortunately, this method stopped working after plone.app.dexterity beta and now my content items don't have their names assigned properly.
Would anyone happen to know how to extend Dexterity's INameFromTitle behavior for very specific naming use-cases?
Your help is much appreciated, thanks!
You could try the following.
in interfaces.py
from plone.app.content.interfaces import INameFromTitle
class INameForMyType(INameFromTitle):
def title():
"""Return a custom title"""
in behaviors.py
from myproject.mytype.interfaces import INameForMyType
class NameForMyType(object):
implements(INameForMyType)
def __init__(self, context):
self.context = context
#property
def title(self):
return u"Custom Title %s" % self.context.foo
I generally prefer defining my adapters using ZCML; in configure.zcml
<adapter for="myproject.mytype.IMyType"
factory=".behaviors.NameForMyType"
provides=".behaviors.INameForMyType"
/>
but you could probably also use a grok.global_adapter.
I did it with a behavior, by adapting to INameFromTitle
in behaviors.py
class INameFromBrandAndModel(Interface):
""" Interface to adapt to INameFromTitle """
class NameFromBrandAndModel(object):
""" Adapter to INameFromTitle """
implements(INameFromTitle)
adapts(INameFromBrandAndModel)
def __init__(self, context):
pass
def __new__(cls, context):
brand = context.brand
model = context.modeltype
title = u'%s %s' % (brand,model)
inst = super(NameFromBrandAndModel, cls).__new__(cls)
inst.title = title
context.setTitle(title)
return inst
in behaviors.zcml or configure.zcml
<plone:behavior
title="Name from brand and model"
description="generates a name from brand and model attributes"
for="plone.dexterity.interfaces.IDexterityContent"
provides=".behavios.INameFromBrandAndModel"
/>
<adapter factory=".behaviors.NameFromBrandAndModel" />
Then disable INameFromTitle behavior in profiles/types/your.contenttype.xml.
Voila. This integrates very well and shows a proper title in the default view and navigation. Removing context.setTitle(title) from the adapter would just leave us with a proper id, but no title set.
This does not change the title autocratically after editing. I had, so far, no success with overriding the klass property of my content types, as often suggested.
If you define the title attribute in your schema, like:
class IBike(form.Schema):
"""A bike
"""
title = schema.TextLine(
title = _(u'Title'),
required = False,
)
you can easily change the title later. Hiding the title field in the addForm should be done, to avoid misunderstandings.

How do i read embedded bytarray file?

I created a tile map editor for my game and it will generate a file when the user is done with the design. The file will store the assets used and other information.
this is the code on how i generate the file
var ba:ByteArray = new ByteArray();
var masterData:Object = { map:Data.instance.mapLayerArr,
asset:assetCollection,
gridrow:Data.instance.gridRow,
gridColumn: Data.instance.gridColumn,
cellWidth: Data.instance.cellWidth,
cellHeight: Data.instance.cellHeight,
assetCount: Data.instance.assetCount,
layerCount: Data.instance.layerCount,
version: Data.instance.version};
ba.writeObject(masterData);
ba.compress();
file = new FileReference();
file.save(ba, Data.instance.fileName);
problem starts when i want to embed the generated file inside my game.
this is the code in my program.
[Embed(source='../../../../res/tilemapdata/File Name', mimeType='application/octet-stream')]
public static const TileMapFile:Class;
public function TileMapLoader()
{
var byteArray:ByteArray;
byteArray = new TileMapFile();
byteArray.uncompress();
var obj:Object;
obj = byteArray.readObject();
trace(fileReference);
}
whenever i run it ends in "obj = byteArray.readObject();" and will display this error.
[Fault] exception, information=ArgumentError: Error #2173: Unable to read object in stream. The class flex.messaging.io.ArrayCollection does not implement flash.utils.IExternalizable but is aliased to an externalizable class.
You are using a strange class flex.messaging.io.ArrayCollection - try replacing all such imports with mx.collections.ArrayCollection.
Also make sure that all classes that are stored in file has [RemoteClass] metatag or they would be restored as Object instances.
A good read about the situation (adobe's official documentation): (Explicitly mapping ActionScript and Java objects)
I have experianced the same problem. General rules which help me to solve:
better to have explicitly declared metatag [RemoteClass] on your client-side actionscript classes.
collections of server-side classes (lists,arrays,etc.) easier to handle when represented client-side flash by mx.collections.ArrayCollection.
at some point you may need to explicitly declare client-side Flash class with the server-side class relationship by coding before any deserialization occures flash.net.registerClassAlias("net.acme.serverside.Foo", clientside.Foo ); otherwise your objects goes untyped as generic flash.Object after deserialization.
Check, that your ArrayCollection alias registered by this way:
import mx.collections.ArrayCollection;
...
registerClassAlias("flex.messaging.io.ArrayCollection", ArrayCollection);
instead of:
import mx.collections.ArrayCollection;
...
registerClassAlias("mx.collections.ArrayCollection", ArrayCollection);
There explanation:
http://livedocs.adobe.com/blazeds/1/javadoc/flex/messaging/io/ArrayCollection.html

Resources