20 Nov 2019

feedSymfony Blog

New in Symfony 4.4: IP Address Anonymizer

Jordi Boggiano

Contributed by
Jordi Boggiano in #32194.

Privacy is an increasingly important compliance concern for tech companies. Existing regulations such as EU 2016/679, commonly known as GDPR, and upcoming regulations such as CCPA (California Consumer Privacy Act) impose some restrictions on the collection and treatment of personal data.

In addition to classic personal data such as names and phone numbers, some digital information, such as email addresses and IP addresses, are also considered personal data.

A common procedure to store information about users (for analysis purposes) while being compliant is to anonymize IP addresses. Specifically, you must remove the last byte for IPv4 addresses and the last 8 bytes for IPv6 addresses.

Although this is not technically challenging, in Symfony 4.4 we've added a new anonymize() method to the IpUtils class so you don't have to create this method yourself:

1
2
3
4
5
6
7
8
9
use Symfony\Component\HttpFoundation\IpUtils;

$ipv4 = '123.234.235.236';
$anonymousIpv4 = IPUtils::anonymize($ipv4);
// $anonymousIpv4 = '123.234.235.0'

$ipv6 = '2a01:198:603:10:396e:4789:8e99:890f';
$anonymousIpv6 = IPUtils::anonymize($ipv6);
// $anonymousIpv6 = '2a01:198:603:10::'

Be trained by Symfony experts - 2019-11-25 Lille - 2019-11-25 Clichy - 2019-11-25 Clichy

20 Nov 2019 6:35am GMT

19 Nov 2019

feedDjango community aggregator: Community blog posts

One Team’s Development Patterns With Vue.js and Django REST Framework

Within the past year, my development team at Caktus worked on a project that required a front-end framework to build a fast, easy-to-use product for a client. After a discussion of frameworks such as React, Vue, and Angular, and their approaches, our team settled on using Vue.js, along with a Django back-end with Django REST Framework (DRF). Initially, we chose Vue because we were more familiar with it, rather than its current competitor React, but as we worked on the product, we ended up having a number of team discussions about how to organize our code well and avoid extra code debt. This blog outlines some of the development patterns we chose as we worked through a number of issues, such as simplifying a multitude of almost identical Vuex mutations, finding a consistent way of holding temporary state, and working with nested objects on the front-end and back-end.

Note: this blog post assumes familiarity either with Vue.js, or a similar front-end framework, like React or AngularJS.

Issue 1: Almost Identical Mutations

In our use of Vue.js, we chose to use the Vuex library for state management in a store, as recommended by the Vue documentation. Following Vuex documentation, we created a number of mutations to alter the state of objects inside of our store. For example, a user in our store (in this blog post's examples, we'll focus on this user object) could look like:

{
  'first_name': '',
  'middle_name': '',
  'last_name': '',
  'email': '',
  'date_of_birth': '',
}

And, so following the Vuex docs, we created mutations for updating each of the user's properties in the store, like this:

updateUserFirstName (state, firstName) {
  state.user.first_name = firstName
},
updateUserMiddleName (state, middleName) {
  state.user.middle_name = middleName
},
updateUserLastName (state, lastName) {
  state.user.last_name = lastName
},
updateUserEmail (state, email) {
  state.user.email = email
},
updateUserDateOfBirth (state, dateOfBirth) {
  state.user.date_of_birth = dateOfBirth
}

This worked great when having only a few objects in the store, but this pattern became increasingly repetitive when both the number of objects in the store (user, company, address, etc.) and the number of properties for each object (first name, middle name, last name, gender, date of birth, etc.) increased. It became clear that having a mutation for each property (updateUserFirstName, updateUserMiddleName, updateUserLastName, updateUserDateOfBirth, etc.) led to redundant lines of mutation code. As a result, we wanted to find a less repetitive, and a more DRY (Don't Repeat Yourself) way of doing so, in order to keep our codebase more readable and maintainable. After some discussion and coding, we created a generic and flexible mutation that would allow us to update any property of the user object:

updateUserAttributes (state, updatesObject) {
  /* Update specific attributes of the user in the store. */
  state.user = Object.assign(deepcopy(state.user), updatesObject)
},

This way, we could update the user's first name and last name by calling

this.$store.commit(
  'updateUserAttributes',
  { 'first_name': 'Newfirstname', 'last_name': 'Newlastname' }
)

from any of our Vue components, which is both less lines of code (less code debt), and easier to write.

Note: The code above uses a deepcopy() function, which is a utility function we wrote for copying an object, and all of its nested fields and objects so that the copied object's nested data no longer points to the original nested data, using lodash's cloneDeep() method. As we found out earlier, simply using Object.assign() creates a new object with nested fields that point to the original object's nested fields, which becomes problematic if the new object gets committed to the store, but then the original object's nested field gets changed, surprisingly leading to the same field change on the new object.

Issue 2: Using Store Or Components For Temporary State

Another issue we discussed at length had to do with how to manage the state of what the user was doing on a particular page. For example, if the user is editing their personal information on a page, we could hold that data in the store, and end up updating the data in the store as the user types on their keyboard. Alternatively, we could let the Vue component hold onto the data, and save them in the back-end when the user presses 'Save,' and wait for the next page load to load it into the store. Or, we could let the Vue component hold onto the data and update it in the store and the back-end when the user clicks 'Save.' Here's a breakdown of pros and cons to each approach:

only refer to store update store and backend on 'Save' update backend on 'Save'
only 1 place to manage state multiple places to manage state (store for permanent state and components for temporary state) multiple places to manage state permanent state and components for temporary state)
user sees changes immediately user sees changes on when clicking 'Save' user sees changes in other components on page load
user sees that clicking 'Save' changes the page user may not want to see changes in multiple components while typing user may not want to see changes in multiple components while typing
forcing the user to click 'Save' gives a clearer indication of what the user is doing forcing the user to click 'Save' gives a clearer indication of what the user is doing

