Planet Plone

This is where developers and integrators write about Plone, and is your best source for news and developments from the community.

December 01, 2016

Makina Corpus: The world's simplest Python template engine

2016-12-01T00:00:00Z

A template engine is a component able to render some data using a given string template.

We use it extensively in web development (that's not surprising because web development is mainly about reading some data and render them as strings, that's what I say when someone ask me about my job).

So there are already a lot of Python based template engines (Jinja2, Mako, Chameleon, ...).

The purpose of this article is to build a very basic template engine based only on the Python standard string class formatting capacities.

You probably know...

You probably know .format() replaces the old "%" based formatting solution:

>>> "My name is %s and I am %d" % ("Eric", 41)
'My name is Eric and I am 41'
>>> "My name is {name} and I am {age}".format(name="Eric", age=41)
'My name is Eric and I am 41'

It allows to perform all the typical formatting features, for instance:

>>> '{:^20}'.format('centered')
' centered '
>>> '{:^20}'.format('align right')
' align right '
>>> '{:>20}'.format('align right')
' align right'
>>> '{:<20}'.format('align left')
'align left '

and many other things (have a look to https://pyformat.info/).

Did you know?

format() is also able to access attributes or items of the parameters.

For instance with a dictionary, we can do this:

>>> 'Name: {person[name]}, age: {person[age]}'.format(person={'name': 'Eric', 'age': 41})
'Name: Eric, age: 41'

And the same goes with attributes:

>>> class Song(object):
... title = 'Where is my mind'
...
>>> 'My favorite song is: {song.title}'.format(song=Song())
'My favorite song is: Where is my mind'

That's really cool. It starts looking like a template engine, right?

Ok, but few things are missing

What we usually expect from a template engine is to be able to:

  • call methods,
  • make loops over iterables,
  • manage condition.

Let's see how we can handle that.

Calling methods

A method is an attribute of an object, we can call attribute, why couldn't wecall a method? Let's try:

>>> 'My name is {name.upper}'.format(name='eric')
'My name is <built-in method upper of str object at 0x7f67dc8d1630>'

Yeah, not exactly what we expected...

An interesting feature of format() is the format specification: instead of just inserting a field with {field}, we can specify a format like this: {field:spec}.

That's exactly what we do with float for instance:

>>> "{:.3}".format(3.14159)
'3.14'

Well, it is actually very easy to implement our own spec by derivating the Formatter class. So let's implement a ':call' spec in charge of calling the current field:

class SuperFormatter(string.Formatter):
    def format_field(self, value, spec):
        if spec == 'call':
            return value()
        else:
            return super(SuperFormatter, self).format_field(value, spec)

We can use it that way:

>>> sf.format('My name is {name.upper:call}', name="eric")
'My name is ERIC'

Nice!

Loops

Similarly, we can implement a :repeat spec,

class SuperFormatter(string.Formatter):
    def format_field(self, value, spec):
        if spec.startswith('repeat'):
            template = spec.partition(':')[-1]
            if type(value) is dict:
                value = value.items()
            return ''.join([template.format(item=item) for item in value])
        else:
            return super(SuperFormatter, self).format_field(value, spec)

Here, we pass a parameter to the spec to provide the template to use when we iterate on the loop items. So the resulting format is: <field>:repeat:<template>.

This subtemplate is a regular format() template where we escape the curly brackets by doubling them, and where the only field is the loop variable (named item).

So we can use it like this:

>>> sf.format('''Table of contents:
... {chapters:repeat:Chapter {{item}}
... }''', chapters=["I", "II", "III", "IV"])
'''Table of contents:
Chapter I
Chapter II
Chapter III
Chapter IV
'''

Condition

Let's also implement a :if spec to test the field value, and then display or not the subtemplate:

class SuperFormatter(string.Formatter):
    def format_field(self, value, spec):
        if spec.startswith('if'):
            return (value and spec.partition(':')[-1]) or ''
        else:
            return super(SuperFormatter, self).format_field(value, spec)

At first, it seems stupid, because it looks like it will only be able to conditionnally display static portions, like this:

>>> sf.format('Action: Back / Logout {manager:if:/ Delete}', manager=False)
'Action: Back / Logout '
>>> sf.format('Action: Back / Logout {manager:if:/ Delete}', manager=True)
'Action: Back / Logout / Delete'

What if we want to render conditionnally a portion of template containing fields, like this:

>>> sf.format('Action: Back / Logout {manager:if:/ Delete {id}}', manager=False, id=34)
'Action: Back / Logout '
>>> sf.format('Action: Back / Logout {manager:if:/ Delete {id}}', manager=True, id=34)
'Action: Back / Logout / Delete 34'

Hey that works! That was unexpected. To be honest, I first wrote the test exactly like this, and I expected it to fail, but it was not! Why is that?

Because here the curly brackets are not escaped, so they are processed by the main format() call. So cool!

Here we go

That's it, we have a pretty nice and complete template engine.

The full code of our world's simplest Python template engine is here, the implementation itself is 10 lines long, Python is a really powerful language!

If you have any funny idea to improve it (remember, I want to keep it short), pull requests are welcome.

The objective is mostly to have fun with Python and demonstrate what the standard Formatter class is able to do, but, having a second though, I might intregate it in Rapido :).

