Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #33905 > unrolled thread
| Started by | ALeX inSide <alex.b.inside@gmail.com> |
|---|---|
| First post | 2012-11-25 04:11 -0800 |
| Last post | 2012-11-26 17:14 -0800 |
| Articles | 16 — 10 participants |
Back to article view | Back to comp.lang.python
How to pass class instance to a method? ALeX inSide <alex.b.inside@gmail.com> - 2012-11-25 04:11 -0800
Re: How to pass class instance to a method? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-25 12:37 +0000
Re: How to pass class instance to a method? Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2012-11-26 11:22 +1300
Re: How to pass class instance to a method? Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2012-11-26 11:08 +0100
Re: How to pass class instance to a method? Nobody <nobody@nowhere.com> - 2012-11-26 16:56 +0000
Re: How to pass class instance to a method? Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-26 13:51 -0700
Re: How to pass class instance to a method? Dave Angel <d@davea.name> - 2012-11-26 16:58 -0500
Re: How to pass class instance to a method? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-26 22:18 +0000
Re: How to pass class instance to a method? Dave Angel <d@davea.name> - 2012-11-26 22:14 -0500
Re: How to pass class instance to a method? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-27 04:10 +0000
Re: How to pass class instance to a method? Roy Smith <roy@panix.com> - 2012-11-26 23:25 -0500
Re: How to pass class instance to a method? Dave Angel <d@davea.name> - 2012-11-27 00:18 -0500
Re: How to pass class instance to a method? Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-26 16:07 -0700
Re: How to pass class instance to a method? Hans Mulder <hansmu@xs4all.nl> - 2012-11-27 01:36 +0100
Re: How to pass class instance to a method? Dave Angel <d@davea.name> - 2012-11-26 21:50 -0500
Re: How to pass class instance to a method? Drew <r.drew.davis@gmail.com> - 2012-11-26 17:14 -0800
| From | ALeX inSide <alex.b.inside@gmail.com> |
|---|---|
| Date | 2012-11-25 04:11 -0800 |
| Subject | How to pass class instance to a method? |
| Message-ID | <3193e3dd-0507-4ff7-9026-ee80e5d9c1dd@googlegroups.com> |
How to "statically type" an instance of class that I pass to a method of other instance? I suppose there shall be some kind of method decorator to treat an argument as an instance of class? Generally it is needed so IDE (PyCharm) can auto-complete instance's methods and properties. Pseudo-python-code example: i = MyClass() xxx(i, 1, 2); ... def xxx(self, MyClass myclass, number, foobar): myclass.classsmethod() #myclass - is an instance of known class
[toc] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2012-11-25 12:37 +0000 |
| Message-ID | <50b2110f$0$29994$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #33905 |
On Sun, 25 Nov 2012 04:11:29 -0800, ALeX inSide wrote: > How to "statically type" an instance of class that I pass to a method of > other instance? Please explain what you mean by this. What do you think "statically type" means? > I suppose there shall be some kind of method decorator to treat an > argument as an instance of class? Python does not allow you to lie about the type of an argument. All objects are strongly typed. If an object is a Spam instance, it is a Spam instance, you can't pretend that it is a Cheese instance.[1] > Generally it is needed so IDE (PyCharm) can auto-complete instance's > methods and properties. > > Pseudo-python-code example: > > i = MyClass() > > xxx(i, 1, 2); > > ... > def xxx(self, MyClass myclass, number, foobar): > myclass.classsmethod() #myclass - is an instance of known class I do not understand what you are saying here. Please try to explain more carefully. [1] You cannot lie about the type of an instance, but sometimes you can actually change its type. Use this feature with care, since it rarely is useful. -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Gregory Ewing <greg.ewing@canterbury.ac.nz> |
|---|---|
| Date | 2012-11-26 11:22 +1300 |
| Message-ID | <ahfk25Fg86jU1@mid.individual.net> |
| In reply to | #33905 |
ALeX inSide wrote:
> I suppose there shall be some kind of method decorator to treat an argument as an
> instance of class?
You can do this:
xxx = MyClass.some_method
and then
i = MyClass()
xxx(i, foo, bar)
Does that help?
--
Greg
[toc] | [prev] | [next] | [standalone]
| From | Alain Ketterlin <alain@dpt-info.u-strasbg.fr> |
|---|---|
| Date | 2012-11-26 11:08 +0100 |
| Message-ID | <87ip8s65i2.fsf@dpt-info.u-strasbg.fr> |
| In reply to | #33905 |
ALeX inSide <alex.b.inside@gmail.com> writes: > How to "statically type" an instance of class that I pass to a method > of other instance? Python does not do static typing. > I suppose there shall be some kind of method decorator to treat an > argument as an instance of class? Decorators are an option. Another is the use of the new parameter annotations (param : expr) in function/method parameters. (That's python 3, not 2). > Generally it is needed so IDE (PyCharm) can auto-complete instance's > methods and properties. You can't expect static info on the class of the object referenced by any name, unless you impose strong conventions on the code. > Pseudo-python-code example: > > i = MyClass() > > xxx(i, 1, 2); > > ... > def xxx(self, MyClass myclass, number, foobar): > myclass.classsmethod() #myclass - is an instance of known class Could: xxx(self,myclass : MyClass, ...) -- Alain.
[toc] | [prev] | [next] | [standalone]
| From | Nobody <nobody@nowhere.com> |
|---|---|
| Date | 2012-11-26 16:56 +0000 |
| Message-ID | <pan.2012.11.26.16.56.29.389000@nowhere.com> |
| In reply to | #33905 |
On Sun, 25 Nov 2012 04:11:29 -0800, ALeX inSide wrote:
> How to "statically type" an instance of class that I pass to a method of
> other instance?
Python isn't statically typed. You can explicitly check for a specific
type with e.g.:
if not isinstance(arg, SomeType):
raise TypeError('expected SomeType but got %s' % type(arg))
But this defeats duck typing. If you do this a lot, you're using the wrong
language.
> I suppose there shall be some kind of method decorator to treat an
> argument as an instance of class?
>
> Generally it is needed so IDE (PyCharm) can auto-complete instance's
> methods and properties.
You have it backwards.
In a dynamically-typed language such as Python, the set of acceptable
types for an argument is determined by the operations which the function
performs on it. This is in direct contrast to a statically-typed language,
where the set of acceptable operations on an argument is determined by the
type of the argument.
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2012-11-26 13:51 -0700 |
| Message-ID | <mailman.297.1353963109.29569.python-list@python.org> |
| In reply to | #33941 |
On Mon, Nov 26, 2012 at 9:56 AM, Nobody <nobody@nowhere.com> wrote: > In a dynamically-typed language such as Python, the set of acceptable > types for an argument is determined by the operations which the function > performs on it. This is in direct contrast to a statically-typed language, > where the set of acceptable operations on an argument is determined by the > type of the argument. Not how I would put it. In a statically typed language, types are checked at compile-time (which does not necessarily imply that useful type information can be made available to an IDE), whereas in a dynamically typed language, some or all type checking is deferred to run-time. The description that "the set of acceptable types for an argument is determined by the operations which the function performs on it" sounds to me more like type inference, as exemplified by Haskell, which is nonetheless a statically typed language.
[toc] | [prev] | [next] | [standalone]
| From | Dave Angel <d@davea.name> |
|---|---|
| Date | 2012-11-26 16:58 -0500 |
| Message-ID | <mailman.300.1353967142.29569.python-list@python.org> |
| In reply to | #33941 |
On 11/26/2012 03:51 PM, Ian Kelly wrote: > On Mon, Nov 26, 2012 at 9:56 AM, Nobody <nobody@nowhere.com> wrote: >> In a dynamically-typed language such as Python, the set of acceptable >> types for an argument is determined by the operations which the function >> performs on it. This is in direct contrast to a statically-typed language, >> where the set of acceptable operations on an argument is determined by the >> type of the argument. > Not how I would put it. In a statically typed language, types are > checked at compile-time (which does not necessarily imply that useful > type information can be made available to an IDE), whereas in a > dynamically typed language, some or all type checking is deferred to > run-time. Not how I would put it. In a statically typed language, the valid types are directly implied by the function parameter declarations, while in a dynamic language, they're defined in the documentation, and only enforced (if at all) by the body of the function. -- DaveA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2012-11-26 22:18 +0000 |
| Message-ID | <50b3eab5$0$29994$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #33948 |
On Mon, 26 Nov 2012 16:58:47 -0500, Dave Angel wrote:
> In a statically typed language, the valid types
> are directly implied by the function parameter declarations, while in a
> dynamic language, they're defined in the documentation, and only
> enforced (if at all) by the body of the function.
Well that certainly can't be true, because you can write functions
without *any* documentation at all, and hence no defined type
restrictions that could be enforced:
def trivial_example(x):
return x+1
No documentation, and so by your definition above this should be weakly
typed and operate on any type at all. Since there are no type
restrictions defined, the body cannot enforce those type restrictions.
But that's clearly not true.
Please, everybody, before replying to this thread, please read this:
http://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wrote/
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Dave Angel <d@davea.name> |
|---|---|
| Date | 2012-11-26 22:14 -0500 |
| Message-ID | <mailman.307.1353986116.29569.python-list@python.org> |
| In reply to | #33950 |
On 11/26/2012 05:18 PM, Steven D'Aprano wrote: > On Mon, 26 Nov 2012 16:58:47 -0500, Dave Angel wrote: > >> In a statically typed language, the valid types >> are directly implied by the function parameter declarations, while in a >> dynamic language, they're defined in the documentation, and only >> enforced (if at all) by the body of the function. > > Well that certainly can't be true, because you can write functions > without *any* documentation at all, and hence no defined type > restrictions that could be enforced: That's backwards. Any body should be a bug in that case. It doesn't matter what you pass to a function that is unspecified, it's behavior is undefined. Calling it is inherently illegal. > > def trivial_example(x): > return x+1 > > No documentation, and so by your definition above this should be weakly > typed and operate on any type at all. Since there are no type > restrictions defined, the body cannot enforce those type restrictions. > But that's clearly not true. > > Please, everybody, before replying to this thread, please read this: > > http://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wrote/ I read part of it, and it's more than I care to read tonight. It seems to be written by an anonymous person. By jumping around in his blog, I see a lot of interesting articles, but i haven't yet figured out who he is. Does he have a name? A degree, a job in computers, a reputation? -- DaveA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2012-11-27 04:10 +0000 |
| Message-ID | <50b43d48$0$21875$c3e8da3$76491128@news.astraweb.com> |
| In reply to | #33961 |
On Mon, 26 Nov 2012 22:14:59 -0500, Dave Angel wrote:
> On 11/26/2012 05:18 PM, Steven D'Aprano wrote:
>> On Mon, 26 Nov 2012 16:58:47 -0500, Dave Angel wrote:
>>
>>> In a statically typed language, the valid types are directly implied
>>> by the function parameter declarations, while in a dynamic language,
>>> they're defined in the documentation, and only enforced (if at all) by
>>> the body of the function.
>>
>> Well that certainly can't be true, because you can write functions
>> without *any* documentation at all, and hence no defined type
>> restrictions that could be enforced:
>
> That's backwards. Any body should be a bug in that case. It doesn't
> matter what you pass to a function that is unspecified, it's behavior is
> undefined. Calling it is inherently illegal.
Have you ever programmed before? *wink*
Seriously, as much as we would like to have full documentation of every
piece of code before it is written, such a thing is awfully heavyweight
for all but the biggest projects.
In practice, many functions never get documented at all, or only
partially documented. Whether this is a good thing or not, it is a fact,
and no mainstream language *requires* you to write documentation, nor is
the documentation is used to determine runtime behaviour. If it did, it
would be code, not documentation.
In lightweight or agile software development methodologies ("Bingo!") or
exploratory development, you often write the code before you know what it
does, or even what you want it to do. E.g. I'll sometimes have a vague
idea of what I want a function or method to do, and go through three or
four iterations of writing code before it is stable enough to begin
documenting it.
Given the practical reality that documentation is often neglected, there
is a school of thought that says that *code* is the One True source of
information about what the code does, that documentation is at best a
hint or at worst completely redundant. While I think that's a bit
extreme, I can see the point. If function f() puts the cat on the mat,
but is documented as putting the hat on the cat, how do you know whether
the documentation is wrong or the code?
[...]
>> Please, everybody, before replying to this thread, please read this:
>>
>> http://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wrote/
>
> I read part of it, and it's more than I care to read tonight. It seems
> to be written by an anonymous person. By jumping around in his blog, I
> see a lot of interesting articles, but i haven't yet figured out who he
> is. Does he have a name? A degree, a job in computers, a reputation?
Does it matter? Surely what he says should stand or fail on its own
merits, not by who he is.
He has a name, although it seems to be hard to find on his current blog:
Chris Smith. As for the rest, I don't know.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2012-11-26 23:25 -0500 |
| Message-ID | <roy-B2BD3D.23254826112012@news.panix.com> |
| In reply to | #33963 |
Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > Given the practical reality that documentation is often neglected, there > is a school of thought that says that *code* is the One True source of > information about what the code does, that documentation is at best a > hint or at worst completely redundant. Yes, there is such a school. Those people are full of bovine excrement. > If function f() puts the cat on the mat, but is documented as putting > the hat on the cat, how do you know whether the documentation is > wrong or the code? Documentation should describe intent and interface. Yes, the code says what the code does. But, the interface description says what it's supposed to do. Can the docs be wrong? Of course they can. Usually because somebody changed the code and didn't bother to change the docs. My take on people who never document anything is that they're just plain lazy. Go ahead, ask me how I really feel about the topic :-)
[toc] | [prev] | [next] | [standalone]
| From | Dave Angel <d@davea.name> |
|---|---|
| Date | 2012-11-27 00:18 -0500 |
| Message-ID | <mailman.309.1353993554.29569.python-list@python.org> |
| In reply to | #33963 |
On 11/26/2012 11:10 PM, Steven D'Aprano wrote:
> On Mon, 26 Nov 2012 22:14:59 -0500, Dave Angel wrote:
>
>> On 11/26/2012 05:18 PM, Steven D'Aprano wrote:
>>> On Mon, 26 Nov 2012 16:58:47 -0500, Dave Angel wrote:
>>>
>>>> In a statically typed language, the valid types are directly implied
>>>> by the function parameter declarations, while in a dynamic language,
>>>> they're defined in the documentation, and only enforced (if at all) by
>>>> the body of the function.
>>> Well that certainly can't be true, because you can write functions
>>> without *any* documentation at all, and hence no defined type
>>> restrictions that could be enforced:
>> That's backwards. Any body should be a bug in that case. It doesn't
>> matter what you pass to a function that is unspecified, it's behavior is
>> undefined. Calling it is inherently illegal.
> Have you ever programmed before? *wink*
I think you know the answer to that. But for anyone else, I've been in
various aspects of software development for 42 years, longer if you
count various projects which were not turned into products. And the
approximately dozen patents were nearly all for things which shipped,
not just theoretical concepts.
>
> Seriously, as much as we would like to have full documentation of every
> piece of code before it is written, such a thing is awfully heavyweight
> for all but the biggest projects.
>
> In practice, many functions never get documented at all, or only
> partially documented. Whether this is a good thing or not, it is a fact,
> and no mainstream language *requires* you to write documentation, nor is
> the documentation is used to determine runtime behaviour. If it did, it
> would be code, not documentation.
>
> In lightweight or agile software development methodologies ("Bingo!") or
> exploratory development, you often write the code before you know what it
> does, or even what you want it to do. E.g. I'll sometimes have a vague
> idea of what I want a function or method to do, and go through three or
> four iterations of writing code before it is stable enough to begin
> documenting it.
>
> Given the practical reality that documentation is often neglected, there
> is a school of thought that says that *code* is the One True source of
> information about what the code does, that documentation is at best a
> hint or at worst completely redundant. While I think that's a bit
> extreme, I can see the point. If function f() puts the cat on the mat,
> but is documented as putting the hat on the cat, how do you know whether
> the documentation is wrong or the code?
Yes, and yes. They're both wrong. Function f() is just broken.
Especially it's name.
I know all that, and wasn't trying to pretend that documentation is
always or even frequently, adequate. But the bulk of this part of the
thread has been dealing with a function call, contrasting static typing,
where some work is done by the compiler, and dynamic typing, where
supposedly something is done by the interpreter. And I claim that the
interpreter cannot in general do anything at the call target, except
count the number of the arguments (maybe) and check the keywords. So
the only thing that can be done there is manual - check the docs. If
they're not there, there's just no comparison with the static case. And
for a non-trivial function, or generally one which calls non-trivial
functions, exhaustively analyzing the code of the function, and of the
function it calls, is impractical. So people just call the function and
hope.
Static typing isn't nearly enough, and therefore the feeling of security
it gives many is dangerously misleading. There have been (and
presumably still are) languages which allow subsets of types to be
explicitly declared, for example the type is int, but the restriction is
nonnegative int (eg. square root). Or the type is int, but the
restriction is between 4 and 7. Or the parameters have an
interrelationship, or a dependency on the system state: e.g. if the
first parameter is a string, then the second one must be one of 8
specific strings.
>
> [...]
>>> Please, everybody, before replying to this thread, please read this:
>>>
>>> http://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wrote/
>> I read part of it, and it's more than I care to read tonight. It seems
>> to be written by an anonymous person. By jumping around in his blog, I
>> see a lot of interesting articles, but i haven't yet figured out who he
>> is. Does he have a name? A degree, a job in computers, a reputation?
> Does it matter? Surely what he says should stand or fail on its own
> merits, not by who he is.
Yes, but since it's very hard slugging at first, I was curious if it
would be worth it. He uses a number of terms in ways foreign to my
background, and while I admire Humpty-Dumpty-ism, it certainly slows
down comprehension. Anyway, he's apparently got a reputation with you,
and that alone should make it worth the trouble. Just not tonight.
> He has a name, although it seems to be hard to find on his current blog:
> Chris Smith. As for the rest, I don't know.
>
>
One of the brightest people I've ever known is named Smith. But come to
think of it, that's a pretty common surname.
--
DaveA
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2012-11-26 16:07 -0700 |
| Message-ID | <mailman.304.1353971263.29569.python-list@python.org> |
| In reply to | #33941 |
On Mon, Nov 26, 2012 at 2:58 PM, Dave Angel <d@davea.name> wrote: > Not how I would put it. In a statically typed language, the valid types > are directly implied by the function parameter declarations, As alluded to in my previous post, not all statically typed languages require parameter type declarations to perform static checking. > while in a > dynamic language, they're defined in the documentation, and only > enforced (if at all) by the body of the function. That's not even true for Python. The following example uses Python 2.x: >>> class Foo(object): ... def method(self): ... pass ... >>> Foo.method(4) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method method() must be called with Foo instance as first argument (got int instance instead) That's a run-time check, and it's not enforced by the body of the function.
[toc] | [prev] | [next] | [standalone]
| From | Hans Mulder <hansmu@xs4all.nl> |
|---|---|
| Date | 2012-11-27 01:36 +0100 |
| Message-ID | <50b40af5$0$6973$e4fe514c@news2.news.xs4all.nl> |
| In reply to | #33954 |
On 27/11/12 00:07:10, Ian Kelly wrote: > On Mon, Nov 26, 2012 at 2:58 PM, Dave Angel <d@davea.name> wrote: >> Not how I would put it. In a statically typed language, the valid types >> are directly implied by the function parameter declarations, > > As alluded to in my previous post, not all statically typed languages > require parameter type declarations to perform static checking. > >> while in a >> dynamic language, they're defined in the documentation, and only >> enforced (if at all) by the body of the function. > > That's not even true for Python. The following example uses Python 2.x: > >>>> class Foo(object): > ... def method(self): > ... pass > ... >>>> Foo.method(4) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: unbound method method() must be called with Foo instance as > first argument (got int instance instead) > > That's a run-time check, and it's not enforced by the body of the function. As Ian already knows, this problem has been fixed in Python 3. -- HansM
[toc] | [prev] | [next] | [standalone]
| From | Dave Angel <d@davea.name> |
|---|---|
| Date | 2012-11-26 21:50 -0500 |
| Message-ID | <mailman.306.1353984622.29569.python-list@python.org> |
| In reply to | #33941 |
On 11/26/2012 06:07 PM, Ian Kelly wrote: > On Mon, Nov 26, 2012 at 2:58 PM, Dave Angel <d@davea.name> wrote: >> Not how I would put it. In a statically typed language, the valid types >> are directly implied by the function parameter declarations, > As alluded to in my previous post, not all statically typed languages > require parameter type declarations to perform static checking. > >> while in a >> dynamic language, they're defined in the documentation, and only >> enforced (if at all) by the body of the function. > That's not even true for Python. The following example uses Python 2.x: > >>>> class Foo(object): > ... def method(self): > ... pass > ... >>>> Foo.method(4) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: unbound method method() must be called with Foo instance as > first argument (got int instance instead) > > That's a run-time check, and it's not enforced by the body of the function. We were talking about function arguments. I don't know of any place where they get their types declared. -- DaveA
[toc] | [prev] | [next] | [standalone]
| From | Drew <r.drew.davis@gmail.com> |
|---|---|
| Date | 2012-11-26 17:14 -0800 |
| Message-ID | <9ea139f7-7be9-4e39-81e2-06fbef7a2cb8@googlegroups.com> |
| In reply to | #33905 |
On Sunday, November 25, 2012 7:11:29 AM UTC-5, ALeX inSide wrote:
> How to "statically type" an instance of class that I pass to a method of other instance?
>
>
>
> I suppose there shall be some kind of method decorator to treat an argument as an instance of class?
>
>
>
> Generally it is needed so IDE (PyCharm) can auto-complete instance's methods and properties.
>
>
>
> Pseudo-python-code example:
>
>
>
> i = MyClass()
>
>
>
> xxx(i, 1, 2);
>
>
>
> ...
>
> def xxx(self, MyClass myclass, number, foobar):
>
> myclass.classsmethod() #myclass - is an instance of known class
I'm not sure I understand exactly what you sre asking. Python uses "duck typing". As far as Python is concerned, you can pass in any class object and so long as it has the needed methods, it'll suffice ("If it walks like a duck and it quacks like a duck, then it is a duck."). The down side to that is that if you hand an object as an argument and the method you pass doesn't behave like the expected method class would, then bad things may happen at run time. It would be a bit of a hassle to check types to make sure things at least smell OK before execution goes possibly awry, but you are certainly free to write guard code that makes those sort of checks.
My reply here is a bit different from the other replies I see so far. I worry that may mean I mis-understood your question. Has this been at all helpful an answer?
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web