Forgot your password?
typodupeerror
Programming

Python Converted To JavaScript, Executed In-Browser 176

Posted by Soulskill
from the hey-why-not dept.
lkcl writes "Two independent projects, Skulpt and Pyjamas, are working to bring Python to the web browser (and the JavaScript command-line) the hard way: as JavaScript. Skulpt already has a cool Python prompt demo on its homepage; Pyjamas has a gwtcanvas demo port and a GChart 2.6 demo port. Using the 64-bit version of Google v8 and PyV8, Pyjamas has just recently and successfully run its Python regression tests, converted to JavaScript, at the command-line. (Note: don't try any of the above SVG demos with FF2 or IE6; they will suck.)"
This discussion has been archived. No new comments can be posted.

Python Converted To JavaScript, Executed In-Browser

Comments Filter:
  • GWT for Python? (Score:3, Interesting)

    by mcvos (645701) on Saturday September 19, 2009 @10:43AM (#29476331)

    It's not entirely clear to me what Skulpt is exactly, but Pyjamas is apparently GWT ported to Python, which sounds like a really cool idea. Now if somebody did the same thing with Ruby and Scala, I'd be really happy.

    Javascript is just way too stupid to program manually, but currently we're in the odd situation where we're writing server stuff in Ruby, and browser stuff in Java. That's just wrong.

    • Re:GWT for Python? (Score:4, Informative)

      by lkcl (517947) <lkcl@lkcl.net> on Saturday September 19, 2009 @11:00AM (#29476427) Homepage

      you're looking for RubyJS [rubyforge.org]. sadly, funding has not been forthcoming in order to carry RubyJS forward. the compiler is excellent; the insights into the technical issues behind dynamic language translation were very useful (even to python translator developers) - but martin ran out of time/money/enthusiasm due to the lack of interest shown, so he only got as far as creating HTML and Button for RWT (Ruby Web Toolkit).

    • Re: (Score:3, Interesting)

      by loufoque (1400831)

      Javascript is just way too stupid to program manually

      Not more than Ruby or Python.
      Don't confuse languages with libraries.

      • Re: (Score:2, Insightful)

        by Xtravar (725372)

        Eh, a language is only as good as its standard library. I don't like telling people to download/build/install a number of other libraries of specific versions just to run/build my stupid application.

        It's just a fact of life. For personal applications (where it's hard enough to get people to use your app anyway) and work applications (where licensing causes multiple headaches on this front).

        And no, I don't use Ruby, Python, or Javascript so I can't comment on any of their libraries.

        • by loufoque (1400831)

          Eh, a language is only as good as its standard library.

          So C and C++, ones of the most used languages in the world, are worse than fuck since their standard library is ridiculously small?

          It's not like all the best and more important software is written in those languages... (virtually all operating systems and major applications)

  • In most ways (no explicit integer type being an exception) Javascript is a remarkable and beautiful language [crockford.com]. It has libraries available on a server near you through Dojo, among others. Javascript is one of the best things about browsers.

    What browsers need is a workable CSS and DOM interface (although the DOM interface has improved in recent years). But these are not issues with Javascript per se. Cleaning up the browser programming environment is not about getting rid of Javascript.

    From TFA: """
    anyway

    • by s4m7 (519684) on Saturday September 19, 2009 @11:23AM (#29476521) Homepage

      Cleaning up the browser programming environment is not about getting rid of Javascript.

      Maybe not, but javascript is not a good language, it's a bad language with some good features. The awful scoping mechanism is evidence of this enough. The intrinsic objects are too limited to be useful, so much so that now there are more than 4 different common framework projects to handle all the inconsistency in implementation and they're all incompatible with each other. anonymous functions are great but they make debugging a giant pain the arse.

      i would like to see a viable alternative language to javascript, just for variety's sake. It's just had layers of crap pasted on top of it since 1995 or whatever and it'd be nice to see a new approach that fits what people actually use it for these days.

      • by ggpauly (263626) on Saturday September 19, 2009 @12:32PM (#29476947) Homepage

        The link to Douglas Crockford's site in the parent was to an article entitled "The World's Most Misunderstood Programming Language".

        The awful scoping mechanism

        From the brief survey of Javascript [crockford.com] on Crockford's site:
        """
        When used inside of a function, var defines variables with function-scope. The vars are not accessible from outside of the function. There is no other granularity of scope in JavaScript. In particular, there is no block-scope.
        """
        iow, use the var keyword. Programmers who do not know this ONE RULE (TM) are bitten by mysterious insects. Use a lint program if needed.

        Functions are objects in Javascript, so this effectively allows, in either functional or object styles of programming, programmers to freely and simply define their variable scoping.

        Procedural programmers used to simple block scoping (Hi COBOL fans!) may need to find a mechanism to cope with this. But I'd suggest using OO techniques if your program is complex enough that this is a problem. Javascript allows simple, non-demanding OO. If you like your OO authoritarian then Google has a Java-to-javascript translator.

        intrinsic objects are too limited to be useful, so much so that now there are more than 4 different common framework projects

        Python has one official library (and many 'unofficial' modules too), without which Python would be very limited. Javascript has many unofficial libraries. Welcome to the free world.

        btw, I use Python, and I get Twisted Python at least to some extent. Twisted's deferred abstraction is mimicked in Dojo Javascript. I use Python on the server and Javascript + Dojo on the browser. Python has less warts and more modules. Javascript has astounding power in simplicity, as in the scoping rule.

        • On the surface, JS is a really nice language, but it really has a fair share of warts which will bite you. And yes, I'm aware that Javascript is neither DOM nor CSS. For those interested, Bob Ippolito (the author of MochiKit) wrote the best "Javascript sucks" [pythonmac.org] article I've ever read.
        • by s4m7 (519684)

          yes I know about the var keyword and use it quite religiously. However let me give a specific example of how crappy the JS scope rules are.

          I can globally scope a variable in JS, let's call it foo. If I am a sloppy programmer and write a function accessing a variable named foo without var'ing it within that function, it will access the global var unless foo is an argument for my function.

          oh crap but it's worse because my functions are objects. So i can have a function foo() and a variable foo as prope

          • by Abcd1234 (188840)

            I can globally scope a variable in JS, let's call it foo. If I am a sloppy programmer and write a function accessing a variable named foo without var'ing it within that function, it will access the global var unless foo is an argument for my function.

            Uhh... wtf... that's exactly the way virtually every other language works, as well, include good ol' fashioned C (Perl is another excellent example). I fail to see how this is even remotely surprising.

            So i can have a function foo() and a variable foo as prope

        • iow, use the var keyword. Programmers who do not know this ONE RULE (TM) are bitten by mysterious insects. Use a lint program if needed.

          Functions are objects in Javascript, so this effectively allows, in either functional or object styles of programming, programmers to freely and simply define their variable scoping.

          Procedural programmers used to simple block scoping (Hi COBOL fans!) may need to find a mechanism to cope with this. But I'd suggest using OO techniques if your program is complex enough that this is a problem. Javascript allows simple, non-demanding OO. If you like your OO authoritarian then Google has a Java-to-javascript translator.

          Sorry, but that's just bullshit. Scoping of local variables has nothing to do with OO or lack thereof; in fact, virtually all other OO languages which have explicit variable declarations do block scoping, while COBOL never had it. Nor does this have anything to do with functions as first-class objects.

          In fact, I know of one single language that had the same awful local scope rules as JavaScript - it's VB6.

      • Re: (Score:2, Insightful)

        by BitZtream (692029)

        i would like to see a viable alternative language to javascript, just for variety's sake. It's just had layers of crap pasted on top of it since 1995 or whatever and it'd be nice to see a new approach that fits what people actually use it for these days.

        Why? So in 2025 you can sit around talking about the new language thats fills its roll perfectly but isn't to your liking and wasn't the perfect vision you thought it would be 15 years ago? Javascript has barely changed in the last 15 years. The environmen

        • Re: (Score:3, Insightful)

          by s4m7 (519684)

          wow, cs rage much?

          I am perfectly capable of programming in JS. I've written a number of extremely useful classes in the language and I don't care for your tone.

          if you think your language is better than all the rest, or some other language should go away, then you are a shitty programmer.

          well, hello mr. strawman. I never declared that I wish javascript would go away, and I don't suggest any "better" language should take its place... I merely asked for an alternative that reflects how it is used in a modern sense more accurately.

          Why? [...]Javascript has barely changed in the last 15 years.

          Thank you for answering your own question. js wasn't a good language in the first place and 15 years of

        • Here is reality for you developers of the world, if you think your language is better than all the rest, or some other language should go away, then you are a shitty programmer. The language does not make the programmer, the programmer does. If you find a language/environment difficult to use, you are the shitty part of the equation. Languages are just that, languages. They describe things. You are the one that has to figure out how to describe what you want, if you can't do that, the language or environment isn't the problem, you are.

          Riiight. That's politically-correct bullshit. Languages can very easily make things easy or difficult. Languages can be shitty. Environments can be shitty. If you don't believe me, I can come up with a shitty language and environgment just for you. It'll take a couple of days, but I can guarantee it'll be really shitty. Sure, programmers can be shitty too (and that's often the case), but that doesn't mean there aren't differences in quality between languages and environment.

        • Re: (Score:3, Interesting)

          Here is reality for you developers of the world, if you think your language is better than all the rest, or some other language should go away, then you are a shitty programmer.

          I don't know of any "silver bullet" languages, though I definitely have favorites - and I do not wish all others to go away.

          What I do wish, however, is for badly designed languages which don't have any redeeming qualities to go away. And, yes, JS is on that list. Though, admittedly, way below PHP.

          On a side note, an example of a badly designed language with a redeeming quality is Common Lisp - it's ugly as hell, but nothing else matches it in terms of sheer power.

      • by Blakey Rat (99501)

        The intrinsic objects are too limited to be useful, so much so that now there are more than 4 different common framework projects to handle all the inconsistency in implementation and they're all incompatible with each other.

        Whoa, slow down. Blame where blame is due. That point is DOM's fault, but Javascript's. (Well, ok, DOM's not to blame for the frameworks being incompatible with each other, but the shittiness of DOM is why they exist at all.)

        If you implemented Python or Ruby in a browser, it would have

      • Javascript used to have a really nice scoping mechanism, called eval(); It was blazing fast too, in every browser. The basic idea was when you create an object, you tell it its name.

        var myPlayer = new Player('myPlayer');

        Then it uses eval to generate methods that point to itself. This was necessary because all callbacks are global in Javascript. Unfortunately, FF3 disabled this fine use of eval, so now, you have to do weird scoping shit that slows it down.

        I like how lax Javascript is. A variable can be both

      • by Junta (36770)

        The scoping mechanism I agree is awful, but it's also one reason I am also frustrated by python for sophisticated applications. I have not found a way to acheive more granularity than Javascript in Python apps (i.e. arbitrary block scope). One may fairly argue that they feel those circumstances should be broken up into functions if it seems required to have a block-scoped variable, but sometimes it just works better to know before a function ends that you will get errors if you accidentally use that varia

    • Re: (Score:3, Interesting)

      by lkcl (517947)

      What browsers need is a workable CSS and DOM interface (although the DOM interface has improved in recent years).

      yes - it's these DOM interfaces that i used for the pure-python port of pyjamas. the first one (webkit) i literally had to create, myself (it took 8 weeks). the second one, xulrunner, used a component created by the OLPC team, called hulahop; the third one, for windows only, uses python COM (the comtypes library) and python ctypes.

      But these are not issues with Javascript per se. Cleaning up the browser programming environment is not about getting rid of Javascript.

      From TFA: """
      anyway, just thought there might be people who would be intrigued (or
      horrified enough to care what's being done in the name of computer
      science) by either of these projects.
      """

      Not horrified, but I wonder if W3C politics is creating unforeseen consequences.

      it has to be said that the attitude of the webkit developers (one in particular who can be easily identified) has been incredibly bad, towards the free software glib/gobject bin [github.org]

    • ...is to be buried deep down under ground and never see the face of the Earth again.

      What I mean is that we don't need browsers, we need a code/data distribution system that lazily downloads application components/data.

    • by Unoti (731964)

      What browsers need is a workable CSS and DOM interface (although the DOM interface has improved in recent years).

      Jquery [jquery.com] makes working with the DOM incredibly easy. It completely changed and radically simplified nearly all of the Javascript that I write. If you haven't explored it, you should.

  • A practical use (Score:4, Interesting)

    by slthytove (771782) <james.m.allen@gm a i l . c om> on Saturday September 19, 2009 @11:19AM (#29476503) Homepage

    As a high school computer science teacher, I can see a practical application of this. Currently, I think Python is one of the best languages to learn basic programming concepts with, in that it is relatively straightforward, powerful, and there's not much "voodoo" to prevent students from diving right into programming. It's possible to do some really cool things in Python with not much code.

    However, one of the problems is that it can be difficult to give students a way to show off their code. Since it's an interpreted language, they can't just give an .exe or a .app file to someone else to show it off - they need to say, "Oh, go and install Python, and these libraries, etc." Yes, there are solutions such as py2exe and py2app, but getting these set up can be quite a task in itself. By running Python inside JavaScript, you basically open up the whole web-connected world as a potential audience to these budding programmers. It's much easier to say, "Hey, check out this link!" than "Hey, download Python (but get the right version) and this graphics library, then download my .py file, and open up a command prompt and type python blahblah.py!"

    • by ceoyoyo (59147)

      Actually, if you use pyobjc or whatever the Windows python packager/comiler is these days (py2exe?) you can do just that. They'll make you a self contained .app or .exe that you can just give to someone.

      The web thing is pretty cool as well though.

    • Re: (Score:3, Insightful)

      by ggpauly (263626)

      Why not teach Javascript itself?

      It's a simple but powerful general-purpose object-oriented language. It's also a functional programming language with C-like syntax, closures, and lambdas.

      A browser is the interpreter.

          **** Please read http://javascript.crockford.com/javascript.html [crockford.com] before modding this down. ****

      • by BZ (40346)

        Javascript is not object-oriented in any of the traditional senses of the word. It provides features you can build an OO-like system on top of, but so does any language with closures and first-class functions...

        • by weston (16146)

          Javascript is not object-oriented in any of the traditional senses of the word.

          It's quite object-oriented, just not class oriented, and easy enough to use as if it's class-oriented if that's what you want, even without libraries. The prototype-based object system features add object orientation beyond what's offered via closures.

    • by Cato (8296)

      Perl has a nice way to generate .exe's from Perl scripts, involving:

      cpan -i PAR::Packer

      pp -o myprog.exe myprog.pl

      The end result is a .exe that can be run directly, no need to install (it unpacks itself then runs). Includes all CPAN libraries that you might use in the script.

      See http://search.cpan.org/dist/PAR-Packer/lib/pp.pm [cpan.org] - on Windows, install Strawberry Perl, and everything above will 'just work'.

  • by aoheno (645574) on Saturday September 19, 2009 @11:21AM (#29476509)
    Announcing onelanguage dot com, an extension of Google Translate, ushering in an era where programmers need only learn one language and have it converted to another language of choice.

    FAQ:

    Q. How accurate is it?
    A. Same as Google Translate. You have to learn the output language to know which parts of the language you already know result in garbage-out. We suggest you use our new Pidgin versions of Python, PHP, Java, and Ruby.
  • [script type="text/python"][/script]. Let one of the major browsers implement it, and see if the others follow... there's probably already DOM-access libraries in Python, yes?

    Seems to make a hell of a lot more sense than this translation stuff.

    • Re: (Score:3, Informative)

      by redhog (15207)

      That'd be damn hard. Python isn't made for sandboxing (google python and sandboxing, or restricted execution, and you'll see). If you did the script language=python implementation the "obvbious" way and just linked in the python interpreter into mozilla, you'd have a security hole big enough for a supertanker. There is Python support for extensions though - google PyXPCOM.

      • by Blakey Rat (99501)

        Well, that's a point. I still think this whole concept is a little daft, considering that web scripting has been designed to be language-independent from day one. I mean, IE has been the only browser to really embrace it, but still-- no reason other browsers can't.

    • by lkcl (517947)

      [script type="text/python"][/script]. Let one of the major browsers implement it, and see if the others follow... there's probably already DOM-access libraries in Python, yes?

      Seems to make a hell of a lot more sense than this translation stuff.

      there's two main ways in which this can be achieved:

      1) pyxpcomext

      2) appcelerator / titanium, with IronPython, via Silverlight/Moonlight.

      the problem is - one that both skulpt and pyjamas avoid - you need browser plugins, in each case, to achieve the goal. the pyxpcomext plugin is a whopping TEN MEGABYTES because it literally contains the entire python runtime.

      • by Blakey Rat (99501)

        I didn't realize Python was so large... 10 MB for the runtime? Ouch.

        Either way, my point is that if you want Python supported in the web world, do it the proper front-door method, rather than this goofy language translation stuff. (Obviously, it would need to be implemented a plug-in until all browsers supported it) I still agree with that sentiment, 10 MB or not.

  • Who can string together the largest number of platform layers [wikipedia.org] over each other, and still have it running.

    The first league will start in the 2 GB core memory and 2* 2 GHz (dual-core) CPU range with no other processor (like GPU) or storage (like HDD) usage.
    Every type of platform is only allowed once.

    Here is a list of platforms, to get you started:
    - Emacs
    - the CPU itself
    - Virtual machine (e.g. VirtualBox/VMware)
    - Browser(s)
    - C/C++
    - JavaScript
    - interpreted Piet [99-bottles-of-beer.net]
    - Python
    - LOLCode [99-bottles-of-beer.net]
    - Malbolge [99-bottles-of-beer.net]

    Bonus points for achiev

  • by Animats (122034) on Saturday September 19, 2009 @01:35PM (#29477363) Homepage

    Python is quite a good language, but the implementations suck. This is holding back widespread use of Python. It's too slow, typically 10x to 30x slower than C. That's far worse than Java.

    There have been several attempts at other implementations. But because Guido Rossum fights formal standardization of the language, treating his CPython implementation as a de-facto standard, everyone else has a moving target to hit.

    Google (who hired Guido) likes Python, but they don't like the low performance. CPython is a "naive interpreter" (very little optimization). Worse, with the rather lame implementation the Global Interpreter Lock, not only can't it use a multi-core CPU effectively, multi-thread programs run slower on multi-core CPUs. (The threads fight over the lock in an embarrassingly inefficient way.)

    Google is doing "Unladen Swallow", which is an attempt to bolt CPython to a just-in-time compiler to a virtual machine. It's not clear how well that will work out, but the end result will have more layers than seems to be indicated. The goal is 5x faster than CPython, which won't beat Java, let alone C/C++.

    It's cute that Python to JavaScript translation is possible, but it's not going to help much on the performance front.

    For a few years, the great hope of the Python community was PyPy, but that had too many goals, was being developed in "sprints", and after five years, the European Union pulled the plug on funding after it was slower than CPython.

    Shed Skin [blogspot.com], which is a Python to C++ hard-code compiler, is currently the lead in Python performance, but it doesn't yet implement the whole language. Still, with about two people working on it, Shed Skin is doing better than most of the bigger projects. Shed Skin does automatic type inference. Python doesn't have declarations, but with enough analysis, the compiler can figure out what types each variable can hold and generate hard types, which makes for much faster code.

    • by lkcl (517947)

      Google is doing "Unladen Swallow", which is an attempt to bolt CPython to a just-in-time compiler to a virtual machine.

      It's cute that Python to JavaScript translation is possible, but it's not going to help much on the performance front.

      thanks for posting this - it's interesting to see peoples' insights.

      i'm aware of the unladen/swallow effort: they're replacing the FORTH-based bytecode engine with LLVM JIT compilation.

      on their roadmap is "unboxing" of the http://python.org/ [python.org] c code types (Object/longobject.c, Object/intobject.c, Object/stringobject.c etc.)

      basically the plan is (i believe!) to provide reimplementations of intobject.c's __add__, __mul__ etc. to call LLVM routines instead of straight c code. in this way, they intend to keep p

    • by ceoyoyo (59147)

      "Google (who hired Guido) likes Python, but they don't like the low performance. CPython is a "naive interpreter" (very little optimization). Worse, with the rather lame implementation the Global Interpreter Lock, not only can't it use a multi-core CPU effectively, multi-thread programs run slower on multi-core CPUs. (The threads fight over the lock in an embarrassingly inefficient way.)"

      The semi-new multiprocessing module is pretty cool. For the most part it duplicates the thread api interface, but it use

    • Re: (Score:3, Informative)

      Don't use threads. Use multiprocessing for concurrency and Twisted for asynchronous I/O.

      If you're going to complain about the GIL, perhaps you should go read up on why it's necessary, and perhaps share some of your amazing insights on a better, more performant way to do threading.

      PyPy is far from dead. They've got a JIT working for x86 assembly that matches NumPy in some tests.

      • by dkf (304284)

        If you're going to complain about the GIL, perhaps you should go read up on why it's necessary, and perhaps share some of your amazing insights on a better, more performant way to do threading.

        Their big problem is that they're using a single space of resources that are shared across all threads. That in turn means that they have a lock guarding access to that resource space (the GIL) and so that's where there's massive contention, especially with CPU-bound threads. Drop the general sharing (sharing specific objects is OK if you add the right fine-grained locks) and the code will be much faster. This is very similar to using multiprocessing though, so much so that it makes scaling to a multiproces

        • by Animats (122034)

          The big issue is that this model is not compatible with most existing threaded Python code. The single resource-space assumption is pretty deeply embedded...

          It's not quite that bad. Python guarantees memory safety, and the atomicity of some sequence operations, like "append". But it's not a run-to-completion thread system. Fine-grained locks wouldn't break many pure Python applications.

          The big issue is "who owns what" for locking purposes. I discussed some ways to deal with that issue on the Use

          • by dkf (304284)

            The big issue is "who owns what" for locking purposes. I discussed some ways to deal with that issue on the Usenet Python group a few weeks ago. If you're willing to introduce "synchronized objects" (like Java) and require that all other mutable objects be linked to either by one thread or one synchronized object at a time, it can all be made to work without extensive programmer effort.
            Immutable objects don't have sharing problems, except for memory allocation purposes. (That's what concurrent garbage collection is for.)

            In Tcl (where I know what's going on in quite a lot of detail) each thread has a separate memory pool for small allocations (large allocs - I forget what qualifies as large - come from the global pool, but are also relatively rare) so that there is very little need for holding locks with high levels of contention. This is facilitated by the fact that Tcl uses an apartment threading model: threads are strongly isolated from one another except for explicitly shared resources (where yes, there's a per-resource

      • If you're going to complain about the GIL, perhaps you should go read up on why it's necessary, and perhaps share some of your amazing insights on a better, more performant way to do threading.

        Some insights might come from the fact that neither Jython nor IronPython have GIL (and yet fully support multithreading)...

        • Note how they're also both slower than CPython.

          Jython does it by using JVM for threading, IronPython uses one of the many GIL-less patchsets which degrade performance but still permit threading.

          • Note how they're also both slower than CPython.

            Reference?

            Jython does it by using JVM for threading, IronPython uses one of the many GIL-less patchsets which degrade performance but still permit threading.

            Actually, IronPython also does it by using CLR for threading; it's not based on CPython code, so I'm not sure what "GIL-less patchset" you're even talking about.

            Now can you please explain how Java or CLR threads are different from native threads, and why using the former does not require GIL, but using the latter does?

    • Python is quite a good language, but the implementations suck. This is holding back widespread use of Python. It's too slow, typically 10x to 30x slower than C. That's far worse than Java.

      Frankly, there's only so much you can do. The language semantics itself presents some obstacles to performance. I mean, the language reference explicitly defines member lookup as string lookup in a dictionary associated with an object! This is going to be an order of magnitude slower than vtable dispatch in a statically typed language, there's no way around it. At best you can try to mitigate this by using some caching scheme to avoid repeated lookups (Microsoft's DLR does precisely that), but this only hel

  • Are there any open source web browsers written in Python? If so, I would like to run it in these JavaScript python interpreters so I can browse the web.

    • by lkcl (517947)

      yes - paul bonser's pybrowser [paulbonser.com] is the beginnings of an implementation of a web browser in python. he uses python-cairo and pygame for the graphics and the event handling. a combination of flier liu's PyV8 [google.com] or python-spidermonkey would bring javascript execution to this effort, completing the loop.

      also i just accidentally encountered this [telepolis.com] which is confusingly also called pybrowser: it uses python-gtkhtml2 (which is considered deprecated since this project named pybrowser was written, in 2005).

  • by speedtux (1307149) on Saturday September 19, 2009 @03:38PM (#29478083)

    Compiling Python to JavaScript running in a browser really is like putting lipstick on a dog.

  • There are also a few implementations of Smalltalk using Javascript:

    http://gwt-smalltalk.appspot.com/ [appspot.com]

    http://clamato.net/ [clamato.net]

    http://tinlizzie.org/ometa/ometa-js-old/ [tinlizzie.org]

"It is better to have tried and failed than to have failed to try, but the result's the same." - Mike Dennison

Working...