Makina Corpus: Paypal tracking with Rapido

2016-12-01T00:00:00Z

Paypal Instant Payment Notification (IPN)

If we put a Paypal button somewhere in a website, it is nice to know if the user got through the payment process properly and did not just canceled in the middle.

To achieve this, Paypal provides an asynchronous messaging service named Instant Payment Notification (IPN). Here is the process:

  • we create a regular Paypal button and we add an extra hidden input named "custom" which value will be our tracking id (it can be the user id, or anything relevant to our case),
  • when the user clicks on the button, he/she leaves our site and goes to Paypal, and once the payment is complete, Paypal notifies us by making a request to our IPN URL (this is an URL we declare in our Paypal settings),
  • this request contains all the payment information including the custom variable (so we can know who paid what, how much, and store that in our system),
  • to acknowledge the notification, we are supposed to do 2 things:
    • reply with an empty content
    • make a POST containing the very same information contained in the notification request plus "cmd=_notify-validate"
  • and then Paypal answers to our POST by returning "VERIFIED".

How to do it with Rapido

Creating the Paypal button is easy, we just copy/paste the core provided by Paypal in a block (see the Rapido documentation to learn how to create blocks) and we add our "custom" variable:

pay.yaml:

elements:
    trackingid:
        type: BASIC

pay.py:

def trackingid(context):
    currentUser = context.api.user.get_current()
    return currentUser.getUserName() # or anything else relevant

pay.html:

<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_top">
    <input type="hidden" name="custom" value="{trackingid}"/>
   <input type="hidden" name="cmd" value="_s-xclick">
   <input type="hidden" name="hosted_button_id" value="XXXXXXXXXX">
   <input type="image" src="https://www.sandbox.paypal.com/fr_FR/FR/i/btn/btn_paynowCC_LG.gif" border="0" name="submit" alt="PayPal, le réflexe sécurité pour payer en ligne">
   <img alt="" border="0" src="https://www.sandbox.paypal.com/fr_FR/i/scr/pixel.gif" width="1" height="1">
</form>

Note: make sure we do not insert the full block form but just its children with our Diazo rule because we would get a form into a form, so the rule will be like that:

<after css:content="h1.documentFirstHeading">
<include href="@@rapido/myapp/block/pay" css:content-children="form[name='pay']"/>
</after>

Now let's see how to implement the listener that will get the Paypal notification. At some point, we will need to create a POST requests, so we need an extra library for that. We will use the well-known Python requests library, so we need to declare it safe for Rapido.

Hence we add the following somewhere in our custom theme module, for instance in __init__.py (or anywhere else):

import requests
from rapido.core import app
app.safe_modules.requests = requests

Warning: allowing to use a module like Requests in Rapido can have consequences regarding security, so if you do not control who is allowed to create Rapido apps (by default, only managers), do not do it.

And now, we create a block named ipn, containing an element named listener, the IPN URL we will declare to Paypal will be:

http://my.server.com/@@rapido/myapp/block/ipn/listener

Here is the implementation:

ipn.yaml:

elements:
listener:
type: BASIC

ipn.py:

def listener(context):
trackingid = context.request.form['custom']
paypal_params = {'cmd': '_notify-validate'}
# collect all the Paypal params
for key in context.request.form:
paypal_params[key] = context.request.form[key]
# acknowledge with a POST
req = context.modules.requests.post(
'https://www.sandbox.paypal.com/cgi-bin/webscr',
data=paypal_params)
# check if everthing is ok
if req.text == "VERIFIED":
mark_payment_has_done(trackingid)
# return an empty answer to the Paypal original request
return ''

That's it, that's just 10 lines of code (of course we will need to implement mark_payment_has_done() depending on our case inb order to persist in a record that the payment is done and verified). 

November 30, 2016

David "Pigeonflight" Bain: Small Plone team ready for interesting problems

