| Author: | A.M. Kuchling |
|---|
This article explains the new features in Python 2.2.2, released on October 14, 2002. Python 2.2.2 is a bugfix release of Python 2.2, originally released on December 21, 2001.
Python 2.2 can be thought of as the “cleanup release”. There are some features such as
generators
and
iterators
that are completely new, but most of the changes, significant and
far-reaching(
影响深远的；波及广泛的
) though they may be, are aimed at cleaning up irregularities and dark corners of the language design.
This article doesn’t attempt to provide a complete specification of the new features, but instead provides a convenient overview. For full details, you should refer to the documentation for Python 2.2, such as the Python Library Reference and the Python Reference Manual. If you want to understand the complete implementation and design rationale for a change, refer to the PEP for a particular new feature.
The largest and most far-reaching changes in Python 2.2 are to Python’s model of objects and classes. The changes should be backward compatible, so it’s likely that your code will continue to run unchanged, but the changes provide some amazing new capabilities. Before beginning this, the longest and most complicated section of this article, I’ll provide an overview of the changes and offer some comments.
A long time ago I wrote a Web page listing flaws in Python’s design. One of the most significant flaws was that it’s impossible
to subclass Python types implemented in C. In particular, it’s not possible to subclass built-in types, so you can’t
just subclass, say, lists in order to add a single useful method to them. The
UserList
module provides a class that supports all of the methods of lists and that can be subclassed further, but there’s lots
of C code that expects a regular Python list and won’t accept a
UserList
instance.
Python 2.2 fixes this, and in the process adds some exciting new capabilities. A brief summary:
__getattr__()
can be rewritten to use properties instead, making the resulting code simpler and faster. As a small side benefit, attributes
can now have docstrings, too.Some users have voiced concern about all these changes. Sure, they say, the new features are neat and lend themselves to all sorts of tricks that weren’t possible in previous versions of Python, but they also make the language more complicated. Some people have said that they’ve always recommended Python for its simplicity, and feel that its simplicity is being lost.
Personally, I think there’s no need to worry. Many of the new features are quite
esoteric(
极不寻常的；只有少数人（尤指内行）才懂的；限于小圈子的
), and you can write a lot of Python code without ever needed to be aware of them. Writing
a simple class is no more difficult than it ever was, so you don’t need to bother learning or teaching them unless they’re
actually needed. Some very complicated tasks that were previously only possible from C will now be possible in pure Python,
and to my mind that’s all for the better.
I’m not going to attempt to cover every single corner case and small change that were required to make the new features work. Instead this section will paint only the broad strokes. See section Related Links , “Related Links”, for further sources of information about Python 2.2’s new object model.
First, you should know that Python 2.2 really has two kinds of classes: classic or old-style classes, and new-style classes. The old-style class model is exactly the same as the class model in earlier versions of Python. All the new features described in this section apply only to new-style classes. This divergence isn’t intended to last forever; eventually old-style classes will be dropped, possibly in Python 3.0.
So how do you define a new-style class? You do it by subclassing an existing new-style class. Most of Python’s built-in
types, such as integers, lists, dictionaries, and even files, are new-style classes now. A new-style class named
object
, the base class for all built-in types, has also been added so if no built-in type is suitable, you can just subclass
object
:
class C(object):
def __init__ (self):
...
...
This means that
class
statements that don’t have any base classes are always classic classes in Python 2.2. (Actually you can also change
this by setting a module-level variable named
__metaclass__
— see
PEP 253
for the details — but it’s easier to just subclass
object
.)
The type objects for the built-in types are available as built-ins, named using a clever trick. Python has always had
built-in functions named
int()
,
float()
, and
str()
. In 2.2, they aren’t functions any more, but type objects that behave as factories when called.
>>> int
>>> int('123')
123
To make the set of types complete, new type objects such as
dict()
and
file()
have been added. Here’s a more interesting example, adding a
lock()
method to file objects:
class LockableFile(file):
def lock (self, operation, length=0, start=0, whence=0):
import fcntl
return fcntl.lockf(self.fileno(), operation,
length, start, whence)
The now-obsolete (过时的
)
posixfile
module contained a class that emulated all of a file object’s methods and also added a
lock()
method, but this class couldn’t be passed to internal functions that expected a built-in file, something which is possible
with our new
LockableFile
.
In previous versions of Python, there was no consistent way to discover what attributes and methods were supported by
an object. There were some informal conventions, such as defining
__members__
and
__methods__
attributes that were lists of names, but often the author of an extension type or a class wouldn’t bother to define them.
You could fall back on inspecting the
__dict__
of an object, but when class inheritance or an arbitrary
__getattr__()
hook were in use this could still be inaccurate.
The one big idea underlying the new class model is that an API for describing the attributes of an object using descriptors has been formalized. Descriptors specify the value of an attribute, stating whether it’s a method or a field. With the descriptor API, static methods and class methods become possible, as well as more exotic constructs.
Attribute descriptors are objects that live inside class objects, and have a few attributes of their own:
__name__
is the attribute’s name.
__doc__
is the attribute’s docstring.
__get__(object)
is a method that retrieves the attribute value from
object.
__set__(object,
value)
sets the attribute on
object to
value.
__delete__(object,
value)
deletes the
value attribute of
object.For example, when you write
obj.x
, the steps that Python actually performs are:
descriptor = obj.__class__.x
descriptor.__get__(obj)
For methods,
descriptor.__get__()
returns a temporary object that’s callable, and wraps up the instance and the method to be called on it. This is also
why static methods and class methods are now possible; they have descriptors that wrap up just the method, or the method
and the class. As a brief explanation of these new kinds of methods, static methods aren’t passed the instance, and
therefore resemble regular functions. Class methods are passed the class of the object, but not the object itself. Static
and class methods are defined like this:
class C(object):
def f(arg1, arg2):
...
f = staticmethod(f)
def g(cls, arg1, arg2):
...
g = classmethod(g)
The
staticmethod()
function takes the function
f()
, and returns it wrapped up in a descriptor so it can be stored in the class object. You might expect there to be special
syntax for creating such methods (
def
static
f
,
defstatic
f()
, or something like that) but no such syntax has been defined yet; that’s been left for future versions of Python.
More new features, such as slots and properties, are also implemented as new kinds of descriptors, and it’s not difficult to write a descriptor class that does something novel. For example, it would be possible to write a descriptor class that made it possible to write Eiffel-style preconditions and postconditions for a method. A class that used this feature might be defined like this:
from eiffel import eiffelmethod
class C(object):
def f(self, arg1, arg2):
# The actual function
...
def pre_f(self):
# Check preconditions
...
def post_f(self):
# Check postconditions
...
f = eiffelmethod(f, pre_f, post_f)
Note that a person using the new
eiffelmethod()
doesn’t have to understand anything about descriptors. This is why I think the new features don’t increase the basic
complexity of the language. There will be a few wizards who need to know about it in order to write
eiffelmethod()
or the ZODB or whatever, but most users will just write code on top of the resulting libraries and ignore the implementation
details.
Multiple inheritance has also been made more useful through changing the rules under which names are resolved. Consider this set of classes (diagram taken from PEP 253 by Guido van Rossum):
class A:
^ ^ def save(self): ...
/ \
/ \
/ \
/ \
class B class C:
^ ^ def save(self): ...
\ /
\ /
\ /
\ /
class D
The lookup rule for classic classes is simple but not very smart; the base classes are searched depth-first, going from
left to right. A reference to
D.save()
will search the classes
D
,
B
, and then
A
, where
save()
would be found and returned.
C.save()
would never be found at all. This is bad, because if
C
’s
save()
method is saving some internal state specific to
C
, not calling it will result in that state never getting saved.
New-style classes follow a different algorithm that’s a bit more complicated to explain, but does the right thing in this situation. (Note that Python 2.3 changes this algorithm to one that produces the same results in most cases, but produces more useful results for really complicated inheritance graphs.)
D
,
B
,
A
,
C
,
A
].
D
,
B
,
C
,
A
] after dropping duplicates.
Following this rule, referring to
D.save()
will return
C.save()
, which is the behaviour we’re after. This lookup rule is the same as the one followed by Common Lisp. A new built-in
function,
super()
, provides a way to get at a class’s superclasses without having to reimplement Python’s algorithm. The most commonly
used form will be
super(class,
obj)
, which returns a bound superclass object (not the actual class object). This form will be used in methods to call a
method in the superclass; for example,
D
’s
save()
method would look like this:
class D (B,C):
def save (self):
# Call superclass .save()
super(D, self).save()
# Save D's private information here
...
super()
can also return unbound superclass objects when called as
super(class)
or
super(class1,
class2)
, but this probably won’t often be useful.
A fair number of sophisticated Python classes define hooks for attribute access using
__getattr__()
; most commonly this is done for convenience, to make code more readable by automatically mapping an attribute access
such as
obj.parent
into a method call such as
obj.get_parent
. Python 2.2 adds some new ways of controlling attribute access.
First,
__getattr__(attr_name)
is still supported by new-style classes, and nothing about it has changed. As before, it will be called when an attempt
is made to access
obj.foo
and no attribute named
foo
is found in the instance’s dictionary.
New-style classes also support a new method,
__getattribute__(attr_name)
. The difference between the two methods is that
__getattribute__()
is
always called whenever any attribute is accessed, while the old
__getattr__()
is only called if
foo
isn’t found in the instance’s dictionary.
However, Python 2.2’s support for
properties will often be a simpler way to trap attribute references. Writing a
__getattr__()
method is complicated because to avoid recursion you can’t use regular attribute accesses inside them, and instead have
to mess around with the contents of
__dict__
.
__getattr__()
methods also end up being called by Python when it checks for other methods such as
__repr__()
or
__coerce__()
, and so have to be written with this in mind. Finally, calling a function on every attribute access results in a sizable
performance loss.
property
is a new built-in type that packages up three functions that get, set, or delete an attribute, and a docstring. For
example, if you want to define a
size
attribute that’s computed, but also settable, you could write:
class C(object):
def get_size (self):
result = ... computation ...
return result
def set_size (self, size):
... compute something based on the size
and set internal state appropriately ...
# Define a property. The 'delete this attribute'
# method is defined as None, so the attribute
# can't be deleted.
size = property(get_size, set_size,
None,
"Storage size of this instance")
That is certainly clearer and easier to write than a pair of
__getattr__()
/
__setattr__()
methods that check for the
size
attribute and handle it specially while retrieving all other attributes from the instance’s
__dict__
. Accesses to
size
are also the only ones which have to perform the work of calling a function, so references to other attributes run at
their usual speed.
Finally, it’s possible to constrain the list of attributes that can be referenced on an object using the new
__slots__
class attribute. Python objects are usually very dynamic; at any time it’s possible to define a new attribute on an
instance by just doing
obj.new_attr=1
. A new-style class can define a class attribute named
__slots__
to limit the legal attributes to a particular set of names. An example will make this clear:
>>> class C(object):
... __slots__ = ('template', 'name')
...
>>> obj = C()
>>> print obj.template
None
>>> obj.template = 'Test'
>>> print obj.template
Test
>>> obj.newattr = None
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'C' object has no attribute 'newattr'
Note how you get an
AttributeError
on the attempt to assign to an attribute not listed in
__slots__
.
Another significant addition to 2.2 is an iteration interface at both the C and Python levels. Objects can define how they can be looped over by callers.
In Python versions up to 2.1, the usual way to make
for
item
in
obj
work is to define a
__getitem__()
method that looks something like this:
def __getitem__(self, index):
return <next item>
__getitem__()
is more properly used to define an indexing operation on an object so that you can write
obj[5]
to retrieve the sixth element. It’s a bit misleading when you’re using this only to support
for
loops. Consider some file-like object that wants to be looped over; the
index
parameter is essentially meaningless, as the class probably assumes that a series of
__getitem__()
calls will be made with
index incrementing by one each time. In other words, the presence of the
__getitem__()
method doesn’t mean that using
file[5]
to randomly access the sixth element will work, though it really should.
In Python 2.2, iteration can be implemented separately, and
__getitem__()
methods can be limited to classes that really do support random access. The basic idea of iterators is simple. A new built-in
function,
iter(obj)
or
iter(C,
sentinel)
, is used to get an iterator.
iter(obj)
returns an iterator for the object
obj, while
iter(C,
sentinel)
returns an iterator that will invoke the callable object
C until it returns
sentinel to signal that the iterator is done.
Python classes can define an
__iter__()
method, which should create and return a new iterator for the object; if the object is its own iterator, this method
can just return
self
. In particular, iterators will usually be their own iterators. Extension types implemented in C can implement a
tp_iter
function in order to return an iterator, and extension types that want to behave as iterators can define a
tp_iternext
function.
So, after all this, what do iterators actually do? They have one required method,
next()
, which takes no arguments and returns the next value. When there are no more values to be returned, calling
next()
should raise the
StopIteration
exception.
>>> L = [1,2,3]
>>> i = iter(L)
>>> print i
>>> i.next()
1
>>> i.next()
2
>>> i.next()
3
>>> i.next()
Traceback (most recent call last):
File "", line 1, in ?
StopIteration
>>>
In 2.2, Python’s
for
statement no longer expects a sequence; it expects something for which
iter()
will return an iterator. For backward compatibility and convenience, an iterator is automatically constructed for sequences
that don’t implement
__iter__()
or a
tp_iter
slot, so
for
i
in
[1,2,3]
will still work. Wherever the Python interpreter loops over a sequence, it’s been changed to use the iterator protocol.
This means you can do things like this:
>>> L = [1,2,3]
>>> i = iter(L)
>>> a,b,c = i
>>> a,b,c
(1, 2, 3)
Iterator support has been added to some of Python’s basic types. Calling
iter()
on a dictionary will return an iterator which loops over its keys:
>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
... 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m: print key, m[key]
...
Mar 3
Feb 2
Aug 8
Sep 9
May 5
Jun 6
Jul 7
Jan 1
Apr 4
Nov 11
Dec 12
Oct 10
That’s just the default behaviour. If you want to iterate over keys, values, or key/value pairs, you can explicitly call
the
iterkeys()
,
itervalues()
, or
iteritems()
methods to get an appropriate iterator. In a minor related change, the
in
operator now works on dictionaries, so
key
in
dict
is now equivalent to
dict.has_key(key)
.
Files also provide an iterator, which calls the
readline()
method until there are no more lines in the file. This means you can now read each line of a file using code like this:
for line in file:
# do something for each line
...
Note that you can only go forward in an iterator; there’s no way to get the previous element, reset the iterator, or make
a copy of it. An iterator object could provide such additional capabilities, but the iterator protocol only requires
a
next()
method.
See also
Generators are another new feature, one that interacts with the introduction of iterators.
You’re doubtless familiar with how function calls work in Python or C. When you call a function, it gets a private namespace
where its local variables are created. When the function reaches a
return
statement, the local variables are destroyed and the resulting value is returned to the caller. A later call to the same
function will get a fresh new set of local variables. But, what if the local variables weren’t thrown away on exiting
a function? What if you could later resume the function where it left off? This is what generators provide; they can
be thought of as resumable functions.
Here’s the simplest example of a generator function:
def generate_ints(N):
for i in range(N):
yield i
A new keyword,
yield
, was introduced for generators. Any function containing a
yield
statement is a generator function; this is detected by Python’s bytecode compiler which compiles the function specially
as a result. Because a new keyword was introduced, generators must be explicitly enabled in a module by including a
from
__future__
import
generators
statement near the top of the module’s source code. In Python 2.3 this statement will become unnecessary.
When you call a generator function, it doesn’t return a single value; instead it returns a generator object that supports
the iterator protocol. On executing the
yield
statement, the generator outputs the value of
i
, similar to a
return
statement. The big difference between
yield
and a
return
statement is that on reaching a
yield
the generator’s state of execution is suspended and local variables are preserved. On the next call to the generator’s
next()
method, the function will resume executing immediately after the
yield
statement. (For complicated reasons, the
yield
statement isn’t allowed inside the
try
block of a
try
…
finally
statement; read
PEP 255
for a full explanation of the interaction between
yield
and exceptions.)
Here’s a sample usage of the
generate_ints()
generator:
>>> gen = generate_ints(3)
>>> gen
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
Traceback (most recent call last):
File "", line 1, in ?
File "", line 2, in generate_ints
StopIteration
You could equally write
for
i
in
generate_ints(5)
, or
a,b,c
=
generate_ints(3)
.
Inside a generator function, the
return
statement can only be used without a value, and signals the end of the procession of values; afterwards the generator
cannot return any further values.
return
with a value, such as
return
5
, is a syntax error inside a generator function. The end of the generator’s results can also be indicated by raising
StopIteration
manually, or by just letting the flow of execution fall off the bottom of the function.
You could achieve the effect of generators manually by writing your own class and storing all the local variables of the
generator as instance variables. For example, returning a list of integers could be done by setting
self.count
to 0, and having the
next()
method increment
self.count
and return it. However, for a moderately complicated generator, writing a corresponding class would be much messier.
Lib/test/test_generators.py
contains a number of more interesting examples. The simplest one implements an in-order traversal of a tree using generators
recursively.
# A recursive generator that generates Tree leaves in in-order.
def inorder(t):
if t:
for x in inorder(t.left):
yield x
yield t.label
for x in inorder(t.right):
yield x
Two other examples in
Lib/test/test_generators.py
produce solutions for the N-Queens problem (placing $N$ queens on an $NxN$ chess board so that no queen threatens another)
and the Knight’s Tour (a route that takes a knight to every square of an $NxN$ chessboard without visiting any square
twice).
The idea of generators comes from other programming languages, especially Icon ( https://www.cs.arizona.edu/icon/), where the idea of generators is central. In Icon, every expression and function call behaves like a generator. One example from “An Overview of the Icon Programming Language” at https://www.cs.arizona.edu/icon/docs/ipd266.htm gives an idea of what this looks like:
sentence := "Store it in the neighboring harbor"
if (i := find("or", sentence)) > 5 then write(i)
In Icon the
find()
function returns the indexes at which the substring “or” is found: 3, 23, 33. In the
if
statement,
i
is first assigned a value of 3, but 3 is less than 5, so the comparison fails, and Icon retries it with the second value
of 23. 23 is greater than 5, so the comparison now succeeds, and the code prints the value 23 to the screen.
Python doesn’t go nearly as far as Icon in adopting generators as a central concept. Generators are considered a new part of the core Python language, but learning or using them isn’t compulsory; if they don’t solve any problems that you have, feel free to ignore them. One novel feature of Python’s interface as compared to Icon’s is that a generator’s state is represented as a concrete object (the iterator) that can be passed around to other functions or stored in a data structure.
See also
In recent versions, the distinction between regular integers, which are 32-bit values on most machines, and long integers,
which can be of arbitrary size, was becoming an annoyance. For example, on platforms that support files larger than
2**32
bytes, the
tell()
method of file objects has to return a long integer. However, there were various bits of Python that expected plain integers
and would raise an error if a long integer was provided instead. For example, in Python 1.5, only regular integers could
be used as a slice index, and
'abc'[1L:]
would raise a
TypeError
exception with the message ‘slice index must be int’.
Python 2.2 will shift values from short to long integers as required. The ‘L’ suffix is no longer needed to indicate a
long integer literal, as now the compiler will choose the appropriate type. (Using the ‘L’ suffix will be discouraged
in future 2.x versions of Python, triggering a warning in Python 2.4, and probably dropped in Python 3.0.) Many operations
that used to raise an
OverflowError
will now return a long integer as their result. For example:
>>><PHONE_NUMBER>123
1234567890123L
>>> 2 ** 64
18446744073709551616L
In most cases, integers and long integers will now be treated identically. You can still distinguish them with the
type()
built-in function, but that’s rarely needed.
See also
The most controversial change in Python 2.2 heralds the start of an effort to fix an old design flaw that’s been in Python
from the beginning. Currently Python’s division operator,
/
, behaves like C’s division operator when presented with two integer arguments: it returns an integer result that’s truncated
down when there would be a fractional part. For example,
3/2
is 1, not 1.5, and
(-1)/2
is -1, not -0.5. This means that the results of division can vary unexpectedly depending on the type of the two operands
and because Python is dynamically typed, it can be difficult to determine the possible types of the operands.
(The controversy is over whether this is really a design flaw, and whether it’s worth breaking existing code to fix this. It’s caused endless discussions on python-dev, and in July 2001 erupted into a storm of acidly sarcastic postings on comp.lang.python. I won’t argue for either side here and will stick to describing what’s implemented in 2.2. Read PEP 238 for a summary of arguments and counter-arguments.)
Because this change might break code, it’s being introduced very gradually. Python 2.2 begins the transition, but the switch won’t be complete until Python 3.0.
First, I’ll borrow some terminology from
PEP 238
. “True division” is the division that most non-programmers are familiar with: 3/2 is 1.5, 1/4 is 0.25, and so forth.
“Floor division” is what Python’s
/
operator currently does when given integer operands; the result is the floor of the value returned by true division.
“Classic division” is the current mixed behaviour of
/
; it returns the result of floor division when the operands are integers, and returns the result of true division when
one of the operands is a floating-point number.
Here are the changes 2.2 introduces:
A new operator,
//
, is the floor division operator. (Yes, we know it looks like C++’s comment symbol.)
//
always performs floor division no matter what the types of its operands are, so
1
//
2
is 0 and
1.0
//
2.0
is also 0.0.
//
is always available in Python 2.2; you don’t need to enable it using a
__future__
statement.
By including a
from
__future__
import
division
in a module, the
/
operator will be changed to return the result of true division, so
1/2
is 0.5. Without the
__future__
statement,
/
still means classic division. The default meaning of
/
will not change until Python 3.0.
Classes can define methods called
__truediv__()
and
__floordiv__()
to overload the two division operators. At the C level, there are also slots in the
PyNumberMethods
structure so extension types can define the two operators.
Python 2.2 supports some command-line arguments for testing whether code will work with the changed division semantics.
Running python with
-Q
warn
will cause a warning to be issued whenever division is applied to two integers. You can use this to find code that’s
affected by the change and fix it. By default, Python 2.2 will simply perform classic division without a warning; the
warning will be turned on by default in Python 2.3.
See also
Python’s Unicode support has been enhanced a bit in 2.2. Unicode strings are usually stored as UCS-2, as 16-bit unsigned
integers. Python 2.2 can also be compiled to use UCS-4, 32-bit unsigned integers, as its internal encoding by supplying
--enable-unicode=ucs4
to the configure script. (It’s also possible to specify
--disable-unicode
to completely disable Unicode support.)
When built to use UCS-4 (a “wide Python”), the interpreter can natively handle Unicode characters from U+000000 to U+110000,
so the range of legal values for the
unichr()
function is expanded accordingly. Using an interpreter compiled to use UCS-2 (a “narrow Python”), values greater than
65535 will still cause
unichr()
to raise a
ValueError
exception. This is all described in
PEP 261
, “Support for ‘wide’ Unicode characters”; consult it for further details.
Another change is simpler to explain. Since their introduction, Unicode strings have supported an
encode()
method to convert the string to a selected encoding such as UTF-8 or Latin-1. A symmetric
decode([*encoding*])
method has been added to 8-bit strings (though not to Unicode strings) in 2.2.
decode()
assumes that the string is in the specified encoding and decodes it, returning whatever is returned by the codec.
Using this new feature, codecs have been added for tasks not directly related to Unicode. For example, codecs have been
added for uu-encoding, MIME’s base64 encoding, and compression with the
zlib
module:
>>> s = """Here is a lengthy piece of redundant, overly verbose,
... and repetitive text.
... """
>>> data = s.encode('zlib')
>>> data
'x\x9c\r\xc9\xc1\r\x80 \x10\x04\xc0?Ul...'
>>> data.decode('zlib')
'Here is a lengthy piece of redundant, overly verbose,\nand repetitive text.\n'
>>> print s.encode('uu')
begin 666
M2&5R92!I=F5R8F]S92P*86YD(')E<&5T:71I=F4@=&5X="X*
end
>>> "sheesh".encode('rot-13')
'furrfu'
To convert a class instance to Unicode, a
__unicode__()
method can be defined by a class, analogous to
__str__()
.
encode()
,
decode()
, and
__unicode__()
were implemented by Marc-André Lemburg. The changes to support using UCS-4 internally were implemented by Fredrik Lundh
and Martin von Löwis.
See also
In Python 2.1, statically nested scopes were added as an optional feature, to be enabled by a
from
__future__
import
nested_scopes
directive. In 2.2 nested scopes no longer need to be specially enabled, and are now always present. The rest of this
section is a copy of the description of nested scopes from my “What’s New in Python 2.1” document; if you read it when
2.1 came out, you can skip the rest of this section.
The largest change introduced in Python 2.1, and made complete in 2.2, is to Python’s scoping rules. In Python 2.0, at any given time there are at most three namespaces used to look up variable names: local, module-level, and the built-in namespace. This often surprised people because it didn’t match their intuitive expectations. For example, a nested recursive function definition doesn’t work:
def f():
...
def g(value):
...
return g(value-1) + 1
...
The function
g()
will always raise a
NameError
exception, because the binding of the name
g
isn’t in either its local namespace or in the module-level namespace. This isn’t much of a problem in practice (how often
do you recursively define interior functions like this?), but this also made using the
lambda
statement clumsier, and this was a problem in practice. In code which uses
lambda
you can often find local variables being copied by passing them as the default values of arguments.
def find(self, name):
"Return list of any entries equal to 'name'"
L = filter(lambda x, name=name: x == name,
self.list_attribute)
return L
The readability of Python code written in a strongly functional style suffers greatly as a result.
The most significant change to Python 2.2 is that static scoping has been added to the language to fix this problem. As
a first effect, the
name=name
default argument is now unnecessary in the above example. Put simply, when a given variable name is not assigned a value
within a function (by an assignment, or the
def
,
class
, or
import
statements), references to the variable will be looked up in the local namespace of the enclosing scope. A more detailed
explanation of the rules, and a dissection of the implementation, can be found in the PEP.
This change may cause some compatibility problems for code where the same variable name is used both at the module level and as a local variable within a function that contains further function definitions. This seems rather unlikely though, since such code would have been pretty confusing to read in the first place.
One side effect of the change is that the
from
module
import
*
and
exec
statements have been made illegal inside a function scope under certain conditions. The Python reference manual has said
all along that
from
module
import
*
is only legal at the top level of a module, but the CPython interpreter has never enforced this before. As part of the
implementation of nested scopes, the compiler which turns Python source into bytecodes has to generate different code
to access variables in a containing scope.
from
module
import
*
and
exec
make it impossible for the compiler to figure this out, because they add names to the local namespace that are unknowable
at compile time. Therefore, if a function contains function definitions or
lambda
expressions with free variables, the compiler will flag this by raising a
SyntaxError
exception.
To make the preceding explanation a bit clearer, here’s an example:
x = 1
def f():
# The next line is a syntax error
exec 'x=2'
def g():
return x
Line 4 containing the
exec
statement is a syntax error, since
exec
would define a new local variable named
x
whose value should be accessed by
g()
.
This shouldn’t be much of a limitation, since
exec
is rarely used in most Python code (and when it is used, it’s often a sign of a poor design anyway).
See also
The
xmlrpclib
module was contributed to the standard library by Fredrik Lundh, providing support for writing XML-RPC clients. XML-RPC
is a simple remote procedure call protocol built on top of HTTP and XML. For example, the following snippet retrieves
a list of RSS channels from the O’Reilly Network, and then lists the recent headlines for one channel:
import xmlrpclib
s = xmlrpclib.Server(
'http://www.oreillynet.com/meerkat/xml-rpc/server.php')
channels = s.meerkat.getChannels()
# channels is a list of dictionaries, like this:
# [{'id': 4, 'title': 'Freshmeat Daily News'}
# {'id': 190, 'title': '32Bits Online'},
# {'id': 4549, 'title': '3DGamers'}, ... ]
# Get the items for one channel
items = s.meerkat.getItems( {'channel': 4} )
# 'items' is another list of dictionaries, like this:
# [{'link': 'http://freshmeat.net/releases/52719/',
# 'description': 'A utility which converts HTML to XSL FO.',
# 'title': 'html2fo 0.3 (Default)'}, ... ]
The
SimpleXMLRPCServer
module makes it easy to create straightforward XML-RPC servers. See
http://www.xmlrpc.com/ for more information about XML-RPC.
The new
hmac
module implements the HMAC algorithm described by
RFC 2104
. (Contributed by Gerhard Häring.)
Several functions that originally returned lengthy tuples now return pseudo-sequences that still behave like tuples
but also have mnemonic attributes such as memberst_mtime or
tm_year
. The enhanced functions include
stat()
,
fstat()
,
statvfs()
, and
fstatvfs()
in the
os
module, and
localtime()
,
gmtime()
, and
strptime()
in the
time
module.
For example, to obtain a file’s size using the old tuples, you’d end up writing something like
file_size
=
os.stat(filename)[stat.ST_SIZE]
, but now this can be written more clearly as
file_size
=
os.stat(filename).st_size
.
The original patch for this feature was contributed by Nick Mathewson.
The Python profiler has been extensively reworked and various errors in its output have been corrected. (Contributed by Fred L. Drake, Jr. and Tim Peters.)
The
socket
module can be compiled to support IPv6; specify the
--enable-ipv6
option to Python’s configure script. (Contributed by Jun-ichiro “itojun” Hagino.)
Two new format characters were added to the
struct
module for 64-bit integers on platforms that support the C
long
long
type.
q
is for a signed 64-bit integer, and
Q
is for an unsigned one. The value is returned in Python’s long integer type. (Contributed by Tim Peters.)
In the interpreter’s interactive mode, there’s a new built-in function
help()
that uses the
pydoc
module introduced in Python 2.1 to provide interactive help.
help(object)
displays any available help text about
object.
help()
with no argument puts you in an online help utility, where you can enter the names of functions, classes, or modules
to read their help text. (Contributed by Guido van Rossum, using Ka-Ping Yee’s
pydoc
module.)
Various bugfixes and performance improvements have been made to the SRE engine underlying the
re
module. For example, the
re.sub()
and
re.split()
functions have been rewritten in C. Another contributed patch speeds up certain Unicode character ranges by a factor
of two, and a new
finditer()
method that returns an iterator over all the non-overlapping matches in a given string. (SRE is maintained by Fredrik
Lundh. The BIGCHARSET patch was contributed by Martin von Löwis.)
The
smtplib
module now supports
RFC 2487
, “Secure SMTP over TLS”, so it’s now possible to encrypt the SMTP traffic between a Python program and the mail transport
agent being handed a message.
smtplib
also supports SMTP authentication. (Contributed by Gerhard Häring.)
The
imaplib
module, maintained by Piers Lauder, has support for several new extensions: the NAMESPACE extension defined in
RFC 2342
, SORT, GETACL and SETACL. (Contributed by Anthony Baxter and Michel Pelletier.)
The
rfc822
module’s parsing of email addresses is now compliant with
RFC 2822
, an update to
RFC 822
. (The module’s name is
not going to be changed to
rfc2822
.) A new package,
email
, has also been added for parsing and generating e-mail messages. (Contributed by Barry Warsaw, and arising out of
his work on Mailman.)
The
difflib
module now contains a new
Differ
class for producing human-readable lists of changes (a “delta”) between two sequences of lines of text. There are also
two generator functions,
ndiff()
and
restore()
, which respectively return a delta from two sequences, or one of the original sequences from a delta. (Grunt work
contributed by David Goodger, from ndiff.py code by Tim Peters who then did the generatorization.)
New constants
ascii_letters
,
ascii_lowercase
, and
ascii_uppercase
were added to the
string
module. There were several modules in the standard library that used
string.letters
to mean the ranges A-Za-z, but that assumption is incorrect when locales are in use, because
string.letters
varies depending on the set of legal characters defined by the current locale. The buggy modules have all been fixed
to use
ascii_letters
instead. (Reported by an unknown person; fixed by Fred L. Drake, Jr.)
The
mimetypes
module now makes it easier to use alternative MIME-type databases by the addition of a
MimeTypes
class, which takes a list of filenames to be parsed. (Contributed by Fred L. Drake, Jr.)
A
Timer
class was added to the
threading
module that allows scheduling an activity to happen at some future time. (Contributed by Itamar Shtull-Trauring.)
Some of the changes only affect people who deal with the Python interpreter at the C level because they’re writing Python extension modules, embedding the interpreter, or just hacking on the interpreter itself. If you only write Python code, none of the changes described here will affect you very much.
Profiling and tracing functions can now be implemented in C, which can operate at much higher speeds than Python-based
functions and should reduce the overhead of profiling and tracing. This will be of interest to authors of development
environments for Python. Two new C functions were added to Python’s API,
PyEval_SetProfile()
and
PyEval_SetTrace()
. The existing
sys.setprofile()
and
sys.settrace()
functions still exist, and have simply been changed to use the new C-level interface. (Contributed by Fred L. Drake,
Jr.)
Another low-level API, primarily of interest to implementors of Python debuggers and development tools, was added.
PyInterpreterState_Head()
and
PyInterpreterState_Next()
let a caller walk through all the existing interpreter objects;
PyInterpreterState_ThreadHead()
and
PyThreadState_Next()
allow looping over all the thread states for a given interpreter. (Contributed by David Beazley.)
The C-level interface to the garbage collector has been changed to make it easier to write extension types that support garbage collection and to debug misuses of the functions.  Extensions that use the old API will still compile but will not participate in garbage collection, so updating them for 2.2 should be considered fairly high priority.
To upgrade an extension module to the new API, perform the following steps:
Rename
Py_TPFLAGS_GC()
to
PyTPFLAGS_HAVE_GC()
.
PyObject_GC_New()
or
PyObject_GC_NewVar()
to allocateobjects, and
PyObject_GC_Del()
to deallocate them.
PyObject_GC_Init()
to
PyObject_GC_Track()
and
PyObject_GC_Fini()
to
PyObject_GC_UnTrack()
.
Remove
PyGC_HEAD_SIZE()
from object size calculations.
Remove calls to
PyObject_AS_GC()
and
PyObject_FROM_GC()
.
A new
et
format sequence was added to
PyArg_ParseTuple()
;
et
takes both a parameter and an encoding name, and converts the parameter to the given encoding if the parameter turns out
to be a Unicode string, or leaves it alone if it’s an 8-bit string, assuming it to already be in the desired encoding.
This differs from the
es
format character, which assumes that 8-bit strings are in Python’s default ASCII encoding and converts them to the
specified new encoding. (Contributed by M.-A. Lemburg, and used for the MBCS support on Windows described in the following
section.)
A different argument parsing function,
PyArg_UnpackTuple()
, has been added that’s simpler and presumably faster. Instead of specifying a format string, the caller simply gives
the minimum and maximum number of arguments expected, and a set of pointers to
PyObject*
variables that will be filled in with argument values.
Two new flags
METH_NOARGS
and
METH_O
are available in method definition tables to simplify implementation of methods with no arguments or a single untyped
argument. Calling such methods is more efficient than calling a corresponding method that uses
METH_VARARGS
. Also, the old
METH_OLDARGS
style of writing C methods is now officially deprecated.
Two new wrapper functions,
PyOS_snprintf()
and
PyOS_vsnprintf()
were added to provide cross-platform implementations for the relatively new
snprintf()
and
vsnprintf()
C lib APIs. In contrast to the standard
sprintf()
and
vsprintf()
functions, the Python versions check the bounds of the buffer used to protect against buffer overruns. (Contributed
by M.-A. Lemburg.)
The
_PyTuple_Resize()
function has lost an unused parameter, so now it takes 2 parameters instead of 3. The third argument was never used,
and can simply be discarded when porting code from earlier versions to Python 2.2.
 A search through the CVS change logs finds there were 527 patches applied and 683 bugs fixed between Python 2.1 and 2.2; 2.2.1 applied 139 patches and fixed 143 bugs; 2.2.2 applied 106 patches and fixed 82 bugs. These figures are likely to be underestimates.
Some of the more notable changes are:
The code for the MacOS port for Python, maintained by Jack Jansen, is now kept in the main Python CVS tree, and many changes have been made to support MacOS X.
The most significant change is the ability to build Python as a framework, enabled by supplying the
--enable-framework
option to the configure script when compiling Python. According to Jack Jansen, “This installs a self-contained Python
installation plus the OS X framework “glue” into
/Library/Frameworks/Python.framework
(or another location of choice). For now there is little immediate added benefit to this (actually, there is the disadvantage
that you have to change your PATH to be able to find Python), but it is the basis for creating a full-blown Python
application, porting the MacPython IDE, possibly using Python as a standard OSA scripting language and much more.”
Most of the MacPython toolbox modules, which interface to MacOS APIs such as windowing, QuickTime, scripting, etc. have
been ported to OS X, but they’ve been left commented out in
setup.py
. People who want to experiment with these modules can uncomment them manually.
Keyword arguments passed to built-in functions that don’t take them now cause a
TypeError
exception to be raised, with the message “
function takes no keyword arguments”.
Weak references, added in Python 2.1 as an extension module, are now part of the core because they’re used in the implementation
of new-style classes. The
ReferenceError
exception has therefore moved from the
weakref
module to become a built-in exception.
A new script,
Tools/scripts/cleanfuture.py
by Tim Peters, automatically removes obsolete
__future__
statements from Python source code.
An additional
flags argument has been added to the built-in function
compile()
, so the behaviour of
__future__
statements can now be correctly observed in simulated shells, such as those presented by IDLE and other development
environments. This is described in
PEP 264
. (Contributed by Michael Hudson.)
The new license introduced with Python 1.6 wasn’t GPL-compatible. This is fixed by some minor textual changes to the 2.2 license, so it’s now legal to embed Python inside a GPLed program again. Note that Python itself is not GPLed, but instead is under a license that’s essentially equivalent to the BSD license, same as it always was. The license changes were also applied to the Python 2.0.1 and 2.1.1 releases.
When presented with a Unicode filename on Windows, Python will now convert it to an MBCS encoded string, as used by
the Microsoft file APIs. As MBCS is explicitly used by the file APIs, Python’s choice of ASCII as the default encoding
turns out to be an annoyance. On Unix, the locale’s character set is used if
locale.nl_langinfo(CODESET)
is available. (Windows support was contributed by Mark Hammond with assistance from Marc-André Lemburg. Unix support
was added by Martin von Löwis.)
Large file support is now enabled on Windows. (Contributed by Tim Peters.)
The
Tools/scripts/ftpmirror.py
script now parses a
.netrc
file, if you have one. (Contributed by Mike Romberg.)
Some features of the object returned by the
xrange()
function are now deprecated, and trigger warnings when they’re accessed; they’ll disappear in Python 2.3.
xrange
objects tried to pretend they were full sequence types by supporting slicing, sequence multiplication, and the
in
operator, but these features were rarely used and therefore buggy. The
tolist()
method and the
start
,
stop
, and
step
attributes are also being deprecated. At the C level, the fourth argument to the
PyRange_New()
function,
repeat
, has also been deprecated.
There were a bunch of patches to the dictionary implementation, mostly to fix potential core dumps if a dictionary contains objects that sneakily changed their hash value, or mutated the dictionary they were contained in. For a while python-dev fell into a gentle rhythm of Michael Hudson finding a case that dumped core, Tim Peters fixing the bug, Michael finding another case, and round and round it went.
On Windows, Python can now be compiled with Borland C thanks to a number of patches contributed by Stephen Hansen, though the result isn’t fully functional yet. (But this is progress…)
Another Windows enhancement: Wise Solutions generously offered PythonLabs use of their InstallerMaster 8.1 system. Earlier PythonLabs Windows installers used Wise 5.0a, which was beginning to show its age. (Packaged up by Tim Peters.)
Files ending in
.pyw
can now be imported on Windows.
.pyw
is a Windows-only thing, used to indicate that a script needs to be run using PYTHONW.EXE instead of PYTHON.EXE in
order to prevent a DOS console from popping up to display the output. This patch makes it possible to import such scripts,
in case they’re also usable as modules. (Implemented by David Bolen.)
On platforms where Python uses the C
dlopen()
function to load extension modules, it’s now possible to set the flags used by
dlopen()
using the
sys.getdlopenflags()
and
sys.setdlopenflags()
functions. (Contributed by Bram Stolk.)
The
pow()
built-in function no longer supports 3 arguments when floating-point numbers are supplied.
pow(x,
y,
z)
returns
(x**y)
%
z
, but this is never useful for floating point numbers, and the final result varies unpredictably depending on the platform.
A call such as
pow(2.0,
8.0,
7.0)
will now raise a
TypeError
exception.


Just Dance site gives an overview of all the renowned choreographers around the world, who are specialized in various dance forms to help improve one's dancing skills.
Just Dance site exclusively displays all the dance workshops held at nearby locations irrespective of the dance forms. Thus you can get learn your favourite dance styles and meet famous dance personalities through dance workshops.
Just Dance site is the best place to get tips and other interesting info on varied dance forms to master the skill. In addition to this there are many interesting articles on various topics of dance.
House Dance is an amalgamation of the post-disco era.The main elements of House dance include "Footwork", "Jacking", and "Lofting". House dance is often improvised and emphasizes fast and complex foot-oriented steps combined with fluid movements in the torso, as well as floor work. The major source in house dance movement stems directly from the music and the elements within the music such as jazz, African, Latin, soul, R&B, funk, hip hop, etc.In house dancing, there is an emphasis on the subtle rhythms and riffs of the music, and the footwork follows them closely. This is one of the main features that distinguishes house dancing from dancing that was done to disco before house emerged and current dancing that is done to electronic dance music as part of the rave culture.
Inspired by Vogue magazine, voguing is characterized by model-like poses integrated with angular, linear, and rigid arm, leg, and body movements. It was originally called "presentation" and later "performance". Over the years, the dance evolved into the more intricate and illusory form that is now called "vogue". Vogue Fem ("Fem" is derived from the French word femme, meaning "woman") is fluidity at its most extreme with exaggerated feminine movements influenced by ballet, jazz and modern dance. Styles of Vogue Fem performance range from Dramatics (which emphasizes stunts, tricks, and speed) to Soft (which emphasizes a graceful, beautiful, easy flow and flow continuations between the five elements). There are five elements of Vogue Fem: hand performance, catwalk, duckwalk, floor performance, and dips & drops (although some non-official performances may count spins as one of the elements
The Nae Nae is a hip-hop dance that involves planting one’s feet, swaying with shoulder movement, placing one hand in the air and one hand down, and incorporating personal creativity. In 2015, American rapper Silentó released his debut single "Watch Me (Whip/Nae Nae)" which also included the Nae Nae along with other dance moves, appearing in viral videos and mainstream media. Numerous celebrities have been covered by the social and mainstream media when they performed the dance, including Jeremy Lin and Stephen Curry, Dwight Howard, Lance Moore, TLC, John Wall, Pharrell Williams, Miley Cyrus, and JJ Watt. The video game NBA 2K16 allows players to dance the Nae Nae.


Its possible to write Gremlin based extensions. To do so, you will need to make sure to make use of GMaven in your pom.xml
. For example:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<goals>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
</goals>
<configuration>
<providerSelection>1.7</providerSelection>
</configuration>
</execution>
</executions>
</plugin>
Next you can then create a Gremlin-based extension.
@ExtensionNaming(namespace = "ex", name = "gremlinExample")
public class GremlinBasedExtension extends AbstractRexsterExtension {
static {
Gremlin.load();
}
@ExtensionDefinition(extensionPoint = ExtensionPoint.VERTEX)
@ExtensionDescriptor(description = "Traversal with native Gremlin")
public ExtensionResponse evaluate(@RexsterContext RexsterResourceContext context,
@RexsterContext Vertex v) {
JSONObject results = new JSONObject();
results.put("foaf count", v.out('knows').out('knows').count())
return ExtensionResponse.ok(results);
}
}
NOTE Like all extensions, don’t forget to add the extension’s full class name to your
src/resources/META-INF/services/com.tinkerpop.rexster.extension.RexsterExtension
Please see Deploying an Extension for more details


This is part 1 of the alchemy-modelgen
series. In this post, we’ll explore the tool alchemy-modelgen
and get to know the features and API’s of this tool.
alchemy-modelgen
is tool which makes RDBMS (such as Redshift, PostgreSQL, Snowflake, MySQL, etc.) management easy by abstracting typical mundane tasks like writing and storing multiple sql files, modifying tables and tracking these modifications, etc.
alchemy-modelgen
enables database/warehouse construction either using YAML based schema-configuration files or through replication of existing database schema. It also facilitates schema versioning and tracking, at the same time enabling time travel back to earlier versions.
Underneath, alchemy-modelgen
uses alembic for table creation, modification, and version management, and sqlacodegen for schema extraction from existing databases and warehouses.
Database migration refers to movement of your data structure from one platform to another.
Let’s look at a typical use case for data migration. In an enterprise, the application was built on a relatively slower databases like MySQL or Postgres. But as the volume of the data grew, the process of analyzing the data became cumbersome. Inorder to tackle this, the enterprise decided to shift from MySQL to a big data handler database like AWS Redshift for example.
To migrate your data to redshift, we first need to migrate all the table structure from mysql to redshift. Generally, in an enterprise the number of tables are in two digits. Imagine the amount of time and precision this would require, especially when the tables have numerous columns and have constraints like primary key, unique or null constraint.
Let’s take another use case. Let’s say we want to setup a data warehouse using Redshift. This could be done in many ways:
Create the tables manually
Write big SQL files
Use an ORM tool like hibernate (for java), sqlalchemy (for python)
In all of the above approaches, a lot of coding and maintenance is involved. Also, we need to have specialized skills to create and maintain the tables like fluency with SQL, understanding of ORM tools and so forth. And what if we need to change the structure? Let’s say we want to add or delete a column, or change the data type of a column? What happens then? What if we change the structure now, and we want to move back to the old structure? How to maintain different versions of the table structure? We’ll try to answer these question in the following sections.
alchemy-modelgen
is a tool which simplifies typical database management tasks. This includes identifying tables, altering their schema, and versioning of these updates.
Tables can be constructed using two approaches:
Specifying the database model through a YAML file including tables, columns, constraints and relationships. (YAML files are easy to write, do not require programming skills, and can be stored in any storage location (local, cloud buckets, git, etc).
Replicating the database model of an existing database or warehouse. This is especially applicable for data migration workflows.
Schema changes are extremely common and typical require manual queries to be run in order to make these changes. Furthermore, recording these changes is needed in order to roll back the changes or return to a previous version of the schema. alchemy-modelgen
handles this out of the box, preserving all iterations of the table schema and enabling roll back to any previous state.
Let’s look into the usage of alchemy-modelgen
in the following sections.
Note: python version >= 3.8 is required
alchemy-modelgen
can be installed from pypi
using:
pip install alchemy-modelgen
modelgen
, a command-line utility, is included in the kit. The command modelgen
is used to carry out all of the executions.
Before conducting any database operations, modelgen must be initialized. To begin, type the following command:
modelgen init -d ./modelgen_folder
./modelgen_folder
refers to the folder that modelgen will build. The folder may be assigned any name; the only requirement is that it does not already exist.
(./modelgen_folder
will be used as an example initialization folder in the following parts of this article. The folder name should be the same as the one used to initialize modelgen.)
The above command results in the following folder structure:
modelgen_folder
├── alembic_migrate
│ └── __init__.py
│ └── env.py
│ └── script.py.mako
│ └── versions
│ └── __init__.py
│ └── README
├── templates
│ └── example.yaml
└── alembic.ini
The tool includes a sample YAML file that shows how to write tables, define schema, and specify constraints, among other things. The file can be found in the modelgen_folder/templates/example.yaml
folder.
The initialized directory (modelgen_folder
in this case, essentially, cd modelgen_folder
) should always be the working directory for all modelgen operations.
tables: # In this section, we define the tables, their name and schema
userinfo: # This is the table name
columns: # In this section, we define column names and their data types
- name: id
type: integer
primary_key: true # Set this value for the primary key column
- name: firstname # Column name
type: varchar # Column datatype
length: 20
- name: lastname
type: varchar
length: 20
- name: dob
type: date
- name: contact
type: numeric
nullable: false # Allow / disallow null values in the column, default `true`
unique: true # Apply unique constraint for the column, default `false`
- name: address
type: varchar
length: 200 # specify length of the column
In order to register this YAML schema with modelgen, we run modelgen createmodel
after it is specified in YAML:
modelgen createmodel -s yaml -p <path/to/your/template.yaml> -a
In the above command, the parameters -s
, -p
and -a
are:
-s
: whether it’s a yaml file or an existing database/warehouse to read schema from, should be database
or yaml
-p
: path of the YAML schema file
-a
: enables support for database migration. It is disabled by default
The recommended location for the YAML file is modelgen_folder/templates
. However, the file can be stored at any path or location.
Some databases, such as AWS Redshift, may have additional parameters such as diststyle, distkey, and sortkey. Please read this document to learn more about this advanced use.
It is possible to extract the schema of all tables and views from an existing database or warehouse using modelgen. The procedure is as follows:
modelgen_folder
as current working directory:cd modelgen_folder
modelgen createmodel -s database --outfile models/<FILENAME>.py -p <SQLALCHEMY_DATABASE_URL> -a
In the above command, the parameters -s
, --outfile
, -p
and -a
are:
-s
: whether it’s a yaml file or an existing database/warehouse to read schema from, should be database
or yaml
--outfile
: The schema from the database/warehouse should be saved in this file. models/<FILENAME>.py
should always be the path, where <FILENAME>
can be any name you like.
-p
: The database/warehouse’s url. The sqlalchemy url syntax should be followed for this URL. The syntax of sqlalchemy is as follows:
database+connector://username:password@host:port/database
Database connections supported by modelgen
are:
MySQL: mysql+mysqlconnector://username:password@host:port/database
Postgresql: postgresql+psycopg2://username:password@host:port/database
Redshift: redshift+psycopg2://username:password@host:port/database
snowflake: snowflake://username:password@account
, more info can be found here
It’s time to move the schema to our actual target database/warehouse, either through the YAML file or by pulling from an existing database/warehouse. Under the hood, modelgen
uses a migration tool called alembic
to accomplish this.
git
commits. Your updates are saved to the local repository using these revisions. Revisions can also be thought of as snapshots of the yaml schema written in a language that modelgen
can understand. These revisions are saved in the alembic_migrate/versions/
folder by modelgen.modelgen migrate revision --autogenerate -m '<COMMIT_MESSAGE>' -p <SQLALCHEMY_DATABASE_URL>
Depending on what the new revision is doing, the <COMMIT MESSAGE>
may be contextual. If this is the first migration, the commit message may be initial migration
, making our final command:
modelgen migrate revision --autogenerate -m 'initial migration' -p <SQLALCHEMY_DATABASE_URL>
The parameter -p
corresponds to the sqlalchemy URL of the target database/warehouse.
modelgen migrate upgrade head -p <SQLALCHEMY_DATABASE_URL>
The addition of a new column, modifying the datatype of a column, increasing or reducing the length of a column, or imposing or eliminating restrictions on a column are all examples of table alterations. The procedure to alter tables is:
Make changes in the YAML schema file
Let’s take the YAML template from the earlier section of this article:
tables:
userinfo:
columns:
- name: id
type: integer
primary_key: true
- name: firstname
type: varchar
length: 20
- name: lastname
type: varchar
length: 20
- name: dob
type: date
- name: contact
type: numeric
nullable: false
unique: true
- name: address
type: varchar
length: 200
address
from 200
to 350
and add a new column called country
:
tables:
userinfo:
columns:
- name: id
type: integer
primary_key: true
- name: firstname
type: varchar
- name: lastname
type: varchar
- name: dob
type: date
- name: contact
type: numeric
nullable: false
unique: true
- name: address
type: varchar
length: 350 # Column length changed from 200 to 350
- name: country # New column added
type: varchar
length: 20
Create migration revision:
modelgen migrate revision --autogenerate -m 'initial migration' -p <SQLALCHEMY_DATABASE_URL>
Alter the tables in the database/warehouse:
modelgen migrate upgrade head -p <SQLALCHEMY_DATABASE_URL>
The alterations should now be reflected in the database/warehouse.
Modelgen uses alembic to keep track of schema versions under the hood. To upgrade or downgrade to any old/new version, we begin by listing the versions, obtaining the version id, and then upgrading/downgrading using the version id.
List all the versions:
modelgen migrate history -p <SQLALCHEMY_DATABASE_URL>
Get the version id:
The output of the above command would look something like this:
787cf0fee9c1 -> 16225b6adae3 (head), add new column country, change address length from 200 to 350
<base> -> 787cf0fee9c1, initial migration
The id 787cf0fee9c1
refers to the older migration, while the id 16225b6adae3
refers to the most recent migration.
The most recent migration is also the one that is active in the database/warehouse right now.
Let’s suppose we want to go back to the edition with the id 787cf0fee9c1
. We can do so by running the following command:
modelgen migrate downgrade 787cf0fee9c1 -p <SQLALCHEMY_DATABASE_URL>
The database/warehouse tables should now be at the same state as 787cf0fee9c1
.
If we want to go back to the most recent schema version again with the id 16225b6adae3, we can use the following command:
modelgen migrate ugrade 16225b6adae3 -p <SQLALCHEMY_DATABASE_URL>
We looked at alchemy-modelgen
, its functionality, and how to use it in this post. Support for more databases and warehouses will be included in future releases. Please visit the GitHub repository if you want to learn more or contribute to the project.


The powerful feature of Horntell is the web widget that can be placed on you website and can act as the notification center. Horntell Center listens for all the real-time notifications that are pushed from your backend and renders them on your site. Besides this, it also does a lot of non-onvious things like maintaining read/unread status of notifications, buffering unread notifications if you user is not currently online on your site, etc.
Tip: It’s best to get your technology team do this integration for you. It will take a couple of minutes for them to do this.
-
When you first log in you account, you will see a switch in top-right corner of your account which lets you switch between Live and Test environments. Use test environment when working locally and live environment in production.
-
Once the environment is set, you need to find the integration code by clicking on your app’s name in top-right corner and then clicking on Settings. Under the Integrate tab, you will find the API keys and integration code.
-
You will need to paste the widget code in the webpage where you want to show notifications. As the notifications are based on the logged-in user in your app, you will need to fill the values in these variables dynamically using the server-side language that you are using.
- uid: This is the unique identifier for the user in your app. (Primary Key)
- uid_hash: This is the HMAC SHA256 hash of profile’s uid with your app’s secret key.
-
Besides these required parameters, you can also send the optional data that you want to keep in the profile. More information about various profile attributes can be found at: http://docs.horntell.com/api/#profiles.
Note: In the JS code snippet, the variable __ht.app
will already be initialized with correct value for your account. You do NOT need to alter this variable.
Now, you’ve got the Horntell Center working, let’s send our first push notification.


I was hanging out at a lowkey party and had an interest in trying Salvia. I had tried to concoct a morning glory extract dissolved in 3 shots of whiskey earlier and drank it about two hours earlier, but it had no effect, and I'm assuming it had no effect on the salvia experience. My friend had some 15x extract lying around so I decided to try it.
I was in a second story room with a few friends watching me with a black light on. He loaded the pipe and handed the lighter to me. I was a bit apprehensive, my heart pounding in nervousness and excitement, but finally calmed down and lit the herb. I inhaled to almost full capacity, held it... then it hit. I don't even remember exhaling the smoke. Instantly, reality twisted away into oblivion, downwards and to the right. Images of reality stuttered and repeated infinitely. I completely forgot I had smoked anything, and I guess I fought a little bit to control it, but no luck of course. Time was obliterated. I remember feeling the pipe drop from my fingers. It came on so fast, it was like being hit in the head with a hammer and left to reel from the impact.
I kept trying to comprehend the whole experience, and it seemed like a very odd dream. I'm told that during the experience I was grasping at the air. The taste of the extract lingered in my mouth and I kept thinking I was drowning in reality. At one point, after I had dropped the pipe, I supposedly picked it up and cradled it like a child. I remember trying to talk, because everyone was just silent and watching me. I couldn't hear myself talk at all, and I could barely hear them talk. The silence was unnerving and I really wanted them to talk, but I couldn't even make the thought.
I was beginning to get hot, so I supposedly said, 'I've just opened the door!' and then 20 seconds later I fling open the door and almost run out of the room. I don't remember going down the stairs at all, and people tell me I almost fell down. I remember two still frames of reality as I make my way down a hallway and past a group of kids I don't even know. I make it into a well lighted room with some couches and just kind of sit down. Everything is still spinning and I'm still trying to comprehend it. By this point, I still don't know I had smoked it.
My friends came to see how I was doing and I asked how long it had been. What seemed like 3 minutes in the black lit room was actually something like fifteen. Once everything stopped spinning and twisting, I finally remembered I had smoked it. Needless to say, it was a very intense experience, one which I was not ready for. I plan on trying the 5x and 10x extracts before trying the 15x again.
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


Dominant Vinales storms to Malaysian MotoGP victory
Sepang - Spain's Maverick Vinales stormed to a dominant victory in the Malaysian MotoGP Sunday as world champion Marc Marquez fought his way from near the back of the starting grid to finish second.
Ducati rider Andrea Dovizioso came in third but there was disappointment for French rookie Fabio Quartararo, who only managed a lacklustre seventh-place after starting from pole.
Vinales's second win of the season was a major boost following last week's Australian MotoGP, where he crashed out after leading for much of the race - and compatriot Marquez went on to win.
The Monster Energy Yamaha rider said the victory felt "amazing" after his disappointing performance in Phillip Island.
"In Phillip Island, I felt like I had the victory in my hands but I made a mistake and I crashed," he told reporters at the Sepang circuit following the penultimate race of the season.
"Here all weekend I've been very consistent. I knew if I got first place I had a chance to push, push and push."
The 24-year-old surged into an early lead at Sepang after starting second on the grid and never looked threatened.
By the halfway mark, he had opened up a two second lead over second-placed Marquez, and was over three seconds ahead of him when he crossed the finish line.
Marquez's performance was even more astonishing, however, after he started 11th on the grid following a terrifying crash in qualifying that saw him thrown from his bike.
Within a few laps the Repsol Honda rider, who was crowned world champion for the sixth time last month, had smashed his way through the pack and was trying to chase down Vinales.
While he did not manage to catch his compatriot, Marquez nevertheless opened up a sizeable gap with the rest of the field and cruised to a comfortable second place.
The 26-year-old said the first lap, which catapulted him to the front, was "incredible" and congratulated his team for the good result.
"We started from 11th, and we cannot forget that here normally we struggle a lot," he said.
As well as the rider's title, Marquez has helped secure the constructor's championship for Honda this season.
And on Sunday, he added another record to his list - the most points scored in a season in motorcycling's premier class.
He has now racked up 395, higher than the previous record of 383 held by three-time world champion Jorge Lorenzo.
There was a tough fight for third place between Italy's Dovizioso, who won at Sepang in 2016 and 2017, and nine-time world champion Valentino Rossi.
Rossi managed to push past Dovizioso on several occasions, only for the Ducati rider to snatch the lead back and finish just ahead of his compatriot.
Quartararo had dominated all weekend going into the MotoGP, topping the timesheets in practice and smashing the Sepang lap record, before seizing his fifth pole position of the season.
The 20-year-old Petronas Yamaha rider had been aiming for his maiden MotoGP victory - but in the event, he was no match for his more experienced rivals and fell to the back right at the start.
The MotoGP in tropical Malaysia has often been disrupted by torrential downpours in previous years but the rain stayed away this year for the whole weekend.
In the Moto2 class, Alex Marquez - Marc's younger brother - was crowned world champion after finishing second in his race Sunday.
Results and standings after the Malaysian MotoGP at Sepang, the 18th of the 19-round world championship series, on Sunday:
1. Maverick Vinales (ITA/Yamaha) 40 min 14.632 sec, 2. Marc Marquez (ESP/Honda) at 3.059sec, 3. Andrea Dovizioso (ITA/Ducati) 5.611, 4. Valentino Rossi (ITA/Yamaha) 5.965, 5. Alex Rins (ESP/Suzuki) 6.350, 6. Franco Morbidelli (ITA/Yamaha-SRT) 9.993, 7. Fabio Quartararo (FRA/Yamaha-SRT) 12.864, 8. Jack Miller (AUS/Ducato-Pramac) 17.252, 9. Danilo Petrucci (ITA/Ducati) 19.773, 10. Joan Mir (ESP/Suzuki) 22.854
World championship standings:
1. Marc Marquez (ESP/Honda) 395 pts, 2. Andrea Dovizioso (ITA/Ducati) 256, 3. Maverick Vinales (ESP/Yamaha) 201, 4. Alex Rins (ESP/Suzuki) 194, 5. Danilo Petrucci (ITA/Ducati) 176, 6. Fabio Quartararo (FRA/Yamaha-SRT) 172, 7. Valentino Rossi (ITA/Yamaha) 166, 8. Jack Miller (AUS/Ducati) 149, 9. Cal Crutchlow (GBR/Honda) 133, 10. Franco Morbidelli (ITA/Yamaha) 115
Moto2
1. Brad Binder (RSA/KTM) 38min 7.843sec, 2. Alex Marquez (ESP/Kalex) at 0.758sec, 3. Thomas Luethi (SUI/Kalex) 2.683, 4. Xavi Vierge (ESP/Kalex) 6.646, 5. Jorge Navarro (ESP/Speed up) 7.114
Overall standings
1. Alex Marquez (ESP/Kalex) 262 pts, 2. Brad Binder (RSA/KTM) 234, 3. Thomas Luethi (SUI/Kalex) 230, 4. Jorge Navarro (ESP/SpeedUp) 210, 5. Augusto Fernandez (ESP/Kalex) 197
Moto3
1. Lorenzo Dalla Porta (ITA/Honda) 38min 1.355sec, 2. Sergio Garcia (ESP/Honda) at 0.410sec, 3. Jaume Masia (ESP/KTM) 0.803, 4, Ai Ogura (JPN/HONDA) 0.885, 5. Celestino Vietti (ITA/KTM) 0.902
Overall standings:
1. Lorenzo Dalla Porta (ITA/Honda) 279 pts, 2. Aron Canet (ESP/KTM) 190, 3. Tony Arbolino (ITA/Honda) 175, 4. Marcos Ramirez (ESP/Honda) 174, 5. John McPhee (GBR/Honda) 156


Hi there. My name is Grace. I'm a Midwest native and recent graduate of Indiana University's journalism program. I'm living in Phoenix, Arizona, and working as a reporter at the Arizona Republic. When I'm not telling stories, I enjoy hiking, baking, traveling (the picture above was taken in Monument Valley, Utah) and catching up on my favorite reality TV shows.
Indiana University - B.A. in Journalism
Pulliam Fellow, The Arizona Republic
June 2017 - Sept. 2017
News Reporter, Indiana Daily Student
Aug. 2013 - May 2017
Reporting Intern, Indianapolis Monthly
Aug. 2016 - Dec. 2016
Newsletter Intern, IU Communications
May 2016 - August 2016
Managing Editor, Indiana Daily Student
Aug. 2015 - Dec. 2015
General Assignments Reporter, Monticello Herald Journal
May 2015 - July 2015
1st place, Keating Feature Writing Competition
Fall 2015
Pat Siddons Indiana Daily Student scholarship for involvement in student media
Spring 2016
IU Media School Ambassador
2016-2017
Top 10, Hearst National Sports Writing Competition


What Ruiz’s Defeat Did To Me – Joshua
by Ridwan YusufBriton Anthony Joshua said his first career defeat at the hands of Andy Ruiz Jr. was due to a lack of experience and he had become a “smarter” fighter ahead of December’s rematch.
Concise News reports that Mexican-American Ruiz produced one of boxing’s biggest upsets when he dethroned the previously undefeated world heavyweight champion with a seventh-round stoppage at New York’s Madison Square Garden in June.
“It wasn’t burnout. The issues I faced in the last camp, it’s just down to lack of experience,” he told BBC.
“Even though it was at a high level, we were still finding experience.
“Andy Ruiz is good but I don’t think he should beat me twice. I used to hear guys say you have to take a loss and I would think ‘why’?
“Now I can understand it and know what it takes. I have more understanding now and my ears are open to new information so that’s making me smarter as a fighter,” Joshua said.
The WBA, IBF and WBO heavyweight title rematch – dubbed the ‘Clash on the Dunes’, will take place in Saudi Arabia on Dec. 7 after former Olympic Champion Joshua triggered a rematch clause.
“The blessing is I have a second chance and here we are,” the 30-year-old said.


---
layout: legacy
custom_js:
- workshop.bundle.js
---
{% include legacy/navigation.html %}
{% assign workshop = page.workshop %}
{% assign speaker = site.data.speakers.2017.speakers | where:"url", workshop.speaker | first %}
{% assign speakerName = speaker.first_name | append: ' ' | append: speaker.last_name %}
{% assign speakerImg = speaker.first_name | append: '_' | append: speaker.last_name %}
- DEVit 2017
- Workshops
- {{ workshop.title }}
{% if workshop.type == "allDay" %}
- All day Workshop Ticket price: €250
- Limited to 25 seats / workshop.
- Schedule: 11:00 AM - 8:00 PM. Registration will start at 10:00 AM.
{% endif %}
- Coffee and drinks during the day, lunch will be all provided.
- Please note that a computer will not be provided, so please bring your own laptop to the workshop.
{{ workshop.title }}
| Instructor |
{{ speakerName }} |
| Skill Level |
{{ workshop.skill }} |
| Prerequisites |
{{ workshop.prerequisites }} |
| Description |
{{ workshop.description }} |
{% if workshop.type == "allDay" %}
{% endif %}
This workshop covers:
{% for cover in workshop.covers %}
- {{ cover }}
{% endfor %}
{% include legacy/footer.html %}


Terms: The Landlord represents and warrants that they have the authority and permission to
lease out the said parking space listed above.
The Tenant represents and warrants that they live in the Premise listed above.
The Landlord assumes no responsibility for any damage to person or property arising out of this rental.
The Tenant agrees to abide by all by-laws of the condominium corporation and will follow any notices given
by the condo corporation in regards to the parking spot and/or garage.
The rental unit cannot be sublet, assigned, or transferred. Only the car listed above shall have the right
to park in the spot.
Should a garage door opener/access/card/FOB be needed to enter the garage, the Landlord agrees to provide
the Tenant with said access. A Hundred Dollar ($100) deposit cheque will be required at the start of the
lease. The deposit will be returned at the end of the lease provided all garage door opener/access card/FOB
are returned without damage (save for normal wear and tear).
Either the Tenant or the Landlord may terminate this Agreement by providing Two (2) months notice to the
other. On termination of this agreement any refund owed of advance payment, deposits, and/or the returning
of
cheques in the Landlords possession must be completed within 14 days. Any unpaid rental amounts must be paid
within 7 days.


What’s that good sir? You’d like some news… but you don’t have time today to read it all…. hmmm… Can I help with that? Well, I do believe I can. I have this thing called Meme the News. You’ll get a healthy dose of the news along with some critical thinking skills. Warning: MtN may cause cognitive dissonance, cleft toes, and aural oblivion.
This will solve everything
Majestic-12
Elite prefer Cosby to Trump
Why doesn’t he start every conversation this way?
No more war!
oh look, Americans released from NK
I believe this to be true
it’s like this plan has been around for a while
Blacks free thinking is now supremacist and nazi?!?
The gender nuetral furry scouts sounds awesome…

When they see the sign they will be compelled to lay down their arms because people that shoot at children will obey a sign
Read between the lines
Moar NASA hacks
This guy…
Trillions of apple slices go unaccouted for every year,..
This needs to haplpen
Thanos did Harambe
Funny if it wasn’t true so often
This page is synchronized from the post: ‘Meme the News 5/4/18’


Fits the Fused Lasso Latent Feature model, which is used for modeling multi-sample aCGH data to identify regions of copy number variation (CNV). Produces a set of features that describe the patterns of CNV and a set of weights that describe the composition of each sample. Also provides functions for choosing the optimal tuning parameters and the appropriate number of features, and for estimating the false discovery rate.
| Version: | 1.2-1 |
| Imports: | graphics, stats, gplots |
| Published: | 2017-05-23 |
| Author: | Gen Nowak [aut, cre], Trevor Hastie [aut], Jonathan R. Pollack [aut], Robert Tibshirani [aut], Nicholas Johnson [aut] |
| Maintainer: | Gen Nowak <gen.nowak at gmail.com> |
| License: | GPL-2 | GPL-3 [expanded from: GPL (≥ 2)] |
| NeedsCompilation: | yes |
| Materials: | NEWS |
| CRAN checks: | FLLat results |
| Reference manual: | FLLat.pdf |
| Vignettes: |
FLLat Tutorial |
| Package source: | FLLat_1.2-1.tar.gz |
| Windows binaries: | r-devel: FLLat_1.2-1.zip, r-release: FLLat_1.2-1.zip, r-oldrel: FLLat_1.2-1.zip |
| OS X binaries: | r-release: FLLat_1.2-1.tgz, r-oldrel: FLLat_1.2-1.tgz |
| Old sources: | FLLat archive |
Please use the canonical form https://CRAN.R-project.org/package=FLLat to link to this page.


| DOSE: T+ 0:00 |
1 cup |
oral |
Kava |
(tea) |
| T+ 2:00 |
1 cup |
oral |
Kava |
(tea) |
| T+ 5:00 |
2 cups |
oral |
Kava |
(tea) |
| T+ 6:00 |
1 cup |
oral |
Kava |
(tea) |
| T+ 22:00 |
4 cups |
oral |
Kava |
(tea) |
I bought a package of kava tea from my local grocery store, 16 packages of 78mg's each (other plants were already in the tea--roots to give it a drinkable taste; cinnamon and jamacian something root.)
Around 12:30-1:00 after taking a shower;
I drank an 8oz cup with two tea bags (156 mg). I put on 'Ambient 1 - Music for Airports' by Brian Eno and relaxed. Within 5-10 mins my throat had more of a burning (pleasently warm though) feeling rather than a numb one (As most people report). It was pretty close to being numb, (usually higher doses have stronger effects-). Since this drug is very subtle, I won't report my effects in chronological order, but in general how I felt during and after I ingested the tea.
-Comes in small waves (on and off)
-warmness in body
-subtle changes of perception (feeling peaceful, less worrysome)
-Relaxing feeling, could fall asleep easier than ever.
-Focused. Could concentrate better.
-Music seemed much more flowing.
I noticed all these things by relaxing and really paying attention to the effects of the kava. These effects are not strong, but subtle, very, very subtle.
At 3:00;
I drank another cup with two bags of tea (another 156 mg). Relaxed and played a lot of music, things seemed to flow better, could focus on what I wanted to do. Same effects as before, no more intense or less intense, same.
At 6:00;
Drank another two. No change in effects.
At 7:00;
Drank another cup of two bags of tea. This time, (I'm not sure if it's from all the other kava tea I drank before, but) I felt much more relaxed, peaceful, warm. The effects seemed intensified. I didn't drink anymore tea, I felt very relaxed, peaceful, focused and content.
Fell alseep at 11:00 after having band practice. I Remember having a very peaceful sleep, and it was very easy to sleep. At around 11:00 the next morning, I was still feeling the effects, but to a much lesser extent. I drank four cups of tea this time, all at once. Four tea bags in 8oz of water. I talked to my friend a little bit afterwards, said my goodbyes and started my walk home.
The best part about kava is it's subtlies, and it's waves come and sneak up on you---
As I walked home, I was very introspective about everything. Everything seemed very, well, balanced. Not quite euphoria (well, to a small extent). Walking was nice, did not become tired at all of walking. The sun felt like pure warmth against my skin, quite an amazing feeling. Even though it was hot outside, My body seemed to not mind as much as it usually would. Even though there were some things I could complain about usually, I didn't. I just felt as if it were trival and I can enjoy life anyways, even though there are these small factors. I didn't drink anymore tea because I was pretty content for the rest of the day. I just relaxed with my friend.
All in all, Kava's effects are enjoyable when they can be noticed. Kava is not like any other drug. It's not a substitute for getting stoned- it's not a sub. for anything, it's effects are diffrent than weed or opium, it's a completly diffrent feeling. I will likely drink Kava tea once in a while before I go outside for a walk, or if I feel like a peaceful day. If I am busy doing something, I don't quite notice the effects as much.
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


tumblr the game is a pop culture game wherein you guess the common tag for a set of images.
As all images are sourced from the latest posts on tumblr, we are not responsible for the contents of each game. We are sorry for any duplicate images, or any unrelated images, and especially sorry if any pornography shows up.
Try to get a high score, and share with your friends!
tumblr the game was created by Rita and Daniel. Follow them on Tumblr!
This application uses the Tumblr application programming interface but is not endorsed or certified by Tumblr, Inc. All of the Tumblr logos and trademarks displayed on this application are the property of Tumblr, Inc.
Close


Warning: Remember this is a very early release so there's a lot of things that just don't work.
This is not an explanation about the Pascal language. This document just explains differences between Standard Pascal and the current compiled language.
Current version compiles a very limited subset of the Pascal language.
Current version of the compiler supports Pascal comments ({ .. }
and (* .. *)
). It doesn't support C++ style comments, so don't use them.
ASM .. END
Z80-Pascal introduces a block that allows to add Z80 Assembler code inside the Pascal sources. For example:
ASM
LD A, 65;
CALL $00A2;
END;
There are some issues you must to know:
$
character, just as Pascal ones. Warning: Current version doesn't support negative numbers.


"CHERETHIM "(Ezekiel 25:16), more frequently Cherethites, the inhabitants of Southern Philistia, the Philistines (Zephaniah 2:5). The Cherethites and the Pelethites were David’s life-guards (1 Samuel 30:14; 2 Samuel 8:18; 20:7, 23; 23:23). This name is by some interpreted as meaning “Cretans,” and by others “executioners,” who were ready to execute the king’s sentence of death (Genesis 37:36, marg.; 1 Kings 2:25).
"CHERETHIM "(Ezekiel 25:16), more frequently Cherethites, the inhabitants of Southern Philistia, the Philistines (Zephaniah 2:5). The Cherethites and the Pelethites were David’s life-guards (1 Samuel 30:14; 2 Samuel 8:18; 20:7, 23; 23:23). This name is by some interpreted as meaning “Cretans,” and by others “executioners,” who were ready to execute the king’s sentence of death (Genesis 37:36, marg.; 1 Kings 2:25).


Is Always Be Your Place
Is Always Be Your Place Have been very well known in the early 90’s, My Place is back to town to be a leading entertainment venue in Malang. The metamorphosis of My Place that turned into “She Pub” then finally Re-Born as My Place, after found its perfect shape of entertainment center, has given more power to gather the entertainment seeker around Malang even more in East Java. Completed with 9 deluxe room and 2 suite karaoke room, My Place gave a new breeze of entertainment concept. My Place karaoke will indulge you with wide selection of music, comfortable room which are design differently, careful selection of Food & Beverage menus as well as room amenities
At My Place bar, you will enjoy most everything that people visit a nightclub for (the great vibe, good music, drinks, and, of course, plenty of good looking women dancing on the floor), but typically won’t have to deal with the headaches of the long lines, packed bars, and over-crowded...
Read MoreMY KTV
Each room equipped with uptodate best karaoke audio and each room are equipped with 42inch wide LCD,best room interior, lighting and temperature. We also have approx 50.500 music bank and we keep it update every month...
Read MoreMY HOUSE KICKERS
FIVE MINUTES Kalo emang ngerasa fit tapi malemnya kurang asik or masih ngebikin bete, gak ada salahnya nyobain minuman yang satu ini. Yang isinya campuran dari vodka, rum, dry din, tequila, triple sec, whisky, southern...
Read MoreMY HOUSE KICKERS
FIVE MINUTES Kalo emang ngerasa fit tapi malemnya kurang asik or masih ngebikin bete, gak ada salahnya nyobain minuman yang satu ini. Yang isinya campuran dari vodka, rum, dry din, tequila, triple sec, whisky, southern...
Read MoreLast Event
Follow Us
Tweet oleh @MyPlaceMalangContact
Jln. Jaksa Agung Suprapto 17, Malang, Jawa Timur
Email<EMAIL_ADDRESS>Telephone : (0341) 352 209


| < Day Day Up > |
Hack 99 Useful One-Liners
Unix is amazing. Only your imagination limits the usefulness of the built-in commands. You can create your own commands and then pipe them together, allowing one utility to work on the results of another.  Here are some of my favorite one-liners, intended to demonstrate useful ideas as well as to prime your pump for writing your own one-liner hacks. 9.12.1 Simultaneously Download and UntarHave you ever downloaded an extremely large archive over a slow connection? It seems to take forever to receive the archive and forever to untar it. Being impatient, I hate not knowing how many of the archived files are already here. I miss the ability to work on those files while the rest of the archive finishes its slow migration onto my system. This one-liner will decompress and untar the files as the archive downloads, without interfering with the download. Here's an example of downloading and untarring the ports collection: # tail -f -b=1m ports.tar.gz | tar -zxvf ports.tar.gz ports/ ports/Mk/ <snip> Here I've asked tail to stream up to one megabyte of the specified file as it is received. It will pipe those bytes to the tar utility, which I've directed to decompress (-z) and to extract (x) the specified file (f) while displaying the results verbosely (v). To use this command, download the archive to where you'd like to untar it—in this example, /usr. Simply replace the filename ports.tar.gz with the name of your archive. 9.12.2 When Did I Change That File?Do you ever need to know the last modification date of a file? Consider a long listing: % ls -l filename -rw-r--r-- 1 dru wheel 12962 Dec 16 18:01 filename If you count the fields, the sixth (Dec), seventh (16), and eighth (18:01) fields all contain part of the modification date. However, there's whitespace separating those fields, which makes it difficult to determine their exact character positions. Fortunately, awk doesn't mind variable whitespace, so this one-liner will always work: % echo filename was last modified on `/bin/ls -l filename \ | awk '{print $6, $7, $8}'` filename was last modified on Dec 16 18:01 Here I've asked echo to repeat a string as well as the results of a command contained within single quotes. The first half of that command is simply ls -l filename. I've piped the output of that command to awk, which will print the sixth ($6), seventh ($7), and eighth ($8) fields of the long listing. Note that the awk action is enclosed between '{ }'. While this is a useful one-liner, it is fairly awkward to type as needed. However, if you replace filename with a positional parameter [Hack #13], you have a very handy script. I'll call mine when: % more ~/bin/when #!/bin/sh # script to list date of a file's last modification # replaces $1 with specified filename # or gives error message if user forgets to include filename if test $1 then echo $1 was last modified on `/bin/ls -l $1| awk '{print $6, $7, $8}'` else echo "Don't forget the name of the file you're interested in" exit 1 fi Once you've made your script executable, use when filename to find the date of a file's most recent modification. 9.12.3 Finding SymlinksIf you ever need to find symbolic links, you're in luck. find's -type l or link option serves just this purpose. Start with this invocation: % find /etc -type l -ls 25298 0 lrwxrwxrwx 1 root wheel 23 Apr 7 2003 /etc/termcap -> /usr/share/misc/termcap 25299 0 lrwxrwxrwx 1 root wheel 13 Apr 7 2003 /etc/rmt -> /usr/sbin/rmt 25301 0 lrwxrwxrwx 1 root wheel 12 Apr 7 2003 /etc/aliases -> mail/aliases 25305 0 lrwxr-xr-x 1 root wheel 36 Oct 26 09:08 /etc/localtime -> /usr/share/zoneinfo/America/Montreal Well, that worked, but the output is downright ugly. Let's pipe the results to our good friend awk to display only the last three fields. If you count them, those are fields 11 through 13: % find /etc -type l -ls | awk '{print $11, $12, $13}' /etc/termcap -> /usr/share/misc/termcap /etc/rmt -> /usr/sbin/rmt /etc/aliases -> mail/aliases /etc/localtime -> /usr/share/zoneinfo/America/Montreal Aah, much better. If you ever plan on needing to find symlinks, it's well worth saving this in a shell script similar to the when script shown previously. 9.12.4 Making cron More User-FriendlyAre you always forgetting the meanings of the various fields in a crontab? It would probably be a lot easier if your crontab began like this: # minute (0-59), # | hour (0-23), # | | day of the month (1-31), # | | | month of the year (1-12), # | | | | day of the week (0-6 with 0=Sunday). # | | | | | commands 3 2 * * 0,6 /some/command/to/run To achieve that, type those lines into a text file, say ~/cronheader. (Be patient, we're getting to the one-liner.) Then, open up your crontab editor: % crontab -e Unless you've changed your default editor, this will open up your crontab using vi. Place your cursor at the beginning of the file, and type the following: !!more /usr/home/dru/cronheader The !! tells vi to insert the output of the specified command. Be sure to give the full pathname to your file. vi will insert its contents for you once you press Enter. When you're finished, type :wq as usual to exit the editor. 9.12.5 See Also
|
| < Day Day Up > |


this settings page contains various network related settings
Proxy server
here you may specify a http proxy server to be used for network requests if desired
(no "http://" prefix, just the plain server name)
Proxy port
here you may specify the port the proxy server is listening to
Proxy user name
here you may set the user name for autentification to the proxy server (if required)
Proxy password
here ou may set the password for autentification to the proxy server (if required).
NOTE: the password is never stored/restored. you have to reenter it in any new TableCrab
session
Fetch timeout
here you may adjust the time TableCrab tries to fetch a network request before giving up (in seconds)