Though making the changes instantly in the store took away the need to manage data in the Vue component, we ultimately decided that it would be more reusable and useful to save the changes both in the front-end store and in the back-end API when the user clicked a 'Save' button. Moreover, having the user click a 'Save' button seemed a more clear indication that they want to save a piece of data than just typing a value in a field. As a result, we ended up utilizing Vue components' data to hold the local state of the objects, and sent those objects to both the back-end and the store when the user clicked 'Save.' In such a pattern, a user detail page could look something like this:

<template>
...
</template>

<script>
export default {
  name: 'UserDetailPage',
  data () {
    return {
      localUser: {}
    }
  },
methods: {
  saveUser () {
    /* Make an API call to the backend, and update the store. */
    ...
    }
  }
}
</script>

So the data that the user was editing would be held in the localUser object, and when the user clicks 'Save,' the data would be sent to both the back-end and the store.

Issue 3: Nested Objects

A third issue we had a number of discussions about was how to manage an object's relations to other objects. From our user example above, a user likely has an address (which is its own object), and the user could have a number of siblings, who have their own addresses, and the user could work at a company, which also has an address, which could have employees, who have their own addresses. Very quickly, the user object could have many layers of nested data, which can become rather unmanageable:

store = {
  user: {
    'id': 100,
    'first_name': '',
    'middle_name': '',
    'last_name': '',
    'email': '',
    'date_of_birth': '',
    'address': {
      'id': 123,
      'street_line_1': '',
      'street_line_2': '',
      'city': '',
      ...
    },
    'siblings':
      [
        {
          'id': 200,
          'first_name': '',
          ...
      },
      {
        'id': 2,
        'first_name': '',
        ...
      },
      ...
    ]
  }
}

One solution for avoiding unmanageable nesting would be to manage each object's nested relations with only the related object's ID in the nested fields:

store = {
  user: {
    'first_name': '',
    'middle_name': '',
    'last_name': '',
    'email': '',
    'date_of_birth': '',
    'address': 123,
    'siblings': [200, 2],
  },
  addresses:
    [
      {
        'id': 123,
        'street_line_1': '',
        ...
      }
  ]
}

This makes each object's data much smaller in the store, and decreases repetition of data (for example, when a user's address matches their sibling's address, we don't need to have multiple places with the same data; only referring to the object's ID should be enough).

However, this approach makes communication between the front-end and the back-end more complex. For instance, the user may want to edit their own information on their detail page to:

  • change their email
  • change their address
  • add a child

In such a case, the front-end may have to make three API calls (one to create an address, one to create a child, and one to update user.email, user.address, and user.children), which could take significantly longer than just making one API call to update everything related to the user. As an aside, learn more about creating an API endpoint in this post.

Seeing the pros and cons of each approach, we had some discussion about which way to develop, and after working through several API endpoints, we ended up with the nested approach, though we also tried to limit the amount of nesting that the back-end would be forced to handle. Django REST Framework does support editing an object's relations to other objects by writing custom update() or create() serializer methods (read more here) and we were able to write these methods for some of our serializers. As a result, we were left with some nested data, but tried to be cognizant of how many nested relations we were using, and to limit them when possible.

Team Discussions Led to Sustainable Decisions

Throughout the course of the project, we continued to have conversations about the development patterns we were forming and following, and we attempted to make decisions that would lead to a more maintainable app with less code debt. Through these team discussions, we were able to come up with solutions that worked for us in terms of handling very similar Vuex mutations, handling temporary state, and working with nested data. As a consequence, we were able to deliver a product that satisfied our client's needs, and is maintainable for our future work. We have such conversations as we continue to build apps that are well-built, maintainable, and work well for our users.

19 Nov 2019 12:44am GMT

18 Nov 2019

feedSymfony Blog

New in Symfony 4.4: HttpClient Improvements

Nicolas Grekas

Contributed by
Nicolas Grekas
in #31641, #31831, #31976, #32104, #32231, and #32290.