by David Bain at 2016-11-30T21:17:00Z




Starting December 1, 2016 the Alteroo team will be available for new Plone gigs.

Our team members are ready to dive into modern Plone development including Diazo and Mosaic on Plone 5. We also have experience with older versions of Plone.

If you're into checking boxes we also have experience with Javascript/ReactJS/Webpack/Babel, Pyramid/Kotti, Firebase, QA, Linux server administration and General Design skills.

Send an email to newgigs - [ at ]- alteroo.com.

November 28, 2016

Gil Forcada: Faster tests and python 3

by gforcada at 2016-11-28T19:40:39Z

2x faster

Thanks to the Plone Foundation that is sponsoring a new dedicated server for our jenkins nodes (the machines that run our test suite on every change),
the Plone community is starting to enjoy faster builds (twice as fast!).

If your pull request or jenkins job runs on Node 5 or Node 6 you will notice it :-)

Please report any misbehavior on jenkins.plone.org github project if you happen to notice something not working as expected.

Happy testing!

Python 3

As the Zope community is getting closer and closer to make a Zope release Python 3 compatible, us, the Plone community have to step up and do the same.
For that, we are working on, guess what, a new Jenkins job that will only run the test suite of all packages that are known to work on Python 3 already.

The initial list isn’t that big, roughly 10 packages so far, but as more and more Zope packages are updated, the more Plone packages that can be made compatible as well.

The upcoming Alpine Sprint will be dedicated towards this: getting a Plone version compatible with the current Zope versions, which will eventually lead to this Zope on python 3 target (aimed to be released by the end of next year).

Happy hacking!

November 25, 2016

Four Digits: Using SCSS mixins to render repetitive selectors

by Thijs Kramer at 2016-11-25T15:57:31Z

I had the following things to keep in mind:

  • the designers provided me font-sizes defined in px while I wanted to use rem.
  • There were multiple themes, so the font sizes and line heights differ per theme.

At first I had to write a mixin that returned font-size and line-height properties, and converted pixel values to rem values:

@mixin fontsize-lineheight($font-size, $line-height, $base: 16px) {
    $remsize: ($font-size / $base);
    font-size: #{$remsize}rem;
    line-height: $line-height / $font-size;
}

However I wanted line-height to be unit-less, so I had to convert the variables to unit-less values using the following @function:

@function strip-units($value) {
    @return $value / ($value * 0 + 1);
}

(source: this Stackoverflow answer)

So the final result of the mixin was:

@mixin fontsize-lineheight($font-size, $line-height, $base: 16px) {
    $remsize: (strip-units($font-size) / strip-units($base));
    font-size: #{$remsize}rem;
    line-height: strip-units($line-height / $font-size);
}

Now this mixin was ready to use for every heading:

h1, .h1 {
    @include fontsize-lineheight(30px, 40px);
    @include media-breakpoint-up(md) {
        @include fontsize-lineheight(40px, 50px);
    }
    @include media-breakpoint-up(lg) {
        @include fontsize-lineheight(60px, 72px);
    }
}
// ....and so on

This still looks quite repetitive, so I made a map containing lists for the font sizes and line heights, like this:

// font-sizes, from left to right:
//      lg   md   sm
$heading-sizes: (
    h1: 72px 48px 36px,
    h2: 48px 32px 30px,
    ...
);
$heading-lineheights: (
    h1: 72px 48px 36px,
    h2: 48px 36px 30px,
    ...
);

Every entry in the map can be accessed with map-get, for example:

$font-size-h1: map-get($heading-sizes, h1);

And every entry in a list can be accessed by its index (1-based) using nth, for example:

$font-sizes-h1: map-get($heading-sizes, h1);
$font-size-h1-md: nth($font-sizes-h1, 2);

So all of the above can be combined into the following mixin:

@mixin heading($heading) {
    $sizes: map-get($heading-sizes, $heading);
    $line-heights: map-get($heading-lineheights, $heading);
    @include fontsize-lineheight(nth($sizes, 3), nth($line-heights, 3));
    @include media-breakpoint-up(md) {
        @include fontsize-lineheight(nth($sizes, 2), nth($line-heights, 2));
    }
    @include media-breakpoint-up(lg) {
        @include fontsize-lineheight(nth($sizes, 1), nth($line-heights, 1));
    }
}

So putting everything together the final result is:

@function strip-units($value) {
    @return $value / ($value * 0 + 1);
}
@mixin fontsize-lineheight($font-size, $line-height, $base: 16px) {
    $remsize: (strip-units($font-size) / strip-units($base));
    font-size: #{$remsize}rem;
    line-height: strip-units($line-height / $font-size);
}
@mixin heading($heading) {
    $sizes: map-get($heading-sizes, $heading);
    $line-heights: map-get($heading-lineheights, $heading);
    @include fontsize-lineheight(nth($sizes, 3), nth($line-heights, 3));
    @include media-breakpoint-up(md) {
        @include fontsize-lineheight(nth($sizes, 2), nth($line-heights, 2));
    }
    @include media-breakpoint-up(lg) {
        @include fontsize-lineheight(nth($sizes, 1), nth($line-heights, 1));
    }
}
$heading-sizes: (
    h1: 72px 48px 36px,
    h2: 48px 32px 30px,
    h3: 36px 30px 24px,
    h4: 30px 24px 20px,
    h5: 24px 20px 18px,
    h6: 20px 18px 16px
);
$heading-lineheights: (
    h1: 72px 48px 36px,
    h2: 48px 36px 30px,
    h3: 42px 36px 30px,
    h4: 36px 30px 24px,
    h5: 30px 24px 21px,
    h6: 24px 21px 18px
);
$headings: h1 h2 h3 h4 h5 h6;
@each $heading in $headings {
    #{$heading}, .#{$heading} {
        @include heading($heading);
    }
}

If you have any reactions please leave them in the comments section below!

November 23, 2016

Martijn Faassen: Looking for new challenges

by Martijn Faassen at 2016-11-23T12:14:22Z

Fair warning: In this blog post I aim to sell myself. I'm looking for an exciting and challenging new freelance engagement.

I'm a software developer and I have been one professionally for about 20 years now. I have deep experience, and I continue to learn and create. I know what real-world codebases look like, and I know software development is also about people. I think I can offer lot of value. I can develop software for you, and I can also help you improve the way you develop software.

I see myself as a creative developer -- I want to invent things to improve life for myself and others. Creativity is what attracts me to software development the most. Creativity is transformative. If you need a bit of transformation in your software, talk to me.

I'm a web application developer. I've focused on web development since the late 90s. In that period I've seen the web grow from static websites and with a few server-side Perl scripts thrown in to the dynamic application platform it is today. I started developing web applications with the server-side, the only game in town then, but over the last 10 years I've shifted more and more to the client-side and JavaScript, where much of the creativity is today. I am however still very much at home on the server as well. I've done React, I've done REST, I've done hypermedia APIs, I've dug into GraphQL. If you need a web developer with deep insight in the whole stack, look no further.

I've focused on Python for the better part of my software development career. I came to Python early; I have seen Python grow from a small language with no name recognition to the enormously popular language it is today. I greatly enjoy using it. I've also criticized it where I felt it was needed, painful as it was. If you need a very experienced Python developer, contact me.

But in the last decade I've started to use JavaScript more and more. Thanks to the React community I've learned a few new things about functional programming; it's exciting to see it become relevant to the web. I haven't stopped looking at interesting new languages. I'm a developer who can look beyond a single programming language.

I have repeatedly demonstrated I can take a large piece of software and transform it:

  • Back in the day, I rejuvenated the Zope web framework with Five, a technology that is still in use by the Plone CMS today.
  • I took libxml2, a huge C library that was difficult to use for Python developers, and created the most powerful XML library in the Python world: lxml. I used the predecessor to Cython to do this (in 2004!).
  • I created a simpler, better way to use Zope with Grok. I've helped add web capabilities to existing codebases with a deep history.

I can help you open up your codebase to new possibilities.

I can build on other people's foundations, but I can also build new foundations. In the last few years I've created Morepath, a web framework that compresses the power I expect into a few thousand lines of Python code.

I'm not afraid to say I've also created many a thing that went nowhere. In 2010 I created Obviel, a client-side web framework. I took concepts like model/view separation and templates and a form library and brought them to JavaScript and the client. I thought I was doing something new in 2010, something that people hadn't really thought of yet. It turns out everybody had the same idea about the same time. Backbone burst upon the scene and Obviel never got any traction. Now I'm a frontend web framework hipster; I was doing them before it was cool. It was worth it, because I gained deep insights in what makes a frontend framework tick.

These days I prefer to use React for front-end application development. React is awesome. With React Native a mere web developer such as myself can even build a real mobile app. Want a developer that loves React but is also tempered by experience? Look no further.

I'm looking for a new challenge. I want to help build, create and transform. I work from home (in the Netherlands) so I can enjoy my family and garden, but I can certainly come visit you on a regular basis. I write code, I write docs, I write tests, I give talks, I give training, and I review your code. I am open, constructively critical and honest. I contribute a bit of insight here and there. My services are not cheap, but they are worth it.

