FLOSS Project Planets

EuroPython: EuroPython 2019: Community Discounts

Planet Python - Tue, 2019-06-18 14:07

The EuroPython Society (EPS) does not only run the EuroPython conference, but also aims to provide help for the Python community in Europe in general.

Let’s all meet at EuroPython

In addition to the Python Organizers Lunch (see previous post), which focuses on conference organizers, we are also establishing a program to support attendees of Python user groups and conferences in Europe.

We’d like to invite all of you to EuroPython 2019 this year. Of course, we cannot give out free tickets to everyone, but we can at least recognize your participation in the Python community by giving out discounts for the conference.

Discounts for EuroPython Tickets

If you are running a Python event (conference or user group) in Europe, please reach out to board@europython.eu to request a coupon code for your group, which you can then pass on to your group members or attendees.

If you are not running a user group or conference, but a regular attendee of one, please contact your organizers to have them submit a request. We can only distribute codes at the user group and conference organizer level.

The coupon codes are valid for conference tickets bought starting today and will give you a 10% discount on the ticket price (both regular and late bird prices). The codes are setup for user group sizes of between 30-50 members, but we are also extending this to organizers and attendees of larger conferences. If you need a code valid for larger groups, please mention this in your email.

Enjoy,

EuroPython Society
https://ep2019.europython.eu/  
https://www.europython-society.org/

Categories: FLOSS Project Planets

EuroPython: EuroPython 2019: Inviting European Python Conference Organizers

Planet Python - Tue, 2019-06-18 14:07

As you may know, the EuroPython Society (EPS) has extended it’s mission to not only run the EuroPython conference, but also provide help for the Python community in Europe in general.

As part of this, we would like to get to know, and help create closer ties between organizers of other European Python events.

Organizers’ Lunch

We would like to invite representatives of all European Python conference to EuroPython 2019 to join us for an organizers’ lunch. We’re planing the lunch for Thursday or Friday. Details will be announced closer to the event.

Our aim is to get to know each other, exchange experience in organizing events and to find out how we, as EPS, can most effectively help other conferences going forward.

Free Tickets

To support and facilitate this, we are giving out one free conference ticket per conference team, so that each team can send a representative to the organizers’ lunch.

If your team wants to send someone to join, please write to board@europython.eu, mentioning the conference you’re organizing and some background on your team.

Enjoy,

EuroPython Society
https://ep2019.europython.eu/  
https://www.europython-society.org/

Categories: FLOSS Project Planets

Trey Hunner: Loop Better: a deeper look at iteration in Python

Planet Python - Tue, 2019-06-18 12:15