The Symfony HttpClient component was introduced in Symfony 4.3 as a low-level HTTP client with support for both PHP stream wrappers and cURL. In Symfony 4.4 we've improved it with lots of new features.

In PR #31641 we made $response->getInfo('debug') to return extended logs about the HTTP transaction so you can debug problems more easily.

This is an example of the generated log:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
* Found bundle for host http2-push.io: 0x56193881ae40 [can multiplex]\n
* Connected to http2-push.io (216.239.38.21) port 443 (#0)\n

> GET /css/style.css HTTP/2\r\n
Host: http2-push.io\r\n
User-Agent: Symfony HttpClient/Curl\r\n
Accept-Encoding: deflate, gzip\r\n
\r\n

< HTTP/2 200 \r\n
< content-type: text/css\r\n
< content-encoding: gzip\r\n
< content-length: 1805\r\n
< etag: "0CqJow"\r\n
< \r\n

In PR #31831 we added a new cancel() method so you can cancel responses at any moment.

In PR #31976 and PR #32104 we improved the integration of the component with HTTPlug, another popular library to make HTTP requests. The Symfony HttpClient component is now interoperable with three different abstractions for HTTP clients: Symfony Contracts, PSR-18 and HTTPlug v1 and v2.

In PR #32231 we added support for NTLM authentication:

1
2
3
4
$client = HttpClient::create([
    'auth_ntlm' => 'username:password',
    // ...
]);

In PR #32290 we added a new toStream() method to cast responses to regular PHP streams:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$response = $client->request('GET', 'https://...');
$content = $response->toStream();

// alternatively, you can use this code:
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpClient\Response\StreamWrapper;

$client = HttpClient::create();
$response = $client->request('GET', 'https://...');
$streamResource = StreamWrapper::createResource($response, $client);
Ruben Jacobs

Contributed by
Ruben Jacobs
in #32565.

In PR #32565 we improved the buffer configuration option. In previous Symfony versions this was a boolean option. In Symfony 4.4 you can also pass a PHP closure (which must return a boolean value) to enable buffering conditionally:

1
2
3
4
5
6
7
$response = $client->request('GET', 'https://...', [
    'buffer' => function (array $headers): bool {
        // some logic here to decide if we want to buffer or not

        return true; // or return false;
    },
]);
Peter Schultz

Contributed by
Peter Schultz
in #34216.

In PR #34216 we improved the json configuration option. In previous Symfony versions, this option only allowed passing arrays or objects implementing JsonSerializable. In Symfony 4.4 you can pass any value which can be passed to json_encode(), which includes scalar values and classes with public properties:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Book
{
    public $title = '...';
    public $author = '...';
    // ...
}

$response = $client->request('PUT', 'https://...', [
    'json' => $book,
]);
Thomas Calvet

Contributed by
Thomas Calvet
in #32807.

In PR #32807 we added a new configuration option called max_duration to define the maximum execution time allowed for the whole request + response process. Set it to 0 to not define any time limit:

1
2
3
$response = $client->request('GET', 'https://...', [
    'max_duration' => 21.7,
]);

Be trained by Symfony experts - 2019-11-25 Lille - 2019-11-25 Clichy - 2019-11-25 Clichy

18 Nov 2019 7:41am GMT

17 Nov 2019

feedSymfony Blog

Symfony 5.0.0-RC1 released

Symfony 5.0.0-RC1 has just been released. Here is a list of the most important changes:

Want to upgrade to this new release? Fortunately, because Symfony protects backwards-compatibility very closely, this should be quite easy. Read our upgrade documentation to learn more.

Want to be notified whenever a new Symfony release is published? Or when a version is not maintained anymore? Or only when a security issue is fixed? Consider subscribing to the Symfony Roadmap Notifications.


Be trained by Symfony experts - 2019-11-25 Lille - 2019-11-25 Clichy - 2019-11-25 Clichy

17 Nov 2019 5:20pm GMT

14 Nov 2019

feedDjango community aggregator: Community blog posts

Kenneth Love

14 Nov 2019 12:00am GMT

13 Nov 2019

feedDjango community aggregator: Community blog posts

Django – NGINX: deploy your Django project on a production server

Django - NGINX is a popular and well tested combination used to deploy web applications in production. In this post I will explain the steps needed to have your Django project deployed on a production server using Ubuntu 18.04.

To have Django - NGINX deployed on your production server follow these simple steps.

1. Install required packages using apt

sudo apt install nginx uwsgi uwsgi-plugin-python3

Why do you need uWSGI? In very simple terms NGINX on its own cannot run a Python process to host your application, for this you'll need a so called application server that will host a Python process running your Django project. NGINX and uWSGI will "talk" each other using the uwsgi protocol.

2. Create directories for your static and media files

Static files are "not-python" files needed by your Django project, for example Javascript, CSS and images. Media files will be the files uploaded by the users of your application. Not every application will let users upload files, but it's a very common scenario. Django will not serve static and media files by itself. We'll leverage NGINX to serve them.

First of all you have to create the directories. Here I assume that you are currently using the user ubuntu with the default home directory /home/ubuntu:

mkdir -p /home/ubuntu/static /home/ubuntu/media
sudo chown www-data.www-data /home/ubuntu/media

The second command will make the user named www-data the owner of the /home/ubuntu/media directory. www-data will be the user running your Python process in uWSGI, and that user should be able to write in the media directory to correctly save user uploaded files.

3. Setup your Django project and install requirements

This step really depends on your particular Django application, for the purpose of this tutorial I will assume that your Django project is installed in the directory /home/ubuntu/django_project/ with the following structure:

/home/ubuntu/django_project/
├── app1
│   ├── admin.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── views.py
├── manage.py
└── project
    ├── __init__.py
    ├── settings
    │   └── __init__.py
    │   └── base.py
    │   └── production.py
    ├── urls.py
    ├── wsgi.py

Also I will assume that you installed all your Python requirements, for example using apt or pip.

I always follow a best practice when starting a new Django project, by splitting the monolithic settings.py file in different files, one for each deploy environment (local, test, production, …). You can read a more in depth explanation of this approach if you aren't used to it.

In our case Django will use the module project/settings/production.py for his settings. Here we set the STATIC_ROOT and MEDIA_ROOT variables to the directories we created at step 2:

from .base import *

ALLOWED_HOSTS = [ 'www.example.com' ] # customize with your domain name

DATABASES = {
    'default': { ... } # here the configuration for your database
}

STATIC_ROOT = '/home/ubuntu/static'
MEDIA_ROOT = '/home/ubuntu/media'

4. Collect static files

Run the following command to collect all static files for your Django project:

./manage.py collectstatic

This command will copy all static files (Javascript, CSS, images) for all your Django apps in the STATIC_ROOT directory configured in production.py. For instance /home/ubuntu/static.

5. Configure uWSGI to host your Django project

Create a file named django.ini in the /etc/uwsgi/apps-enabled/ directory. The content of the file should be something like this:

[uwsgi]
chdir = /home/ubuntu/django_project # customize with your django installation directory
env = DJANGO_SETTINGS_MODULE=project.settings.production # customize with your settings module
wsgi-file = project/wsgi.py # customize with the relative path to your wsgi.py file
workers = 1

Restart uWSGI with:

service uwsgi restart

You should find the uWSGI logs in /var/log/uwsgi/apps/django.log. Therefore you can check them to see if the Python process started correctly or there are issues.

6. Configure NGINX to serve your application

Create a file named django in the /etc/nginx/sites-enabled/ directory. The content of the file should be something like this:

server {
    listen 80;
    server_name www.example.com; # customize with your domain name

    location / {
        # django running in uWSGI
        uwsgi_pass unix:///run/uwsgi/app/django/socket;
        include uwsgi_params;
        uwsgi_read_timeout 300s;
        client_max_body_size 32m;
    }

    location /static/ {
       # static files
       alias /home/ubuntu/static/; # ending slash is required
    }

    location /media/ {
        # media files, uploaded by users
        alias /home/ubuntu/media/; # ending slash is required
    }
}

Restart NGINX with:

service nginx restart

7. Enjoy your Django application

Point the browser to your domain, and you should see your Django application in all of its glory!

8. Extra step: automate all these steps with Ansible!

If you have to manage many different Django projects on many different servers, certainly you'll find that automating stuff is always a good idea.

Read my post on How to deploy a Django project in 15 minutes with Ansible to automate all the steps described here.

In conclusion, I hope that this post helped you with configuring Django - NGINX to deploy your Django project on a production server. Please let me know if you have questions leaving a comment in the area below or contacting me by email or social account.

The post Django - NGINX: deploy your Django project on a production server appeared first on guguweb.com.

13 Nov 2019 3:46pm GMT

11 Nov 2011

feedCI News

Reportula

What can you tell us about the team that built reportula.org?

The Team that made reportula.org is just one person. Pedro Oliveira, started Reportula when he needed a clean and fast web application that reported the Bacula Backups software of the company he works for. He has decided to open the project, and let it grow to full web application that is able to manage the Bacula Backups.

Reportula Website Screen Shot

What can you tell us about the site in general? What are the goals of the site and the main audience?

Reportula is a php based web program that provides you a summarized output of jobs that have already run. It obtains its information from the Bacula's database. Aside from a nice graphical display, it provides summaries of your jobs, as well as graphs of job usage. This is a fairly high level bacula management tool.

The main goals were to create a web reporting tool for the bacula backups system, as I got further into the project it developed into something more than that. Right know it calculates average of bacula backups, it has time line history of backups. Imagine this scenario for example, if you use the crontab feature of reportula, you can see in time by how much data your backups infrastructure is growing.

Example. in 2011.05.01 if backups infrastructure stores 500 Tera bytes, in 2011.12.30 it stores 510 terabytes. This is very handy for us because with this feature you can predict the storage needs of your backups for the future.

What was your major consideration in using CodeIgniter for this?

I chose codeigniter because I needed an easy, fast, and supported PHP development framework. I found that with Codeigniter I could achieve that. This project was made in less than month.

Another nice thing about Codeigniter is that you don't have to "re-invent the wheel". Codeigniter has most of the thing that you need for an application already developed. All you have to do is connect the blocks which is very easy.

What is next on the plate for reportula.org? Any additional functionality you can tell us about?

On the plate for Reportula is user registrations, acls, and managing Bacula Backups like "bconsole".

Do you have any other information you'd like to share with the community? Tips from this project you'd like to share? Lessons you've learned?

First of all i think that Codeigniter is one of the best frameworks on the internet. I've tried them all (Cake, Yii, Symfony, Zend) they are all too complicated, too big, with lots of features and slow. They all had one problem BIG, STEEP LEARNING CURVE.

Codeigniter has less features than the others but you start making an application in less than 30 minutes. And what it does it does well! Even if you think you need a big framework after starting with codeigniter it cames to you that you don't need another framework to develop some applications. The lessons I learned are don't re-invent the wheel, Codeigniter does it and does it well, the community are nice, and always had support on the forum.

11 Nov 2011 10:19pm GMT

10 Nov 2011

feedshare.ez.no > All forums (topics and replies)

Re: ezoe : Not found error in customTags popup

Hello Franck,

I'm sorry I have not yet encountered this problem before.

What version of eZ Pubish are you using?

What version of ezoe are you using?

If you have a set of reproducible instructions to recreate the issue using the latest community build available you may wish to consider filing an issue on http://issues.ez.no/ezoe

I hope this helps ...

Cheers,

Heath

10 Nov 2011 2:44am GMT

Re: Single login through different SiteAccess (using sub-domains)

Edit your site.ini like that :

[Session]
SessionNameHandler=custom
SessionNamePerSiteAccess=disabled

Set a common cookie_domain for all your sub domains! To do that you can edit your apache virtual_host and add that line into it :

php_value session.cookie_domain ".mysite.com"

Thanks Yannick, it was really useful, but I needed to isolate groups of siteaccess under the same domain, it's possible using site.ini / [Session] / SessionNamePrefix. You just have to set the same value for each siteaccess you want to share the session.

Example :

I have siteaccesses siteA, siteB, siteC, siteD and siteE. I want siteA, site B and siteC to share a session, and siteD and siteE to share another session.

In

[Session]
SessionNameHandler=custom
SessionNamePerSiteAccess=disabled
SessionNamePrefix=fooPrefix

In

[Session]
SessionNameHandler=custom
SessionNamePerSiteAccess=disabled
SessionNamePrefix=barPrefix

10 Nov 2011 2:14am GMT

Re: user ans rules

Hello Amine,

I took a few minutes and wrote a custom owsimpleoperator template operator function on your behalf.
When you use this you should be able to do so without touching the code.

This solution provides you a new custom template operator named 'member_of_role' which you would use like this ... (note this is a simple static example you will want to use dynamic values instead of course.

{def $userID=10
        $roleID=1
        $isMemberOfRole=$userID|member_of_role( $roleID )}
 
{if $isMemberOfRole}
 
Success! This userID {$userID} is a member of this roleID {$roleID} ...
 
{else}
 
Failure! This userID {$userID} is *not* a member of this roleID {$roleID} ...
 
{/if}

The custom 'member_of_role' operator accepts UserID and RoleID (Both required) and fetches the user, user roles, iterates over user roles and compares RoleID param till it finds a match and returns true, false if no match is found / etc.

This operator uses builtin / core eZ Publish PHP class methods for the very best in terms of reliability and stability.

share.ez.no is terrible to use when trying to paste pre formated (whitespace, no tabs, plain text) source code within the ezoe custom plugin input which has been written outside of ezoe and pasted in.

This off and on is a real problem with this site. It's no wonder so few folks post source code within the forums these days ... So I have posted my example solution source code in a pastebin instead, http://ezpublish.pastebin.ca/2093464

Please let me know how this solution works for you.

One final note: This code can also be called statically within custom PHP code without making any changes.

Here is an example PHP call of the function which powers the operator: ''

Please remember to clear cache and regenerate autoloads be for using this solution within eZ Publish!

I hope this helps ...

Cheers,

Heath

Edit: I found some extra time later in the evening and tested the operator in templates and it worked perfectly (as well as via PHP directly). Best wishes!

10 Nov 2011 1:34am GMT

09 Nov 2011

feedPlanet Zope.org

Updated MiniPlanet, now with meta-feed

My MiniPlanet Zope product has been working steady and stable for some years, when suddenly a user request came along. Would it be possible to get a feed of all the items in a miniplanet? With this update it became possible. MiniPlanet is an old-styl...

09 Nov 2011 9:41am GMT

07 Nov 2011

feedPlanet Zope.org

Welcome to Betabug Sirius

It has been quite some time that I announced_ that I'd be working as a freelancer. Lots of stuff had to be done in that time, but finally things are ready. I've founded my own little company and set up a small website: Welcome to Betabug Sirius!

07 Nov 2011 9:26am GMT

03 Nov 2011

feedPlanet Zope.org

Assertion helper for zope.testbrowser and unittest

zope.testbrowser is a valuable tool for integration tests. Historically, the Zope community used to write quite a lot of doctests, but we at gocept have found them to be rather clumsy and too often yielding neither good tests nor good documentation. That's why we don't use doctest much anymore, and prefer plain unittest.TestCases instead. However, doctest has one very nice feature, ellipsis matching, that is really helpful for checking HTML output, since you can only make assertions about the parts that interest you. For example, given this kind of page:

>>> print browser.contents
<html>
  <head>
    <title>Simple Page</title>
  </head>
  <body>
    <h1>Simple Page</h1>
  </body>
</html>

If all you're interested in is that the <h1> is rendered properly, you can simply say:

>>> print browser.contents
<...<h1>Simple Page</h1>...

We've now ported this functionality to unittest, as assertEllipsis, in gocept.testing. Some examples:

self.assertEllipsis('...bar...', 'foo bar qux')
# -> nothing happens

self.assertEllipsis('foo', 'bar')
# -> AssertionError: Differences (ndiff with -expected +actual):
     - foo
     + bar

self.assertNotEllipsis('foo', 'foo')
# -> AssertionError: "Value unexpectedly matches expression 'foo'."

To use it, inherit from gocept.testing.assertion.Ellipsis in addition to unittest.TestCase.


03 Nov 2011 7:19am GMT

02 Nov 2011

feedCI News

GoCart

Every week we hear of really awesome places that CodeIgniter is being used. I want to start sharing those with the community-at-large. I will start by posting them here under a new Showcase Category with the hopes that any future revisions of CI.com will have a section for stuff like this. You guys and gals make some really cool stuff and deserve a platform to show it off.

So without further ado…

This showcase is an interview with Kyle Roseborrough about GoCart

What can you tell us about the GoCart team?

We have a pair of PHP developers who knew there was a better way to build a shipping cart. Noah (lead developer) has 6 years experience in PHP development and 4 years in CodeIgniter. Gabe has about 10 years experience in web application development. Kyle has been working in UI and management for 10 years.
GoCart Website Screen Shot

What can we tell about the site in general?

GoCartdv.com was built to showcase GoCart and offer some basic information on the system.

What are the goals of the site and the main audience?

The main audience is CodeIgniter developers who are wanting a simple, scalable, CodeIgniter shopping cart. The goal is to get people involved in development to improve the cart and allow it to fully embody the goal of the project. To be easy to customize for developers and easy to use for end users/customers

What was your major consideration in using CodeIgniter for this?

CodeIgniter has great documentation and is easy to learn. We build lot of custom projects on CodeIgniter and it only made sense for us to build our cart on it. When looking for commerce solutions, we never found a suitable solution built on CodeIgniter so we decided to set out to do it on our own.

What is next on the plate for GoCart?

We really want GoCart to foster a great community of people contributing back to the roadmap and path the project will take. We want the focus to remain the same though "Easy to Customize, Easy to Use". It would be great if we could get enough people using.

Any additional functionality you can tell us about?

Well, not really. GoCart is intended to be a shopping cart, plain and simple. It does have some basic page and banner management and a whole slew of cart related features, but ultimately it's an ecommerce platform.

Do you have any other information you'd like to share with the community?

We built GoCart to be simple and scalable. As time goes on, we want the software to become easier and easier to use. We want GoCart to be scalable and to be able to work with new platforms as they come out. We feel that CodeIgniter and the CodeIgniter community is a huge benefit here. It enables developers to tie into a whole plethora of libraries, helpers and applications easily and support each other in the endeavor to make CodeIgniter better. Essentially, what's good for CodeIgniter is good for GoCart.

Tips from this project you'd like to share?

If you really want something, do it yourself. If it doesn't happen then you probably don't want it as bad as you think.

Lessons you've learned?

- Not every idea is a good one. Generally you need someone else around to discuss ideas and methods with. Collaboration is the best way to build a good application.
- No one knows what the next trend will be. Having a scalable platform that will adjust to a new set of tools and user demands is very important.


If you have a project that you would like to see in our showcase email me

02 Nov 2011 7:31pm GMT

01 Nov 2011

feedNews

eZ Systems takes over High-Tech Gruenderfonds

Successful exit for German IT technology and now one of the services offered by eZ Systems.

With the acquisition of the German high-technology start-up, YOOCHOOSE, the Norwegian company eZ Systems AS is expanding its content management system, eZ Publish Enterprise, with one of the world's leading recommendation engines. YOOCHOOSE was founded in 2009 by Dr. Uwe Alkemper and Michael Friedmann, and convinced High-Tech Gruenderfonds to provide seed financing at an early stage. Behind YOOCHOOSE - a spin-off company from Deutsche Telekom Laboratories in Berlin - lies a high-performance, patented recommendation system, which enables companies to significantly increase their revenues on the Internet using personalized recommendations.

01 Nov 2011 1:07pm GMT

26 Oct 2011

feedNews

eZ Delivers Analytics Optimizing Customer Experience

Through the acquisition of odoscope, eZ extends the powerful eZ Publish content management platform with behavior analysis optimizing the end-customer engagement.

26 Oct 2011 6:53am GMT

23 Oct 2011

feedPlanet TurboGears

Cliff Wells: FreeSWITCH on Scientific Linux 6.1

SL 6.1 (and I assume RHEL and CentOS 6.1 as well) has introduced an issue for building and running FreeSWITCH. Apparently a lot of stuff now relies on dynamically linking to libnss3. libnss3, in turn, depends on libnspr4.so, which depends on libplds4.so. Seemingly, this should not be an issue (stuff depends on chained shared objects all over the place), but somehow it is.

What happens is first you can't compile FreeSWITCH. You get complaints about unresolved symbols in /usr/lib64/libnss3.so. The solution is to run the following commands:

yum install nspr-devel
env LIBS="-lnss3 -lnspr4 -lplds4" ./configure
make && make install

This will get you a compiled version of FreeSWITCH. However, when you actually run it, you'll find that several modules won't load at runtime (including the ODBC driver, should you happen to be using it). The solution for this is similar. Assuming you are using an init script to launch FreeSWITCH, you can add the following line to the top of /etc/init.d/freeswitch:

export LD_PRELOAD="/usr/lib64/libnss3.so /usr/lib64/libnspr4.so /usr/lib64/libplds4.so"

Voila. Everything works. Hopefully the FreeSWITCH devs get on RHEL6 support soon, but meanwhile this should get you by.

23 Oct 2011 3:27pm GMT

20 Oct 2011

feedNews

New Cockpit Available for Better Productivity

eZ Content Cockpit is the latest extension from the eZ Market that offers a cohesive website overview to facilitate better editing and maintenance of dynamic content.

20 Oct 2011 7:43am GMT

18 Oct 2011

feedPlanet TurboGears

Michael Pedersen: Request For Ideas for Hiring Pond

So, a favor to ask of people: I'm working on a web application to help people manage their resumes. As I've gotten further in, I've realized I don't have an actual todo list for it. So, since I'm making this to be used by others, I'll ask everybody here:

What would you want to see? Currently, I've added enough code to allow the program to output something very close to my online resume ( http://www.icelus.org/ ). Next up, I have the following features on my todo list already:




What else would you all want to see in order to make you want to use this?

18 Oct 2011 8:44pm GMT

feedDevZone - Items tagged as: Zend Framework

Zend Framework 2.0.0beta1 Released!

The Zend Framework community is pleased to announce the immediate availability of Zend Framework 2.0.0beta1. Packages and installation instructions are available at: http://packages.zendframework.com/

18 Oct 2011 7:44am GMT

13 Oct 2011

feedshare.ez.no > Articles and Tutorials

Building native mobile applications with the eZ Publish REST API

eZ Publish is a Web Content Management System that provides a platform to publish content via any channel. Its powerful presentation engine enables you to create websites and pages that display your content in a variety of renderings. Its powerful API directly and simply integrates your content with any web-enabled application on any device, such as the iPad, iPhone, or an Android device, without ever interfering with, or impacting the platform itself.

At the end of this tutorial, you will have learnt the basics of mobile application development for both iOS and Android platforms, consuming content from eZ Publish. CMS-side adjustments for the mobile channel will be acquired too. This cheatsheet will help you leverage the multichannel capabilities of eZ Publish, and its REST API in future projects, in a more systematic fashion.

13 Oct 2011 2:21pm GMT

05 Oct 2011

feedCI News

New User Guide in Development

We are happy to announce today that the user guide has had some significant improvements, and the first commit of these changes were just pushed today.

As many of you likely heard at CICON 2011, the Reactor team has had an internal project going on for some time to move the user guide to Sphinx. In addition to handling the tedium of generating page and document tables of contents, or maintaining internal links and references, the documentation is now easier to write, as you can simply focus on the content instead of markup and presentation. Don't forget syntax highlighting of PHP, HTML, CSS, and JavaScript in code samples. Based on ReStructured Text, it's also more human readable in a text editor than HTML is, which is likely where you spend most of your time. As an added benefit, Sphinx can output HTML, PDF, and even EPUB formats all from the same source files. We will likely be taking advantage of that at a later date.

But we didn't stop there, we also enlisted the thunderous powers of EllisLab's Chief Creative Officer, James Mathias for a style redesign. They are clean, easy to read, and beautiful.

Setting up your dev environment to work with Sphinx (if you want to render and output locally) is very easy, and takes about five minutes. For those that want to geek out, we have added a readme file to the user guide source folder so the step by step instructions are available right from GitHub.

Today marks the first commit with the new user guide to the unreleased develop branch, so you may encounter some bumps. Most notably are the code blocks, which pandoc lost our line breaks on, and some navigation issues as we experiment with different table of contents presentation and depth. We'll be cleaning these up prior to the next release (much is as simple as some line breaks and tabs), but feel free to pitch in and submit some pull requests if you see anything out of whack.

And lastly, for the first time ever, we have live nightly builds of documentation for the develop branch available at the CodeIgniter web site. Enjoy!

05 Oct 2011 7:23pm GMT

04 Oct 2011

feedPlanet TurboGears

Alessandro Molina: TurboGears2 Performance Improvements

As recently some effort has been involved in improving the performances of TurboGears2, I was curious to see how much things improved. As usually, the test isn't really reliable in any way and was just for fun.

All the graphs report the request/sec the application has been able to perform on my computer with only 1 concurrent client. So higher is better.

Here is the comparison between TG2.0 and TG2dev (will be 2.1.4)

I also compared various setups with different template engines on TG2dev

The comparison happened on an application similar to the quickstarted one.
Actually as there is no database involved in this application the template engine impacts a lot and so was a good benchmark for the template engines themselves.

04 Oct 2011 3:35pm GMT

29 Sep 2011

feedDevZone - Items tagged as: Zend Framework

Zend Framework 1.11.11 Released

The Zend Framework team announces the immediate availability of Zend Framework's ALL ONES 1.11.11 release, the eleventh maintenance release in the 1.11 series. 1.11.11 includes around 30 bug fixes and may be downloaded from the Zend Framework site .

29 Sep 2011 7:52pm GMT

21 Sep 2011

feedDevZone - Items tagged as: Zend Framework

Announcing September's Zend Framework Bug Hunt Days

For those who haven't put the recurring event in their calendar, the Zend Framework Monthly Bug-hunt is here again! This Thursday, Friday and Saturday (the 22nd, 23rd and 24th of September), we'll be hosting our monthly bug hunt. For those of you unfamiliar with the event, each month, we organize the community to help reduce the number of open issues reported against the framework.

21 Sep 2011 3:07pm GMT

16 Aug 2011

feedshare.ez.no > Articles and Tutorials

Image Maps in ezwebin Banners

Beginners guide for learning how to use image maps in the ezwebin extension.

16 Aug 2011 12:40pm GMT

07 Jul 2011

feedshare.ez.no > Articles and Tutorials

Building mobile browser and hybrid applications with eZ Publish

eZ Publish is a Web Content Management System that provides a platform to publish content via any channel. Its powerful presentation engine enables you to create websites and pages that display your content in a variety of renderings. Its powerful API directly and simply integrates your content with any web-enabled application on any device, such as the iPad, iPhone, or an Android device, without ever interfering with, or impacting the platform itself.

At the end of this tutorial, you will have learnt the basics of mobile application development for both iOS and Android platforms, consuming content from eZ Publish. CMS-side adjustments for the mobile channel will be acquired too. This cheatsheet will help you leverage the multichannel capabilities of eZ Publish, and its REST API in future projects, in a more systematic fashion.

07 Jul 2011 1:29pm GMT

06 Apr 2011

feedcakebaker

Bash autocompletion for Git

One thing I often wished to have when using Git was the ability to autocomplete Git commands and branch names. As I had to learn this week from Markus Prinz' article A few of my Git tricks, tips and workflows, Git comes with an autocompletion script for the Bash shell. But to use the autocompletion, […]

06 Apr 2011 8:36am GMT

01 Apr 2011

feedcakebaker

Array iteration with JavaScript

Till recently I always used a for-loop when I had to iterate over an array in JavaScript. For example: var myArray = [1, 2, 3, 4]; for (var i = 0; i < myArray.length; i++) { console.log(myArray[i]); } However, with ECMAScript 5 the Array object itself got some methods for iteration purposes. With those methods […]

01 Apr 2011 2:51pm GMT

10 Jan 2011

feedcakebaker

2-legged vs. 3-legged OAuth

From emails I receive it seems like there is a bit of confusion about what the terms 2-legged OAuth and 3-legged OAuth mean. I hope I can clear up this confusion with this article (and don't contribute more to the confusion…). In short, they describe two different usage scenarios of OAuth involving two respectively three […]

10 Jan 2011 5:30pm GMT

04 Mar 2010

feedWithCake.com Companies Hiring

qpLogic Europe

We can use immediately an experienced Cake developer for assisting us with developing a multi-lingual application that needs some Jake/Joomla (css) integration. We have continuously Cake projects and prefer to work with a team of individual developers in multiple time zones. Please show me that you are experienced, affordable and have at least 24 hours available per week (40 is better ;-).

04 Mar 2010 11:54am GMT