In summary, here I am: a very experienced, creative web developer who looks a little bit beyond what's in front of him.

Think you have an interesting challenge for me? Please drop me a mail at faassen@startifact.com and let's talk.

Alex Clark: Project Makefile Open for Business

2016-11-23T00:00:00Z

Makefile for Python Web Development & Related Projects

A while back I was asked to speak to the Configuration Management Working Group of DC:

../../_images/project-makefile-tweet.png

From that moment on, it was on: an excuse to finish and talk about the Makefile I’d been dragging around formerly since January and informerly much longer.

Finishing the Makefile

I started writing slides on the impressive slides.com then I realized I had to finished the Makefile to finish the slides. This mostly involved deciding on target names and testing target execution.

Finishing the Slides

As I mentioned above, slides.com is very nice. I had hoped to be able to build the slides myself with reveal.js, but in lieu of JavaScript skills I settled on using the slides.com editor. Later I exported and converted them to PDF with pandoc, which was not as nice (through no fault of pandoc, I’m sure; I just wish I could get a better PDF copy from the slides.com HTML export.)

Closed for Business

For month after month as I continued to tweak, the project-makefile repository README contained the following:

**DO NOT USE THIS**
At some point I started using a ``Makefile`` in my Python projects. This repository
contains that ``Makefile``.
**shrug**

Open for Business

Now it contains this:

Installation
------------
::
    curl -O https://raw.githubusercontent.com/aclark4life/project-makefile/master/Makefile
Usage
-----
::
    Usage: make [TARGET]
    Available targets:
        - ablog
        - ablog-build
        - ablog-clean
        - ablog-init
        - ablog-install
        - ablog-serve
        - co
        - commit
        - commit-auto
        - commit-edit
        - django
        - django-clean
        - django-clean-migrations
        - django-init
        - django-install
        - django-migrate
        - django-migrations
        - django-serve
        - django-shell
        - django-static
        - django-su
        - django-test
        - django-yapf
        - git-checkout-remotes
        - git-commit
        - git-commit-auto
        - git-commit-auto-push
        - git-commit-edit
        - git-push
        - grunt
        - grunt-file
        - grunt-init
        - grunt-install
        - grunt-serve
        - h
        - he
        - heroku
        - heroku-debug-off
        - heroku-debug-on
        - heroku-init
        - heroku-push
        - heroku-remote
        - heroku-shell
        - heroku-web-off
        - heroku-web-on
        - install
        - lint
        - npm
        - npm-init
        - npm-install
        - package
        - package-check-manifest
        - package-init
        - package-lint
        - package-pyroma
        - package-readme
        - package-release
        - package-release-test
        - package-test
        - pdf
        - plone
        - plone-heroku
        - plone-init
        - plone-install
        - plone-serve
        - push
        - python-clean
        - python-flake
        - python-freeze
        - python-install
        - python-lint
        - python-serve
        - python-virtualenv
        - python-wc
        - python-yapf
        - release
        - release-test
        - review
        - serve
        - sphinx
        - sphinx-build
        - sphinx-clean
        - sphinx-init
        - sphinx-install
        - sphinx-serve
        - test
        - vagrant
        - vagrant-clean
        - vagrant-down
        - vagrant-init
        - vagrant-up
        - vagrant-update
        - vm
- Check out the `slides <http://slides.com/aclark/project-makefile>`_ for more information.

Now I invite everyone to use and contribute!


November 21, 2016

eGenix: eGenix PyRun - One file Python Runtime 2.2.3 GA

2016-11-21T13:00:00Z

Introduction

eGenix PyRun is our open source, one file, no installation version of Python, making the distribution of a Python interpreter to run based scripts and applications to Unix based systems as simple as copying a single file.

eGenix PyRun's executable only needs 11MB for Python 2 and 13MB for Python 3, but still supports most Python application and scripts - and it can be compressed to just 3-4MB using upx, if needed.

Compared to a regular Python installation of typically 100MB on disk, eGenix PyRun is ideal for applications and scripts that need to be distributed to several target machines, client installations or customers.

It makes "installing" Python on a Unix based system as simple as copying a single file.

eGenix has been using eGenix PyRun internally in the mxODBC Connect Server product since 2008 with great success and decided to make it available as a stand-alone open-source product.

We provide both the source archive to build your own eGenix PyRun, as well as pre-compiled binaries for Linux, FreeBSD and Mac OS X, as 32- and 64-bit versions. The binaries can be downloaded manually, or you can let our automatic install script install-pyrun take care of the installation: ./install-pyrun dir and you're done.

