__clrtype__ Metaclasses: Simple Custom Attributes

I know it’s been a while since my last __clrtype__ post, but I was blocked on some bug fixes that shipped as part of IronPython 2.6 Beta 1. So now let’s start looking at one of the most requested IronPython features – custom attributes!

Over the course of the next three blog posts, I’m going to build out a mechanism for specifying custom attributes on the CLR type we’re generating via __clrtype__. All the various Builder classes in System.Reflection.Emit support a SetCustomAttribute method that works basically the same way. There are two overloads – the one I’m going to use takes a single CustomAttributeBuilder as a parameter.

For this first post, I’m going to focus on the basic custom attribute infrastructure, so we’re going to use the extremely simple ObsoleteAttribute. While you can pass some arguments to the constructor, for this first post I’m going to use the parameterless constructor. To keep things less confusing, I’m going back to the original version of the Product class, before I introduced CLR fields and properties. The one change I’m making is that I’m adding a list of attributes I want to add to the class.

from System import ObsoleteAttribute

class Product(object):
  __metaclass__ = ClrTypeMetaclass
  _clrnamespace = "DevHawk.IronPython.ClrTypeSeries"
  _clrclassattribs = [ObsoleteAttribute]

  # remainder of class omitted for clarity

Python list comprehensions use the same square bracket syntax as C# properties, so it kinda looks right to someone with a C# eye – though having the attribute specifications inside the class, rather than above it, is totally different. I wish I could use Python’s class decorators for custom class attributes, but class decorators run after metaclasses so unfortunately that doesn’t work. Also, I can’t leave off the “Attribute” suffix like you can in C#. If I really wanted to, I could provide a new type name in the import statement (“from System import ObsoleteAttribute as Obsolete”) but I thought spelling it out was clearer for this post.

Now that I have specified the class attributes, I can update the metaclass __clrtype__ method to set the attribute on the generated CLR class:

if hasattr(cls, '_clrclassattribs'):
      for attribtype in cls._clrclassattribs:
        ci = clr.GetClrType(attribtype).GetConstructor(())
        cab = CustomAttributeBuilder(ci, ())
        typebld.SetCustomAttribute(cab)

I’m simply iterating over the list of _clrclassattribs (if it exists), getting the default parameterless constructor for each attribute type, creating a CustomAttributeBuilder instance from that constructor and then calling SetCustomAttribute. Of course, this is very simple because we’re not supporting any custom arguments or setting of named properties. We’ll get to that in the next post. In the mean time, you can get the full code for this post from my SkyDrive.

There is one significant issue with this custom attribute code. Attributes are typically marked with the AttributeUsage attribute that specifies a set of constraints, such as the kind of targets a given attribute can be attached to and if it can be specified multiple times. For example, the MTAThread attribute can’t be specified multiple times and it can only be attached to methods. However, those attribute constraints are validated by the compiler, not the runtime. I haven’t written any code yet to validate those constraints, so you can specify invalid combinations like multiple MTAThread attributes on a class. For now, I’m just going to leave it to the developer not to specify invalid attribute combinations. Custom attributes are passive anyway so I’m figure no one will come looking for a MTAThread attribute on a class or other such scenarios.

However, I’m interested in your opinion: When we get to actually productizing a higher-level API for __clrtype__, what kinds of attribute validation should we do, if any?

Strengthening the Microsoft Ecosystem with Source Code

clip_image001

Today was the Presentation Idol competition I blogged about a couple of weeks ago. Unfortunately, I didn’t win – but believe me when I say I was up against some serious competition. I think I was about in the middle of the pack – better than some but clearly not as good as others.

Since I made a big deal about asking for people ideas on how to present my topic of choice – external contributions to Microsoft Open Source projects – I decided I’d post my deck and my script. Yes, I said script. Usually, I don’t script what I’m going to say word for word like this. But with only three and a half minutes to present, I thought I’d be as precise as possible. You’ll notice some lines near the end are in italics – those are ones I planned on cutting if I was in danger of going over the time limit.

Feedback, as usual, is most welcome.


Slide1

Hello, my name is Harry Pierson. I’m a program manager in the Visual Studio Languages group and I’m here to talk about what I would most like to do to improve Microsoft.

At Microsoft, we care an awful lot about the software ecosystem. Searching for the word “ecosystem” on Microsoft.com returns nearly eight thousand results. We talk about the ecosystem in our marketing and in our press releases.

Slide2

In 2007, we commissioned a study of the global economic impact of the Microsoft ecosystem. In a word, it’s massive. It’s responsible for nearly 15 million jobs and drives over half a trillion dollars a year in tax revenue worldwide.