Python’s for loops don’t work the way for loops do in other languages. In this article we’re going to dive into Python’s for loops to take a look at how they work under the hood and why they work the way they do.

    Note: This article is based on my Loop Better talk. It was originally published on opensource.com.

    Looping Gotchas

    We’re going to start off our journey by taking a look at some “gotchas”. After we’ve learned how looping works in Python, we’ll take another look at these gotchas and explain what’s going on.

    Gotcha 1: Looping Twice

    Let’s say we have a list of numbers and a generator that will give us the squares of those numbers:

    1 2 >>> numbers = [1, 2, 3, 5, 7] >>> squares = (n**2 for n in numbers)

    We can pass our generator object to the tuple constructor to make a tuple out of it:

    1 2 >>> tuple(squares) (1, 4, 9, 25, 49)

    If we then take the same generator object and pass it to the sum function we might expect that we’d get the sum of these numbers, which would be 88.

    1 2 >>> sum(squares) 0

    Instead we get 0.

    Gotcha 2: Containment Checking

    Let’s take the same list of numbers and the same generator object:

    1 2 >>> numbers = [1, 2, 3, 5, 7] >>> squares = (n**2 for n in numbers)

    If we ask whether 9 is in our squares generator, Python will tell us that 9 is in squares. But if we ask the same question again, Python will tell us that 9 is not in squares.

    1 2 3 4 >>> 9 in squares True >>> 9 in squares False

    We asked the same question twice and Python gave us two different answers.

    Gotcha 3: Unpacking

    This dictionary has two key-value pairs:

    1 >>> counts = {'apples': 2, 'oranges': 1}

    Let’s unpack this dictionary using multiple assignment:

    1 >>> x, y = counts

    You might expect that when unpacking this dictionary, we’ll get key-value pairs or maybe that we’ll get an error.

    But unpacking dictionaries doesn’t raise errors and it doesn’t return key-value pairs. When you unpack dictionaries you get keys:

    1 2 >>> x 'apples'

    We’ll come back to these gotchas after we’ve learned a bit about the logic that powers these Python snippets.

    Review: Python’s for loop

    Python doesn’t have traditional for loops. To explain what I mean, let’s take a look at a for loop in another programming language.

    This is a traditional C-style for loop written in JavaScript:

    1 2 3 4 let numbers = [1, 2, 3, 5, 7]; for (let i = 0; i < numbers.length; i += 1) { print(numbers[i]) }

    JavaScript, C, C++, Java, PHP, and a whole bunch of other programming languages all have this kind of for loop. But Python doesn’t.

    Python does not have traditional C-style for loops. We do have something that we call a for loop in Python, but it works like a foreach loop.

    This is Python’s flavor of for loop:

    1 2 3 numbers = [1, 2, 3, 5, 7] for n in numbers: print(n)

    Unlike traditional C-style for loops, Python’s for loops don’t have index variables. There’s no index initializing, bounds checking, or index incrementing. Python’s for loops do all the work of looping over our numbers list for us.

    So while we do have for loops in Python, we do not have have traditional C-style for loops. The thing that we call a for loop works very differently.

    Definitions: Iterables and Sequences

    Now that we’ve addressed the index-free for loop in our Python room, let’s get some definitions out of the way now.

    An iterable is anything you can loop over with a for loop in Python. Iterables can be looped over and anything that can be looped over is an iterable.

    1 2 for item in some_iterable: print(item)

    Sequences are a very common type of iterable. Lists, tuples, and strings are all sequences.

    1 2 3 >>> numbers = [1, 2, 3, 5, 7] >>> coordinates = (4, 5, 7) >>> words = "hello there"

    Sequences are iterables which have a specific set of features. They can be indexed starting from 0 and ending at one less than the length of the sequence, they have a length, and they can be sliced. Lists, tuples, strings and all other sequences work this way.

    1 2 3 4 5 6 >>> numbers[0] 1 >>> coordinates[2] 7 >>> words[4] 'o'

    Lots of things in Python are iterables, but not all iterables are sequences. Sets, dictionaries, files, and generators are all iterables but none of these things are sequences.

    1 2 3 4 >>> my_set = {1, 2, 3} >>> my_dict = {'k1': 'v1', 'k2': 'v2'} >>> my_file = open('some_file.txt') >>> squares = (n**2 for n in my_set)

    So anything that can be looped over with a for loop is an iterable and sequences are one type of iterable but Python has many other kinds of iterables as well.

    Python’s for loops don’t use indexes

    You might think that under the hood, Python’s for loops use indexes to loop. Here we’re manually looping over an iterable using a while loop and indexes:

    1 2 3 4 5 numbers = [1, 2, 3, 5, 7] i = 0 while i < len(numbers): print(numbers[i]) i += 1

    This works for lists, but it won’t work everything. This way of looping only works for sequences.

    If we try to manually loop over a set using indexes, we’ll get an error:

    1 2 3 4 5 6 7 8 9 >>> fruits = {'lemon', 'apple', 'orange', 'watermelon'} >>> i = 0 >>> while i < len(fruits): ... print(fruits[i]) ... i += 1 ... Traceback (most recent call last): File "<stdin>", line 2, in <module> TypeError: 'set' object does not support indexing

    Sets are not sequences so they don’t support indexing.

    We cannot manually loop over every iterable in Python by using indexes. This simply won’t work for iterables that aren’t sequences.

    Iterators power for loops

    So we’ve seen that Python’s for loops must not be using indexes under the hood. Instead, Python’s for loops use iterators.

    Iterators are the things that power iterables. You can get an iterator from any iterable. And you can use an iterator to manually loop over the iterable it came from.

    Let’s take a look at how that works.

    Here are three iterables: a set, a tuple, and a string.

    1 2 3 >>> numbers = {1, 2, 3, 5, 7} >>> coordinates = (4, 5, 7) >>> words = "hello there"

    We can ask each of these iterables for an iterator using Python’s built-in iter function. Passing an iterable to the iter function will always give us back an iterator, no matter what type of iterable we’re working with.

    1 2 3 4 5 6 >>> iter(numbers) <set_iterator object at 0x7f2b9271c860> >>> iter(coordinates) <tuple_iterator object at 0x7f2b9271ce80> >>> iter(words) <str_iterator object at 0x7f2b9271c860>

    Once we have an iterator, the one thing we can do with it is get its next item by passing it to the built-in next function.

    1 2 3 4 5 6 >>> numbers = [1, 2, 3] >>> my_iterator = iter(numbers) >>> next(my_iterator) 1 >>> next(my_iterator) 2

    Iterators are stateful, meaning once you’ve consumed an item from them it’s gone.

    If you ask for the next item from an iterator and there are no more items, you’ll get a StopIteration exception:

    1 2 3 4 5 6 >>> next(iterator) 3 >>> next(iterator) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration

    So you can get an iterator from every iterable. And the only thing that you can do with iterators is ask them for their next item using the next function. And if you pass them to next but they don’t have a next item, a StopIteration exception will be raised.

    Hello Kitty PEZ dispenser photo by Deborah Austin / CC BY

    You can think of iterators as like Hello Kitty PEZ dispensers that cannot be reloaded. You can take PEZ out, but once a PEZ is removed it can’t be put back and once the dispenser is empty, it’s useless.

    Looping without a for loop

    Now that we’ve learned about iterators and the iter and next functions, we’re going to try manually looping over an iterable without using a for loop.

    We’ll do so by attempting to turn this for loop into a while loop:

    1 2 3 def funky_for_loop(iterable, action_to_do): for item in iterable: action_to_do(item)

    To do this we’ll:

    1. Get an iterator from the given iterable
    2. Repeatedly get the next item from the iterator
    3. Execute the body of the for loop if we successfully got the next item
    4. Stop our loop if we got a StopIteration exception while getting the next item
    1 2 3 4 5 6 7 8 9 10 def funky_for_loop(iterable, action_to_do): iterator = iter(iterable) done_looping = False while not done_looping: try: item = next(iterator) except StopIteration: done_looping = True else: action_to_do(item)

    We’ve just re-invented a for loop by using a while loop and iterators.

    The above code pretty much defines the way looping works under the hood in Python. If you understand the way the built-in iter and next functions work for looping over things, you understand how Python’s for loops work.

    In fact you’ll understand a little bit more than just how for loops work in Python. All forms of looping over iterables work this way.

    The iterator protocol is a fancy way of saying “how looping over iterables works in Python”. It’s essentially the definition of the way the iter and next functions work in Python. All forms of iteration in Python are powered by the iterator protocol.

    The iterator protocol is used by for loops (as we’ve already seen):

    1 2 for n in numbers: print(n)

    Multiple assignment also uses the iterator protocol:

    1 x, y, z = coordinates

    Star expressions use the iterator protocol:

    1 2 a, b, *rest = numbers print(*numbers)

    And many built-in functions rely on the iterator protocol:

    1 unique_numbers = set(numbers)

    Anything in Python that works with an iterable probably uses the iterator protocol in some way Any time you’re looping over an iterable in Python, you’re relying on the iterator protocol.

    Generators are iterators

    So you might be thinking: iterators seem cool, but they also just seem like an implementation detail and we might not need to care about them as users of Python.

    I have news for you: it’s very common to work directly with iterators in Python.

    The squares object here is a generator:

    1 2 >>> numbers = [1, 2, 3] >>> squares = (n**2 for n in numbers)

    And generators are iterators, meaning you can call next on a generator to get its next item:

    1 2 3 4 >>> next(squares) 1 >>> next(squares) 4

    But if you’ve ever used a generator before, you probably know that you can also loop over generators:

    1 2 3 4 5 6 7 >>> squares = (n**2 for n in numbers) >>> for n in squares: ... print(n) ... 1 4 9

    If you can loop over something in Python, it’s an iterable.

    So generators are iterators, but generators are also iterables. What’s going on here?

    I lied to you

    So when I explained how iterators worked earlier, I skipped over an important detail about them.

    Iterators are iterables.

    I’ll say that again: every iterator in Python is also an iterable, which means you can loop over iterators.

    Because iterators are also iterables, you can get an iterator from an iterator using the built-in iter function:

    1 2 3 >>> numbers = [1, 2, 3] >>> iterator1 = iter(numbers) >>> iterator2 = iter(iterator1)

    Remember that iterables give us iterators when we call iter on them.

    When we call iter on an iterator it will always give us itself back:

    1 2 >>> iterator1 is iterator2 True

    Iterators are iterables and all iterators are their own iterators.

    1 2 def is_iterator(iterable): return iter(iterable) is iterable

    Confused yet?

    Let’s recap these terms.

    An iterable is something you’re able to iterate over. An iterator is the agent that actually does the iterating over an iterable.

    Additionally, in Python iterators are also iterables and they act as their own iterators.

    So iterators are iterables, but they don’t have the variety of features that some iterables have.

    Iterators have no length and they can’t be indexed:

    1 2 3 4 5 6 >>> numbers = [1, 2, 3, 5, 7] >>> iterator = iter(numbers) >>> len(iterator) TypeError: object of type 'list_iterator' has no len() >>> iterator[0] TypeError: 'list_iterator' object is not subscriptable

    From our perspective as Python programmers, the only useful things you can do with an iterator are pass it to the built-in next function or loop over it:

    1 2 3 4 >>> next(iterator) 1 >>> list(iterator) [2, 3, 5, 7]

    And if we loop over an iterator a second time, we’ll get nothing back:

    1 2 >>> list(iterator) []

    You can think of iterators are lazy iterables that are single-use, meaning they can be looped over one time only.

    Object Iterable? Iterator? Iterable ✔️ ❓ Iterator ✔️ ✔️ Generator ✔️ ✔️ List ✔️ ❌

    As you can see in the truth table above, iterables are not always iterators but iterators are always iterables:

    The iterator protocol, in full

    Let’s define how iterators work from Python’s perspective.

    Iterables can be passed to the iter function to get an iterator for them.

    Iterators:

    1. Can be passed to the next function which will give their next item or raise a StopIteration exception if there are no more items
    2. Can be passed to the iter function and will return themselves back

    The inverse of these statements also hold true:

    1. Anything that can be passed to iter without a TypeError is an iterable
    2. Anything that can be passed to next without a TypeError is an iterator
    3. Anything that returns itself when passed to iter is an iterator

    That’s the iterator protocol in Python.

    Iterators enable laziness

    Iterators allow us to both work with and create lazy iterables that don’t do any work until we ask them for their next item. Because we can create lazy iterables, we can make infinitely long iterables. And we can create iterables that are conservative with system resources, that can save us memory and can save us CPU time.

    Iterators are everywhere

    You’ve already seen lots of iterators in Python. I’ve already mentioned that generators are iterators. Many of Python’s built-in classes are iterators also. For example Python’s enumerate and reversed objects are iterators.

    1 2 3 4 5 6 >>> letters = ['a', 'b', 'c'] >>> e = enumerate(letters) >>> e <enumerate object at 0x7f112b0e6510> >>> next(e) (0, 'a')

    In Python 3, zip, map, and filter objects are iterators too.

    1 2 3 4 5 6 7 >>> numbers = [1, 2, 3, 5, 7] >>> letters = ['a', 'b', 'c'] >>> z = zip(numbers, letters) >>> z <zip object at 0x7f112cc6ce48> >>> next(z) (1, 'a')

    And file objects in Python are iterators also.

    1 2 >>> next(open('hello.txt')) 'hello world\n'

    There are lots of iterators bult-in to Python, in the standard library, and in third-party Python libraries. These iterators all act like lazy iterables by delaying work until the moment you ask them for their next item.

    Creating your own iterator

    It’s useful to know that you’re already using iterators, but I’d like you to also know that you can create your own iterators and your own lazy iterables.

    This class makes an iterator that accepts an iterable of numbers and provides squares of each of the numbers as it’s looped over.

    1 2 3 4 5 6 7 class square_all: def __init__(self, numbers): self.numbers = iter(numbers) def __next__(self): return next(self.numbers) ** 2 def __iter__(self): return self

    But no work will be done until we start looping over an instance of this class.

    Here we have an infinitely long iterable count and you can see that square_all accepts count without fully looping over this infinitely long iterable:

    1 2 3 4 5 6 7 >>> from itertools import count >>> numbers = count(5) >>> squares = square_all(numbers) >>> next(squares) 25 >>> next(squares) 36

    This iterator class works, but we don’t usually make iterators this way. Usually when we want to make a custom iterator, we make a generator function:

    1 2 3 def square_all(numbers): for n in numbers: yield n**2

    This generator function is equivalent to the class we made above and it works essentially the same way.

    That yield statement probably seem magical, but it is very powerful: yield allows us to put our generator function on pause between calls from the next function. The yield statement is the thing that separates generator functions from regular functions.

    Another way we could implement this same iterator is with a generator expression.

    1 2 def square_all(numbers): return (n**2 for n in numbers)

    This does the same thing as our generator function but it uses a syntax that looks like a list comprehension. If you need to make a lazy iterable in your code, think of iterators and consider making a generator function or a generator expression.

    How iterators can improve your code

    Once you’ve embraced the idea of using lazy iterables in your code, you’ll find that there are lots of possibilities for discovering or creating helper functions that assist you in looping over iterables and processing data.

    Laziness and summing

    This is a for loop that sums up all billable hours in a Django queryset:

    1 2 3 4 hours_worked = 0 for event in events: if event.is_billable(): hours_worked += event.duration

    Here is code that does the same thing using a generator expression for lazy evaluation:

    1 2 3 4 5 6 7 billable_times = ( event.duration for event in events if event.is_billable() ) hours_worked = sum(billable_times)

    Notice that the shape of our code has changed dramatically.

    Turning our billable times into a lazy iterable has allowed us to name something (billable_times) that was previously unnamed. This has also allowed us to use the sum function. We couldn’t have used sum before because we didn’t even have an iterable to pass to it. Iterators allow you to fundamentally change the way you structure your code.

    Laziness and breaking out of loops

    This code prints out the first ten lines of a log file:

    1 2 3 4 for i, line in enumerate(log_file): if i >= 10: break print(line)

    This code does the same thing, but we’re using the itertools.islice function to lazily grab the first 10 lines of our file as we loop:

    1 2 3 4 5 from itertools import islice first_ten_lines = islice(log_file, 10) for line in first_ten_lines: print(line)

    The first_ten_lines variable we’ve made is an iterator. Again using an iterator allowed us to give a name to something (first ten lines) that was previously unnamed. Naming things can make our code more descriptive and more readable.

    As a bonus we also removed the need for a break statement in our loop because the islice utility handles the breaking for us.

    You can find many more iteration helper functions in itertools in the standard library as well as in third-party libraries such as boltons and more-itertools.

    Creating your own iteration helpers

    You can find helper functions for looping in the standard library and in third-party libraries, but you can also make your own!

    This code makes a list of the differences between consecutive values in a sequence.

    1 2 3 4 current = readings[0] for next_item in readings[1:]: differences.append(next_item - current) current = next_item

    Notice that this code has an extra variable that we need to assign each time we loop. Also note that this code only works with things we can slice, like sequences. If readings were a generator, a zip object, or any other type of iterator this code would fail.

    Let’s write a helper function to fix our code.

    This is a generator function that gives us the current item and the item following it for every item in a given iterable:

    1 2 3 4 5 6 7 def with_next(iterable): """Yield (current, next_item) tuples for each item in iterable.""" iterator = iter(iterable) current = next(iterator) for next_item in iterator: yield current, next_item current = next_item

    We’re manually getting an iterator from our iterable, calling next on it to grab the first item, and then looping over our iterator to get all subsequent items, keeping track of our last item along the way. This function works not just with sequences, but with any type of iterable

    This is the same code but we’re using our helper function instead of manually keeping track of next_item:

    1 2 3 differences = [] for current, next_item in with_next(readings): differences.append(next_item - current)

    Notice that this code doesn’t have awkward assignments to next_item hanging around our loop. The with_previous generator function handles the work of keeping track of next_item for us.

    Also note that this code has been compacted enough that we could even copy-paste our way into a list comprehension if we wanted to.

    1 2 3 4 differences = [ (next_item - current) for current, next_item in with_next(readings) ] Looping Gotchas: Revisited

    At this point we’re ready to jump back to those odd examples we saw earlier and try to figure out what was going on.

    Gotcha 1: Exhausting an Iterator

    Here we have a generator object, squares:

    1 2 >>> numbers = [1, 2, 3, 5, 7] >>> squares = (n**2 for n in numbers)

    If we pass this generator to the tuple constructor, we’ll get a tuple of its items back:

    1 2 3 4 >>> numbers = [1, 2, 3, 5, 7] >>> squares = (n**2 for n in numbers) >>> tuple(squares) (1, 4, 9, 25, 49)

    If we then try to compute the sum of the numbers in this generator, we’ll get 0:

    1 2 >>> sum(squares) 0

    This generator is now empty: we’ve exhausted it. If we try to make a tuple out of it again, we’ll get an empty tuple:

    1 2 >>> tuple(squares) ()

    Generators are iterators. And iterators are single-use iterables. They’re like Hello Kitty PEZ dispensers that cannot be reloaded.

    Gotcha 2: Partially-Consuming an Iterator

    Again we have a generator object, squares:

    1 2 >>> numbers = [1, 2, 3, 5, 7] >>> squares = (n**2 for n in numbers)

    If we ask whether 9 is in this squares generator, we’ll get True:

    1 2 >>> 9 in squares True

    But if we ask the same question again, we’ll get False:

    1 2 >>> 9 in squares False

    When we ask whether 9 is in this generator, Python has to loop over this generator to find 9. If we kept looping over it after checking for 9, we’ll only get the last two numbers because we’ve already consumed the numbers before this point:

    1 2 3 4 5 6 >>> numbers = [1, 2, 3, 5, 7] >>> squares = (n**2 for n in numbers) >>> 9 in squares True >>> list(squares) [25, 49]

    Asking whether something is contained in an iterator will partially consume the iterator. There is no way to know whether something is in an iterator without starting to loop over it.

    Gotcha 3: Unpacking is iteration

    When you loop over dictionaries you get keys:

    1 2 3 4 5 6 >>> counts = {'apples': 2, 'oranges': 1} >>> for key in counts: ... print(key) ... apples oranges

    You also get keys when you unpack a dictionary:

    1 2 3 >>> x, y = counts >>> x, y ('apples', 'oranges')

    Looping relies on the iterator protocol. Iterable unpacking also relies on the iterator protocol. Unpacking a dictionary is really the same as looping over the dictionary. Both use the iterator protocol, so you get the same result in both cases.

    Recap and related resources

    Sequences are iterables, but not all iterables are sequences. When someone says the word “iterable” you can only assume they mean “something that you can iterate over”. Don’t assume iterables can be looped over twice, asked for their length, or indexed.

    Iterators are the most rudimentary form of iterables in Python. If you’d like to make a lazy iterable in your code think of iterators and consider making a generator function or a generator expression.

    And finally, remember that every type of iteration in Python relies on the iterator protocol so understanding the iterator protocol is the key to understanding quite a bit about looping in Python in general.

    Here are some related articles and videos I recommend:

    Categories: FLOSS Project Planets

    Nonprofit Drupal posts: June Drupal for Nonprofits Chat

    Planet Drupal - Tue, 2019-06-18 11:32

    Our normally scheduled call to chat about all things Drupal and nonprofits will happen this Thursday, June 20, at 1pm ET / 10am PT. (Convert to your local time zone.)

    Feel free to share your thoughts and discussion points ahead of time in our collaborative Google doc: https://nten.org/drupal/notes

    We have an hour to chat so bring your best Drupal topics and let's do this thing!

    Some examples to get your mind firing: how do I recreate [feature] on my Drupal 7 site in Drupal 8? I need to explain [complicated thing] to a non-technical stakeholder -- any advice? How can I get Drupal and my CRM to play nicely?

    This free call is sponsored by NTEN.org but open to everyone.

    View notes of previous months' calls.

    Categories: FLOSS Project Planets

    Catalin George Festila: Python 3.7.3 : Stemming with nltk.

    Planet Python - Tue, 2019-06-18 10:16
    Today I will start another tutorial about nltk python module and stemming. The stemming is the process of producing morphological variants of a root/base word. Stemming programs are commonly referred to as stemming algorithms or stemmers to reduces the words. Errors in Stemming can be overstemming and understemming. These two words are stemmed to the same root that are of different stems then the
    Categories: FLOSS Project Planets

    Real Python: How to Publish Your Own Python Package to PyPI

    Planet Python - Tue, 2019-06-18 10:00

    Learn how to create a Python package for your project and how to publish it to PyPI, the Python Package Repository with this step-by-step course. Quickly get up to speed on everything from naming your package to configuring it using setup.py.

    [ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

    Categories: FLOSS Project Planets

    Reuven Lerner: Understanding Python assignment

    Planet Python - Tue, 2019-06-18 09:36

    Here’s a quick question I often ask students in my Python classes:

    >>> x = 100 >>> y = x >>> x = 200

    After executing the above code, what is the value of y?

    The answer:

    >>> print(y)
    100

    Many of my students, especially those with a background in C, are surprised. Didn’t we say that “y = x”? Thus, shouldn’t a change in x be reflected by a similar change in y?

    Obviously not. But why is this the case?

    Assignment in Python means one thing, and one thing only: The variable named on the left should now refer to the value on the right.

    In other words, when I said:

    y = x

    Python doesn’t read this as, “y should now refer to the variable x.” Rather, it read it as, “y should now refer to whatever value x refers to.”

    Because x refers to the integer 100, y now refers to the integer 100. After these two assignments (“x = 100” and “y = x”), there are now two references to the integer 100 that didn’t previously exist.

    When we say that “x = 200”, we’re removing one of those references, such that x no longer refers to 100. Instead, x will now refer to the integer 200.

    But y’s reference remains in place to where it was originally pointing, to 100. And indeed, the only way to change what y is referring to is via … assignment.

    Think of this as assignment inertia: Without a new and explicit assignment, a variable will continue to refer to whatever it referred to previously.

    Thus, while Python does have references (i.e., variables pointing to objects), it doesn’t have pointers (i.e., variables pointing to other variables). That’s a big difference, and one that makes the language easier to understand. But references can still be a bit tricky and confusing, especially for newcomers to the language.

    Remember also that in an assignment, the right side is evaluated before the left side. By the time the left-hand-side is being assigned, any variables on the right-hand-side are long gone, replaced by the final value of the expression. For example:

    >>> a = 10 >>> b = 20 >>> c = 30 >>> d = a + b * c

    When we assign a value to the variable “d” above, it’s only after Python has evaluated “a + b * c”. The variables are replaced by the values to which they refer, the operations are evaluated, and the final result (610) is then assigned to “d”. “d” has no idea that it was ever getting a value from “a”, “b”, or “c”.

    The post Understanding Python assignment appeared first on Reuven Lerner.

    Categories: FLOSS Project Planets

    Catalin George Festila: Python 3.7.3 : Using getters and setters in object-oriented.

    Planet Python - Tue, 2019-06-18 09:29
    The main purpose of using getters and setters in object-oriented programs is to ensure data encapsulation. Let's start with a simple example. I created a class named my_class init with one variable named my_variable: self._my_variable = my_variableA new, initialized instance can be obtained by this line of code: test_it = my_class()The example use getter and setter methods to use this variable. C
    Categories: FLOSS Project Planets

    ComputerMinds.co.uk: 10 Interesting Drupal Modules

    Planet Drupal - Tue, 2019-06-18 09:07

    Drupal is lucky to benefit from a very active community of developers meaning that there is a wide and varied range of contributed modules to extend the functionality of Drupal core. In this article we’ll take a quick look at 10 interesting contributed modules; some are well known whilst others are a little bit more obscure.

    1. Admin_menu (D7) / Admin_toolbar (D8)

    Out of the box the Drupal admin interface can be a bit unwieldy and whilst this has been significantly improved over the years, especially with the advent of Drupal 8, there’s still room for improvement. Enter admin_menu/admin_toolbar which are two similar modules to make navigating the admin interface a whole lot easier by providing a neat little toolbar with drop downs so you can navigate the whole admin interface from any page of your site.

    2. Kraken

    This module allows you to use the kraken.io web service to optimise images on your website. It works be exposing a kraken optimise image style effect which can be applied to image styles on your Drupal website.

    3. Popup_field_group

    This is a nice little module maintained by ComputerMinds which gives the option to display the children of a field group in a popup overlay. Buttons are exposed to toggle the popup.

    4. Flood_unblock

    Drupal 7 introduced a feature to prevent brute force attacks meaning that no more than five failed login attempts per user in any six hour period or no more than 50 failed attempts from an IP address in a one hour period are allowed. Failed login attempts are recorded in the flood table and this module gives administrators an easy way to unblock users that have exceeded these limits.

    5. Paragraphs

    Paragraphs give much greater control over content creation on your Drupal site. A paragraph is a set of fields which has its own theme associated with it to give much greater flexibility over how content gets rendered on your site. So for example you might have a paragraph which floats an image left and displays text on the right - the possibilities are endless. Take a look at tiles in action to find out more about working with paragraphs (we use the term tiles to mean the same thing!)

    6. Stage_file_proxy

    This module is useful when working on a development version of your Drupal site by providing a proxy to the production site’s files directory. When you need a production file the module maps this the production files directory and downloads it to your development files directory.

    7. Field_display_label

    This is a nice little module to allow you to change a field label on the edit form so that it’s difference to what’s rendered when the field is displayed. So for example you might have a name field labelled ‘what’s your name?’ on the edit form which just renders ‘name’ when it’s displayed.

    8. Custom_add_another

    Another simple module maintained by ComputerMinds which gives site admins the ability to customise the ‘add another’ text for multi valued fields.

    9. Notice_killer

    This is a nice little module that will split out PHP notices and warnings from other Drupal notices and also logs a bit more information about each so that you can track them down and fix them more easily.

    10. Rabbit_hole

    This is a useful module that prevents certain entities from being viewable on their own page. So for example if you have an image content type which you never want to be accessible on node/xx then this is the module for you!

    Categories: FLOSS Project Planets

    Digital Atelier: now also in Russian

    Planet KDE - Tue, 2019-06-18 07:28

    Thanks to the hard work of Maria Malakhova (https://vk.com/owly.owlet) and Ramon Miranda (https://www.ramonmiranda.com/), Digital Atelier is now also available spoken in Russian!And the Russian version is, just like the English version, only €19,95 this month!

    Get Digital Atelier

    Not only does this contain over fifty new brush presets, more than thirty new brush tips and twenty patterns and surfaces.

    There is almost two hours of in-depth video tutorial, working you through the process of creating new brush presets.

     

    Categories: FLOSS Project Planets

    Dirk Eddelbuettel: anytime 0.3.4

    Planet Debian - Tue, 2019-06-18 07:28

    A new minor release of the anytime package is arriving on CRAN. This is the fifteenth release, and first since the 0.3.3 release in November.

    anytime is a very focused package aiming to do just one thing really well: to convert anything in integer, numeric, character, factor, ordered, … format to either POSIXct or Date objects – and to do so without requiring a format string. See the anytime page, or the GitHub README.md for a few examples.

    This release is mostly internal and switches to the excellent new tinytest package, a tweak the iso8601() format helper which now uses T between date and time (which is a breaking change with the usual addition of a option to get the old behaviour back) and a little more. The full list of changes follows.

    Changes in anytime version 0.3.4 (2019-06-18)
    • Documentation was updated about a 'Europe/London' conversion issue (#84, inter alia).

    • The package is now compiled under the C++11 standard.

    • The package now uses tinytest for unit tests.

    • The iso8601() function now places a ‘T’ between date and time; an option switches to prior format using a space.

    • The vignette is now pre-made and included as-is in a Sweave document reducing the number of suggested packages.

    Courtesy of CRANberries, there is a comparison to the previous release. More information is on the anytime page. The issue tracker tracker off the GitHub repo can be use for questions and comments.

    This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. Please report excessive re-aggregation in third-party for-profit settings.

    Categories: FLOSS Project Planets

    Python Software Foundation: PyPI Now Supports Two-Factor Login via WebAuthn

    Planet Python - Tue, 2019-06-18 07:16
    To further increase the security of Python package downloads, we're adding a new beta feature to the Python Package Index: WebAuthn support for U2F compatible hardware security keys as a two-factor authentication (2FA) login security method. This is thanks to a grant from the Open Technology Fund, coordinated by the Packaging Working Group of the Python Software Foundation.

    Last month, we added the first 2FA method for users logging into the canonical Python Package Index at PyPI.org and the test site at test.pypi.org. Hundreds of project owners and maintainers have now started using that method (generating a code through a Time-based One-time Password (TOTP) application) to better secure their accounts.

    Starting today, PyPI also supports (in beta) WebAuthn (U2F compatible) security keys for a second login factor. A security key (also known as a universal second factor, or U2F compatible key) is hardware device that communicates via USB, NFC, or Bluetooth. Popular keys include Yubikey, Google Titan and Thetis. PyPI supports any FIDO U2F compatible key and follows the WebAuthn standard. Users who have set up this second factor will be prompted to use their key (usually by inserting it into a USB port and pressing a button) when logging in. (This feature requires JavaScript.)

    This is a beta feature and we expect that users will find minor issues over the next few weeks; we ask for your bug reports. If you find any potential security vulnerabilities, please follow our published security policy. (Please don't report security issues in Warehouse via GitHub, IRC, or mailing lists. Instead, please directly email one or more of our maintainers.) If you find an issue that is not a security vulnerability, please report it via GitHub.

    We encourage project maintainers and owners to log in and go to your Account Settings to add a second factor. This will help improve the security of your PyPI user accounts, and thus reduce the risk of vandals, spammers, and thieves gaining account access. If you're not yet comfortable using a beta feature, you can provision a TOTP application for your second factor.

    You'll need to verify your primary email address on your Test PyPI and/or PyPI accounts before setting up 2FA. You can also do that in your Account Settings.

    2FA only affects login via the website, which safeguards against malicious changes to project ownership, deletion of old releases, and account takeovers. Package uploads will continue to work without users providing 2FA codes.

    But that's just for now. We are working on implementing per-user API keys as an alternative form of multifactor authentication in the setuptools/twine/PyPI auth flows. These will be application-specific tokens scoped to individual users/projects, so that users will be able to use token-based logins to better secure uploads. And we'll move on to working on an advanced audit trail of sensitive user actions, plus improvements to accessibility and localization for PyPI. More details are in our progress reports.

    Thanks to the Open Technology Fund for funding this work. And please sign up for the PyPI Announcement Mailing List for future updates.
    Categories: FLOSS Project Planets

    Python Insider: PyPI Now Supports Two-Factor Login via WebAuthn

    Planet Python - Tue, 2019-06-18 07:16
    To further increase the security of Python package downloads, we're adding a new beta feature to the Python Package Index: WebAuthn support for U2F compatible hardware security keys as a two-factor authentication (2FA) login security method. This is thanks to a grant from the Open Technology Fund, coordinated by the Packaging Working Group of the Python Software Foundation.

    Last month, we added the first 2FA method for users logging into the canonical Python Package Index at PyPI.org and the test site at test.pypi.org. Hundreds of project owners and maintainers have now started using that method (generating a code through a Time-based One-time Password (TOTP) application) to better secure their accounts.

    Starting today, PyPI also supports (in beta) WebAuthn (U2F compatible) security keys for a second login factor. A security key (also known as a universal second factor, or U2F compatible key) is hardware device that communicates via USB, NFC, or Bluetooth. Popular keys include Yubikey, Google Titan and Thetis. PyPI supports any FIDO U2F compatible key and follows the WebAuthn standard. Users who have set up this second factor will be prompted to use their key (usually by inserting it into a USB port and pressing a button) when logging in. (This feature requires JavaScript.)

    This is a beta feature and we expect that users will find minor issues over the next few weeks; we ask for your bug reports. If you find any potential security vulnerabilities, please follow our published security policy. (Please don't report security issues in Warehouse via GitHub, IRC, or mailing lists. Instead, please directly email one or more of our maintainers.) If you find an issue that is not a security vulnerability, please report it via GitHub.

    We encourage project maintainers and owners to log in and go to your Account Settings to add a second factor. This will help improve the security of your PyPI user accounts, and thus reduce the risk of vandals, spammers, and thieves gaining account access. If you're not yet comfortable using a beta feature, you can provision a TOTP application for your second factor.

    You'll need to verify your primary email address on your Test PyPI and/or PyPI accounts before setting up 2FA. You can also do that in your Account Settings.

    2FA only affects login via the website, which safeguards against malicious changes to project ownership, deletion of old releases, and account takeovers. Package uploads will continue to work without users providing 2FA codes.

    But that's just for now. We are working on implementing per-user API keys as an alternative form of multifactor authentication in the setuptools/twine/PyPI auth flows. These will be application-specific tokens scoped to individual users/projects, so that users will be able to use token-based logins to better secure uploads. And we'll move on to working on an advanced audit trail of sensitive user actions, plus improvements to accessibility and localization for PyPI. More details are in our progress reports.

    Thanks to the Open Technology Fund for funding this work. And please sign up for the PyPI Announcement Mailing List for future updates.
    Categories: FLOSS Project Planets

    Dries Buytaert: Web personalization made simple: announcing the all-new Acquia Lift

    Planet Drupal - Tue, 2019-06-18 06:15

    Today, we released a new version of Acquia Lift, our web personalization tool.

    In today's world, personalization has become central to the most successful customer experiences. Most organizations know that personalization is no longer optional, but have put it off because it can be too difficult. The new Acquia Lift solves that problem.

    While before, Acquia Lift may have taken a degree of fine-tuning from a developer, the new version simplifies how marketers create and launch website personalization. With the new version, anyone can point, click and personalize content without any code.

    We started working on the new version of Acquia Lift in early 2018, well over a year ago. In the process we interviewed over 50 customers, redesigned the user interface and workflows, and added various new capabilities to make it easier for marketers to run website personalization campaigns. And today, at our European customer conference, Acquia Engage London, we released the new Acquia Lift to the public.

    You can see all of the new features in action in this 5-minute Acquia Lift demo video:

    The new Acquia Lift offers the best web personalization solution in Acquia's history, and definitely the best tool for Drupal.

    Categories: FLOSS Project Planets

    FSF Events: Richard Stallman - "Are we facing surveillance like in China?" (Frankurt, Germany)

    GNU Planet! - Tue, 2019-06-18 04:12

    This speech by Richard Stallman will be nontechnical, admission is gratis, and the public is encouraged to attend.

    Location: Festsaal, Casino (#7), Campus Westend, Johann Wolfgang Goethe-Universität Frankfurt am Main, Grßneburgplatz 1, 60323 Frankfurt

    Please fill out our contact form, so that we can contact you about future events in and around Frankfurt.

    Categories: FLOSS Project Planets

    Agiledrop.com Blog: Interview with Mario Hernandez of Mediacurrent: Contributing to Drupal through workshops and training

    Planet Drupal - Tue, 2019-06-18 02:45

    Meet Mario Hernandez, Senior Frontend Developer at Mediacurrent. With over 10 years of experience in Drupal, Mario has seen the CMS evolve significantly throughout the years. Find out more about some of Mediacurrent's most interesting projects and what aspect of his work Mario enjoys the most.

    READ MORE
    Categories: FLOSS Project Planets

    Konsole and Wayland

    Planet KDE - Mon, 2019-06-17 20:00

    Wayland needs a different mindset when you are programming, you cannot just assume things works the same way as in as X11. One of my first patches to konsole was the rewrite of the Tab Bar, and a different way to deal with Drag & Drop of the tabs. In my mind - and how wrong I was - I could assume that I was dragging to a konsole main window by querying the widget below the mouse. Nope, this will not work. As Wayland has security by default, it will not give you anything global. What if I was a spy app trying to record another one to send to NSA? Security in Wayland is much stricter, and because of that I had to redo my drag & drop patch.

    Konsole should work now with drag & drop of tabs in Wayland, as soon as the patch hits master. I also have other patches waiting that will make the wayland transition smoother, I’ll write about them in due time.

    Categories: FLOSS Project Planets

    Steinar H. Gunderson: 0 bytes left

    Planet Debian - Mon, 2019-06-17 18:45

    Around 2003–2004, a friend and I wrote a softsynth that was used in a 64 kB intro. Now, 14 years later, cTrix and Pselodux picked it up and made a really cool 32 kB tune with it! Who would have thought.

    (For the record, the synth plus the original Nemesis tune fit under 16 kB given the right packer and some squeezing, even with some LPC samples. But there's heck of a lot more notes in this one :-) )

    Categories: FLOSS Project Planets

    Mediacurrent: Introducing Open Waters - A New Podcast for Strategic Marketing with Open Source

    Planet Drupal - Mon, 2019-06-17 18:33

    ​Mediacurrent is proud to announce the launch of our new podcast with the release of our pilot episode. Open Waters is a podcast exploring the intersection of open source technology and digital marketing. It’s made especially for CMO's, Directors and Managers of Marketing, technology, and digital strategy.

    Our Purpose

    We think open source is an ocean of opportunity to maximize your martech investment. 

    We encourage you to listen and learn about using open source technology and forward thinking marketing strategy to generate and convert leads, improve security, increase speed to market, and identify the ROI of your digital investments. Our goal is to educate about the challenges and solutions we see with our own clients and in the market.

    Welcome to Open Waters - Episode 0 

    Dive in to our pilot episode!



    Audio Download Link

    In this episode:

    • New format, shorter but more frequent episode release schedule.
    • We're taking a different direction from our Mediacurrent Dropcast, no longer focused strictly on Drupal. Instead, we will be talking about the business benefits of open source software.
    • We are going to change up some sections. A little less news, and more about solutions.
    • We will probably still do the Pro Project pick from our Dropcast
       

    Upcoming Episodes:

    •  Ben Robertson, who presented at the GatsbyJS Days conference in December, will join us to talk about the benefits of Gatsby JS.
    • Mario Hernandez will be on the podcast to talk about our upcoming expanded training for components. 
    • We’ll have an episode to talk about how to choose a CMS, whether it’s Drupal, WordPress, or any of the other bazillion options.
    • Bob Kepford, you may have heard of him, will be on to talk about serverless 101 and the problems it can solve.
    • We will have Jason Lengstorf from Gatsby on to talk about the project.
    • And much, much more.
    Subscribe to Open Waters 

    New episodes will be released tri-weekly on Tuesdays.

    How Can I Support the Show?

    Subscribe, leave a review, and share about us on social media with the hashtag #openwaterspodcast. Have an idea for a topic? Tweet at our hosts Mark Casias, Bob Kepford, and Mario Hernandez. Be sure to subscribe in your favorite podcast platform. Links to follow.

    Categories: FLOSS Project Planets

    Zato Blog: Zato 3.1 Released - Open-Source Python-based API Integrations and Backend Application Server

    Planet Python - Mon, 2019-06-17 18:01

    The newest version of Zato, the open-source Python-based enterprise API integrations platform and backend application server, is out with a lot of interesting features, changes and additions

    The full changelog is here and below is a summary of what is new in 3.1:

    • Greatly enhanced support for Docker, including Quickstart, Swarm and Kubernetes
    • Python 3 is now fully supported in addition to Python 2.7
    • New connectors and adapters: MongoDB, LDAP (Active Directory), Apache Kafka, SFTP, Slack, Telegram and JSON-RPC
    • Extensions to Single Sign-On: two-factor authentication and multi-credentials accounts
    • Rate-limiting and IP white-listing, including hierarchical definitions
    • Extensions to WebSockets: outgoing connections and broadcasts
    • A range of security enhancements, including TOTP two-factor authentication in web-admin
    • General performance boosts - both run-time and server startup
    What is Zato?

    Zato is an open-source API integrations platform and backend application server composed of several major blocks of functionality:

    • Online request/response integrations using a wide range of protocols, including SAP, Odoo, IBM MQ, REST, AMQP, Search, Email and many more

    • Publish/subscribe message topics with queues and guaranteed delivery

    • Single Sign-On for REST and Python applications

    Its HA architecture is highly-scalable and everything comes with a web-based GUI along with a command-line interface and admin APIs.

    If you are looking for a highly productive Python-based open-source platform designed specifically to integrate systems or expose APIs in many protocols or data formats, to be used by other servers, frontends or mobile, Zato is the choice.

    Quick links:
    Categories: FLOSS Project Planets

    Pages