Please see the product page for more details:

    >>> eGenix PyRun - One file Python Runtime

News

This minor level release of eGenix PyRun comes with the following enhancements:

Enhancements / Changes

  • Removed lzma module from PyRun for Python 3.x again, since this caused too many issues with incompatible/missing libzma.so references. The module is still being built as optional add-on and can be used if the necessary libs are available, but it will no longer prevent PyRun from working altogether.

install-pyrun Enhancements

  • Updated install-pyrun to default to eGenix PyRun 2.2.3 and its feature set.
For a complete list of changes, please see the eGenix PyRun Changelog.

Downloads

Please visit the eGenix PyRun product page for downloads, instructions on installation and documentation of the product.

Support

Commercial support for this product is available directly from eGenix.com.

Please see the support section of our website for details.

More Information

For more information on eGenix PyRun, licensing and download instructions, please write to sales@egenix.com.

Enjoy !

Marc-Andre Lemburg, eGenix.com

November 18, 2016

eGenix: eGenix PyRun - One file Python Runtime 2.2.2 GA

2016-11-18T15:00:00Z

Introduction

eGenix PyRun is our open source, one file, no installation version of Python, making the distribution of a Python interpreter to run based scripts and applications to Unix based systems as simple as copying a single file.

eGenix PyRun's executable only needs 11MB for Python 2 and 13MB for Python 3, but still supports most Python application and scripts - and it can be compressed to just 3-4MB using upx, if needed.

Compared to a regular Python installation of typically 100MB on disk, eGenix PyRun is ideal for applications and scripts that need to be distributed to several target machines, client installations or customers.

It makes "installing" Python on a Unix based system as simple as copying a single file.

eGenix has been using eGenix PyRun internally in the mxODBC Connect Server product since 2008 with great success and decided to make it available as a stand-alone open-source product.

We provide both the source archive to build your own eGenix PyRun, as well as pre-compiled binaries for Linux, FreeBSD and Mac OS X, as 32- and 64-bit versions. The binaries can be downloaded manually, or you can let our automatic install script install-pyrun take care of the installation: ./install-pyrun dir and you're done.

Please see the product page for more details:

    >>> eGenix PyRun - One file Python Runtime

News

This minor level release of eGenix PyRun comes with the following enhancements:

Enhancements / Changes

  • Upgraded PyRun to Python 2.7.12, Python 3.4.5 and Python 3.5.2.
  • Fixed rpath setting to properly include the $ORIGIN marker. Without this, the rpath setting doesn't work.
  • Added missing lzma module to default PyRun 3.x installation. Please note that this adds an additional dependency on libzma.so.5 for PyRun for Python 3.4 and 3.5.

install-pyrun Enhancements

  • Updated install-pyrun to default to eGenix PyRun 2.2.2 and its feature set.
For a complete list of changes, please see the eGenix PyRun Changelog.

Downloads

Please visit the eGenix PyRun product page for downloads, instructions on installation and documentation of the product.

Support

Commercial support for this product is available directly from eGenix.com.

Please see the support section of our website for details.

More Information

For more information on eGenix PyRun, licensing and download instructions, please write to sales@egenix.com.

Enjoy !

Marc-Andre Lemburg, eGenix.com

November 17, 2016

David "Pigeonflight" Bain: Installing Plone 5 on Windows: Part 2 - Installing Plone

by David Bain at 2016-11-17T18:10:00Z

This is part 2 of installing Plone 5 on Windows. The following instructions are specific to installing Plone 5 on Windows. Part 1 covered
This is part 2 of installing Plone 5 on Windows. The following instructions are specific to installing Plone 5 on Windows. Part 1 covered preparing your Windows machine for Plone.

Assumptions




You now have all the tools needed to build a full Plone environment. Plone uses a tool called "buildout" for managing builds, this makes it possible to distribute build configurations using git or other revision management tools. The folder where your build configuration exists is also referred to as a buildout. We will checkout an existing buildout called "themedev.buildout". The intention of the "themedev.buildout" is to provide all the tools needed for Plone theme development.

In the steps below you will clone the buildout then run an initializaton script called "setup.bat"

Step 1 - Install Virtualenv

Launch git bash and run the following to install virtualenv.

pip install virtualenv

Step 2 - Clone the buildout, run the setup script and bin/buildout


git clone https://github.com/collective/themedev.buildout
cd themedev.buildout
./setup.bat
bin/buildout

Day to Day Usage

To launch the instance run the following:

bin/instance fg




November 15, 2016

Four Digits: Wagtail Space

by Maarten Kling at 2016-11-15T14:15:00Z

After organising many Plone related sprints and a conference, we will host our first Wagtail Sprint next year. Wagtail is a very clean and neat CMS, based on our beloved language Python. Enough reason for us to host a sprint and add some features like training sessions and talks. You will get the complete Wagtail community experience.

Wagtail Space brings you Wagtail training sessions, Wagtail (lightning) talks and a Wagtail sprint. There is room for over 40 attendees, several of whom will be Wagtail core developers. It’s not just work and no play, there will be a party on Friday evening, so plenty of time to socialize. All Wagtail enthusiasts are welcome, regardless of their role. If you are a beginner, we will get you up and running, whereas more advanced developers can dive in deep right away.

Are you ready to fly? Enter Wagtail Space!

March 21 - 25, 2017
Jansbinnensingel 26,
6811AL Arnhem
The Netherlands

November 10, 2016

David "Pigeonflight" Bain: Installing Plone 5 on Windows: Part 1 - Preparing the machine

by David Bain at 2016-11-10T03:23:00Z

Windows does not ship with all the tools needed to install Plone for development. These are the steps needed to prepare your Windows machine for Plone 5.
Windows does not ship with all the tools needed to install Plone for development. These are the steps needed to prepare your Windows machine for Plone 5.

Assumptions

I assume that you're using a Windows machine on which you have enough permissions to run commands as an administrator. That's it!

What you will need to install

I recommend that you install the following to run Plone:
  • Git for Windows
  • Python 2.7
  • Visual C++ for Python 2.7
  • Pywin32
  • NodeJS
If you don't have a preferred text editor gedit is a simple editor for beginners.

The Steps

Step 1 - Download and install Git for Windows

IMPORTANT, Install Git for Windows First, it adds some context tools to Windows which you will use later.
Download and install git for windows from https://git-for-windows.github.io.

Step 2 - Download and install Python 2.7 from https://www.python.org/downloads/windows/

The latest version at the time of writing was Python 2.7.12. Basically it's a matter of clicking "next, next, next" EXCEPT on the "Customize" dialog. Look for "Add python.exe to Path" and make sure it is enabled (it is disabled by default).






Apart from one adjustment it is basically "next, next, next" to install



























.                                                                                                                                                             .

Step 3 - Download and install Visual C++ for Python 2.7 

Download from https://www.microsoft.com/en-us/download/details.aspx?id=44266

Make sure it is downloaded to your "Downloads" folder.

Right click on your Downloads folder and from the context menu select Git Bash Here.

save image

In the resulting console type the following and hit the enter key:

msiexec /i VCForPython27.msi ALLUSERS=1

This launches the Windows installer with administrator privileges. Click "Ok" to proceed.

save image


Step 4 - Install Pywin32

Make sure you download the latest build (220 at the time of writting) and the one for Python 2.7.
save image

Step 5 - Install NodeJS


Download NodeJS from https://nodejs.org/en/download/ and make sure to select the recommended version LTS.

save image

Step 6 - Install Gedit (optional)

You can skip this step if you already have a text editor, otherwise download and install gedit https://wiki.gnome.org/Apps/Gedit#Download

Why this approach?

  • Visual C++ for Python 2.7 results in faster modules which means that Plone will run faster than if you had used an equivalent compiler like GCC+.
  • It is more common in the Windows world to point and click rather than run commands on the command line, I tried my best to minimize interactions with the command line. The approach should feel more natural for Windows users, especially more casual users.


November 08, 2016

Andreas Jung: Bringing real collaborative editing to Plone

2016-11-08T16:09:24Z

Integration of Plone 5 with the Smashdocs authoring solution.

eGenix: PyDDF Python Sprint 2016

2016-11-08T08:00:00Z

The following text is in German, since we're announcing a Python sprint in Düsseldorf, Germany.

Ankündigung

PyDDF Python Sprint 2016 in Düsseldorf


Samstag, 19.11.2016, 10:00-18:00 Uhr
Sonntag, 20.11.2016, 10:00-18:00 Uhr

trivago GmbH,  Karl-Arnold-Platz 1A,  40474 Düsseldorf

Informationen

Das Python Meeting Düsseldorf (PyDDF) veranstaltet mit freundlicher Unterstützung der trivago GmbH ein Python Sprint Wochenende im September.

Der Sprint findet am Wochenende 19./20.11.2016 in der trivago Niederlassung am Karl-Arnold-Platz 1A statt (nicht am Bennigsen-Platz 1). Bitte beim Pförtner melden. Folgende Themengebiete haben wir als Anregung angedacht:
  • Openpyxl