No wonder we care about the ecosystem so much.

Slide3

But clearly, we’re not the only ones who care. Microsoft represents a fairly small percentage of the overall ecosystem. We earn just over 11% of the total revenue and account for half of one percent of the total employment within the ecosystem.

That means there are an awfully large number of people with a vested interest in the continuing success of the Microsoft platform.

Slide4

With this vast ecosystem in mind, I want to talk about Open Source. Microsoft and Open Source are often portrayed as enemies. But in DevDiv, we have several high profile Open Source projects. I work on IronPython, which has been Open Source for over four years. More recently, the ASP.NET and Extensibility Framework teams have decided to release some projects as Open Source.

I believe we should have more Open Source projects at Microsoft. But more importantly, I feel that we need to go beyond the textbook definition of Open Source. Our Open Source projects are typically closed to external contributions. But for the ecosystem at large, Open Source isn’t just about the availability and distribution terms of the source code. It also implies a collaborative development model - parties working together across organizational boundaries, contributing directly to projects in question.

The thing I would most like to change about Microsoft would be to let members of our ecosystem contribute code to our Open Source projects.

Slide5

I can tell you from personal experience, there are members of the IronPython community who would leap at the opportunity to contribute code. And their engineering prowess and real world would benefit the IronPython project tremendously. But the legal process for getting permission to take contributions is onerous. Worse, the legal stigma attached to code that isn’t 100% pure Microsoft intellectual property makes it nearly impossible for any other group inside Microsoft to build on it.

I realize the onerous legal process is there for a reason: to protect Microsoft’s interests. But improving IronPython and Open Source projects like it isn’t just in Microsoft’s best interest; it’s in the best interest of our ecosystem as well. We need a legal framework that protects Microsoft while allowing for code contributions. Developing such a framework will be a challenge. But competitors like Sun, Google and IBM have already demonstrated that it’s not insurmountable.

Slide6

Half a trillion dollars annually. 15 Million jobs. 42% of the IT workforce. The Microsoft ecosystem is the envy of the industry. And Microsoft is in a unique position to harness the collective experience and engineering prowess of that ecosystem while simultaneously dispelling the myth that we are an enemy of Open Source.

It’s time we make this change.

Thank you very much.

A Somewhat Scary Birthday

Yesterday was my 39th birthday. Among other things I got a vasovagal syncope (aka I fainted), a trip to the hospital and an MRI.

Yeah, I’ve had better birthdays. But I’m feeling much better now.

Since Monday, I’ve been having weird numbness and tingling in my hands, feet and midsection. Ever have your foot fall asleep? You know how it feels when your foot wakes up again? It’s kinda like that. After three days of that, I decided it was time to go see the doctor. My doctor is right by my daughter’s school, so I try and schedule my appointments so I can drop her off and save my wife the trip. But the only appointment they had yesterday was thirty minutes before my daughter’s school starts, so I ended up going alone. That turned out to be a very good thing.

Diabetes is one of the things that can cause this numbness and tingling, so my wife and I figured that I shouldn’t eat anything in case the doctor wanted to check my blood sugar. Sure enough, they wanted to run a few blood tests. My wife called as they were drawing my blood – she had dropped off our daughter and wanted to know if I wanted her to stop by.  I told her to stop by if she wanted, hung up, and promptly fainted. Luckily, Jules had decided she wanted to stop by so she was there when I came to.

Apparently, vasovagal syncope is the most common cause of fainting and having your blood drawn is a common trigger. I’ve never had that reaction to having my blood drawn, though I can’t remember ever having my blood drawn while fasting. But I tell you what, I don’t ever want to go thru that again. All I really remember was trying to get my brain to focus, and it wouldn’t. Pretty scary.

Playing it better safe than sorry, I was sent off to the hospital to spend two hours crammed in the MRI machine to get an scan of my brain and spine done. Also not a pleasant experience, but much better than fainting. There was much more ominous talk like “admitting for observation” and “lumbar puncture”, but apparently the MRI didn’t show anything requiring all that so I was sent home.

I still have the numbness and tingling, though it’s somewhat better today than yesterday. The good news is that it’s not diabetes or my thyroid or anything like that and they don’t think the fainting was related at all. Since the tingling and numbness is a little better today, I’m thinking it’s something like a pinched nerve. My doctor wants me to go see a specialist, so I’ve got an appointment with a neurologist in a couple of weeks. We’ll see how it feels by then – in the meantime, I’m taking it easy. I even skipped work again today – five day weekend FTW!