Openpyxl ist eine Python Bibliothek, mit der man Excel 2010+ Dateien lesen und schreiben kann.

Charlie ist Co-Maintainer des Pakets.
  • MicroPython auf ESP8266 und BBC micro:bit

MicroPython ist eine Python 3 Implementierung für Micro Controller. Sie läuft u.a. auf dem BBC micro:bit, einem Ein-Patinen-Computer, der in Großbritannien an Kinder der 7. Klassen verteilt wurde, und dem mittlerweile sehr populären IoT Chip ESP8266, der WLAN unterstützt.

Im Sprint wollen wir versuchen, ein Mesh Network aus BBC micro:bits aufzubauen, das dann an einen ESP8266 mit dem WLAN verbunden wird. Alles mit Hilfe von MicroPython.

Vorkenntnisse sind eigentlich keine nötig. Wir werden mindestens einen ESP8266 und drei BBC micro:bits zur Verfügung haben.
Natürlich kann jeder Teilnehmer weitere Themen vorschlagen, z.B.
  • Kivy (Python auf Android/iOS)
  • RaspberryPi (wir werden ein paar davon mitbringen)
  • FritzConnection (Python API für die Fritzbox)
  • OpenCV (Bilder von Webcams mit Python verarbeiten)
  • u.a.

Anmeldung und weitere Infos

Alles weitere und die Anmeldung findet Ihr auf der Sprint Seite:

Teilnehmer sollten sich zudem auf der PyDDF Liste anmelden, da wir uns dort koordinieren:

Über das Python Meeting Düsseldorf

Das Python Meeting Düsseldorf ist eine regelmäßige Veranstaltung in Düsseldorf, die sich an Python Begeisterte aus der Region wendet.

Einen guten Überblick über die Vorträge bietet unser PyDDF YouTube-Kanal, auf dem wir Videos der Vorträge nach den Meetings veröffentlichen.

Veranstaltet wird das Meeting von der eGenix.com GmbH, Langenfeld, in Zusammenarbeit mit Clark Consulting & Research, Düsseldorf.

Viel Spaß !

Marc-Andre Lemburg, eGenix.com

November 03, 2016

Reinout van Rees: DSA ssh keys also deprecated in OSX Sierra

by Reinout van Rees at 2016-11-03T08:05:00Z

I've been using an ssh key for a long time. Back in the days when RSA keys were mostly commercial/proprietary and when DSA keys where the recommended method.

When ubuntu 16.04 came out, I suddenly couldn't use my key anymore as ubuntu (or perhaps rather its updated ssh server) didn't accept DSA keys anymore. They're apparently not save enough anymore.

I worked around it by adding a setting on the server, telling it to accept my DSA key.

When the latest Apple OS update (Sierra) came out, I suddenly couldn't log in anywhere. Also git pull to github (I'm using ssh) stopped working. I found the cause by passing -vvvv to ssh:

debug1: Next authentication method: publickey
debug1: Trying private key: /Users/reinout/.ssh/id_rsa
debug3: no such identity: /Users/reinout/.ssh/id_rsa: No such file or directory
debug1: Trying private key: /Users/reinout/.ssh/id_ecdsa
debug3: no such identity: /Users/reinout/.ssh/id_ecdsa: No such file or directory
debug1: Trying private key: /Users/reinout/.ssh/id_ed25519
debug3: no such identity: /Users/reinout/.ssh/id_ed25519: No such file or directory
debug2: we did not send a packet, disable method
debug3: authmethod_lookup password
debug3: remaining preferred: ,password
debug3: authmethod_is_enabled password
debug1: Next authentication method: password

Oh.... Sierra's ssh client also doens't like DSA anymore. Ok... time to create a new key :-)

... which I did about 6 weeks ago. With a nice, long passphrase. And 2 weeks ago I had to create a new one as I couldn't for the life of me remember the exact passphrase. I've rarely felt so stupid :-) A passprase can have many almost-right variants:

I'll take the train to django under the hood
I'll take the train to django under the hood.
I'll take the train to Django under the Hood
I'll take the train to Django under the Hood.
I will take the train to django under the hood
I will take the train to django under the hood.
I will take the train to Django under the Hood
I will take the train to Django under the Hood.
I'm taking the train to Django under the Hood.
I'm taking the train to Django under the Hood
I'm taking the train to Django Under The Hood.
I'll go by train to Django Under The Hood.
etc...
etc...

Well, everything works again :-)