As for my birthday, we did decide to postpone my “FANTASTIC surprise”. Jules had arranged for us to go camping on Orcas island over the weekend. I’m really excited for the trip – it’ll be our first real camping trip outside of the back yard – but I’m not sure if I’ll be up for it this weekend. My parents sent me a bunch of Capitals gear as well as some money for new hockey equipment – I really need a new helmet and elbow pads. My kids both made me awesome cards – Patrick’s new thing is to make pop-up cards. He also made me a paper “cake” crown.

So even though that whole tingling/vasovagal/hospital/MRI thing was a less than fun way to spend the day, I still ended up having a pretty decent birthday. I’m especially thankful for my awesome wife, who does an amazing job taking care of me when I’m sick – much better than I am able to do for her when she’s sick I’m afraid.

IronPython 2.6 Beta 1

In addition to the IronPython CTP for .NET Framework 4.0 Beta 1 I blogged about earlier, we also released the first beta of IronPython 2.6 today. How about that – two IronPython releases in one day! This is our second preview release as we work towards our 2.6 RTM in September. 2.6 Alpha 1 was released back in March.

There are two big new features in this release. The first is our implementation of the ctypes module. The ctypes module is like P/Invoke for Python. It allows Python code to call into unmanaged DLL functions. Here, for example, I’m calling into the standard wprintf function from msvcrt.dll

IronPython 2.6 Beta 1 (2.6.0.10) on .NET 2.0.50727.4918
>>> import ctypes
>>> libc = ctypes.cdll.msvcrt
>>> ret = libc.wprintf("%sn", "hello")
hello

Between ctypes and Ironclad, I think we’ll eventually be able to load most native Python extensions in IronPython. Woot!

The other big new feature in this release is a real implementation of sys._getframe. _getframe lets you write code that inspects the Python callstack. Previously, we supported _getframe only with a depth of zero which is to say you could inspect the current frame, but no others. Now, by default we don’t implement _getframe at all unless you pass in –X:Frames or –X:FullFrames on the command line. Removing the version of _getframe that only worked for depth zero fixes an issue with collections.py that broke much of the 2.6 standard library in IronPython 2.6 Alpha 1.

The difference between Frames and FullFrames is in what is returned by frame.f_locals member. If you’re running with FullFrames, we hoist all local variables into the heap so they can be accessed by our frame walker. If you’re running with Frames, our ability to access locals up the stack is limited. Sometimes they are available – If you called locals() in a frame up the stack for example, then f_locals will be available – but usually not. There’s a performance difference between the default (i.e. no Frames), –X:Frames and –X:FullFrames, hence why we provide the user fine grained control over the Frame support.

Our performance has gotten better relative to 2.6 Alpha 1. Our PyStone numbers have improved 80% from Alpha 1, similar to where we were in IronPython 2.0.1. We’ve also been able to cut our startup time about 25% from 2.0.1. We’re still an order of magnitude slower than CPython on startup, but we’re getting better. We’re significantly worse on PyBench than we were in 2.6 Alpha 1, but that’s primarily because there’s now a second exception test. As I described back in March, we get killed on the exceptions benchmarks – the two combine to consume nearly 62% of our total run time. Ouch!

Finally, there are bug fixes. Of particular relevance to readers of this blog are a series of fixes that allow me to continue on with my __clrtype__ series. Watch for that soon.

As I said back when we released Alpha 1, the release cycle on 2.6 will be much shorter than it was for 2.0. 2.0 had eight alphas, five betas and two release candidates over the course of around twenty months. We expect 2.6 to have one alpha, two betas and a release candidate over eight months. So please start trying using the beta as soon as you can so you can give us your feedback and we can fix your bugs!

IronPython 2.6 CTP for .NET 4.0 Beta 1

The .NET Framework 4.0 and Visual Studio 2010 Beta 1 is now generally available for download. Jason Zander has a very thorough rundown on some of the new features in this release. Of course, my favorite new features in VS2010 is the new dynamic language support in C# and Visual Basic, which let’s you easily call out to IronPython code from those languages.

For anyone who wants to experiment with interoperating C# or VB with IronPython, we released IronPython 2.6 CTP for .NET 4.0 Beta 1 today. There’s also a walkthru showing how you can use the standard Python library module random from both C# and VB. Note, there’s currently a URL bug in that walkthru – it links to IronPython 2.6 Alpha 1 rather than the .NET 4.0 Beta 1 IronPython CTP. Make sure you pick up the right version of IronPython if you want to try out the walkthru. Looks like they fixed the redirect in the walkthru.

FYI, this is a CTP quality release with about the same functionality as IronPython 2.6 Alpha 1.  Essentially, this is the version of IronPython that was in the source tree when the VS team branched for Beta 1.

If you’ve got any feedback, please drop us a line on the mailing list.