Pidgin / D-Bus / Python

No Debian que uso, o aMSN dá um pau muito louco que nunca roda. Nem com o pacote, nem compilando, na hora que conecta, o amsn congela. Parece ser um problema com o modelo de threads utilizado no kernel 2.6 (que é o que utilizo).

Então, tive que passar a usar o gaim que detesto. E um dos motivos que eu detesto ele, é o fator de não ter notificação “Fulano de tal entrou no msn”. Sabia que tinha um plugin chamado guifications (ou algo assim), mas nunca fui muito atrás, de qualquer maneira.

Ontem, estava estudando o D-Bus, que é um sistema de comunicação entre processos numa mesma máquina, é um padrão de comunicação entre aplicações. Eu envio uma mensagem, a aplicação recebe e processa e vice-versa. Diferente do TCP, que transporta fluxo de bits, o D-Bus tranporta mensagens.

Enfim, descobri que o Pidgin (antigo gaim), tem um servidor D-Bus, ou seja, eu poderia acessar várias funções dele. Como já estava estudando o D-Bus (estava fazendo um programa que pesquisava cotações de ações escolhidas por mim e mostrava no desktop, com uma caixinha estilo as do msn). Resolvi então fazer meu próprio “plugin” para isso.

Então, minha linguagem escolhida foi o Python, por sua simplicidade e por já vir com bibilioteca de acesso ao dbus por padrão. O programinha avisa quando o usuário entra e tem também um botão para falar com ele no popup. A caixinha que sobe é estilo as do MSN, no canto inferior direito.

Como o Python é conciso por natureza, o código ficou bem enxuto com 41 linhas. Está bem simples ainda, depois ainda pretendo adicionar suporte ao KDE e XFCE e mostrar a foto da pessoa que entrou. Nesta parte, o pidgin é muito MAL documentado. Na realidade, não tem documentação.

O código segue abaixo, quem quiser utilizar, basta estar usando o gnome e ter o interpretador Python instalado e o pacote python-gobject (Bindings para a biblioteca GObject). Daí você roda o programa (em background, se quiser) e roda o pidgin. Pronto, nenhuma configuração é necessária.

import dbus
import dbus.glib
import gobject

bus = dbus.SessionBus()

obj = bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
pidgin = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")

notify_obj = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
notify = dbus.Interface(notify_obj, "org.freedesktop.Notifications")

folks_cache = {}

def onSignOn(folkID):
    alias = pidgin.PurpleBuddyGetAlias(folkID)
    name = pidgin.PurpleBuddyGetName(folkID)

    alias = alias.replace('&', '&')
    alias = alias.replace('>', '>')
    alias = alias.replace('<', '<')

    text = "%s entrou." % alias

    notificationID = notify.Notify("DBus Test", 0, '/usr/share/icons/cab_view.png', '', \
text, ["newConversation", "Falar com o elemento"], {}, 9000)

    folks_cache[notificationID] = (pidgin.PurpleBuddyGetAccount(folkID), name)

def onClose(notificationID):
    if folks_cache.has(notificationID):
        del folks_cache[notificationID]

def onAction(notificationID, msgReceived):
    if msgReceived == "newConversation":
        pidgin.PurpleConversationNew(1, *folks_cache[notificationID])

bus.add_signal_receiver(onSignOn, dbus_interface="im.pidgin.purple.PurpleInterface", signal_name="BuddySignedOn")
bus.add_signal_receiver(onAction, dbus_interface="org.freedesktop.Notifications", signal_name="ActionInvoked")
bus.add_signal_receiver(onClose, dbus_interface="org.freedesktop.Notifications", signal_name="CloseNotification")

gobject.MainLoop().run()

1 comment 9 Novembro, 2007

Atualização da Situação do Python 3000 – Longo! (Python 3000 Status Update (Long!))

História Antiga

A primeira vez que eu tive a idéia do Python 3000 foi provavelmente em uma conferência sobre Python no ano 2000. O nome foi inspirado no Windows 2000. Por um longo tempo, não havia muito mais que uma lista de arrependimentos e falhas que eram impossíveis de consertar sem quebrar a compatibilidade com antigas versões. A idéia era que o Python 3000 fosse o primeiro lançamento a desistir da compatibilidade em prol de uma melhor linguagem de programação.

História Recente

Talvez um ano e meio atrás (justamente na época que comecei a trabalhar no Google, o que me deu mais tempo de trabalhar no Python do que eu tive em muito tempo). Eu decidi que era tempo de começar a planejar e desenhar o Python 3000 de fato. Juntamente com a comunidade de desenvolvedores e usuários do Python, eu surgi com um plano.
Nós criamos uma série de PEPs (Propostas de Melhoramente do Python – Python Enhancement Proposals) onde os números começavam com 3000. Já havia um PEP 3000, mantido por outros da comunidade, que era mais uma lista preliminar de idéias que vieram à tona como adequadas para implementação no Python 3000. O mesmo foi renomeado para PEP 3100; O PEP 3000 se tornou um documento descrevendo a filosofia e a agenda do projeto.

Desde então, nós temos, bem, talvez não tenhamos movido montanhas, mas certamente muita água correu embaixo da ponte da lista de discussões python-dev, assim como depois, na lista python-3000.

Tentativa de planejar uma agenda

Uma agenda foi publicada há cerca de 1 ano atrás; o planejamento era que o primeiro alpha release fosse lançado ao fim da primeira metade de 2007, com um release final 3.0 um ano depois. (Python 3.0 será o nome quando lançado; “Python 3000″ ou “Py3k” é o nome do projeto).

A agenda se modificou um pouco, estamos agora planejando um primeiro alpha release para o fim de Agosto, e o release final também para 1 ano depois deste período. (O atraso se deve, em grande parte, devido a enorme quantidade de trabalho resultado da transição de strings de texto Unicode e array de raw bytes mutáveis. Talvez
eu mesmo não tenha é delegado trabalho suficiente para outros desenvolvedores; um erro que, sinceramente, estou tentando corrigir).

Python 2.6

Haverá ainda um release paralelo do Python 2.6, agendado para ser lançado poucos meses antes da 3.0, com um alpha release cerca de 4 meses antes. As duas próximas seções explicarão seus papéis. Se vocÊ não está interessado em viver na última onda, 2.6 será a próxima versão do Python que você usará e não será muito diferente da 2.5.

Compatibilidade e Transição

Compatibilidade

Python 3.0 vai quebrar a compatibilidade com antigas versões. Totalmente. Não estamos nem sequer planejando um subconjunto específico. (Claro que haverá um subconjunto comum, provavelmente bem grande, mas não estamos visando tornar isso conveniente ou até mesmo possível de escrever programas significantes neste subset. É simplesmente o conjunto de recursos que simplesmente aconteça de não mudar da 2.6 para a 3.0.)

Por outro lado, o Python 2.6, irá manter total compatiblidade com o Python 2.5 (e quantas versões anteriores forem possíveis), mas irá também suportar compatiblidade futura, das seguintes maneiras:

* Python 2.6 irá suportar o “Modo de Alerta Py3k” (Py3k warnings mode) que vai alertar dinamicamente (por exemplo, em tempo de execução) sobre recursos que irão parar de funcionar no Python 3.0, como por exemplo, assumir que range() retorna uma lista.

* Python 2.6 irá conter versões portadas de vários recursos do Py3k, seja acionando-os através de instruções __future__ ou simplesmente permitindo que a velha e a nova sintaxe sejam usadas lado a lado.

* Complementando a compatiblidade futura de recursos na 2.6, haverá – separadamente – uma ferramente de conversão de código. Esta ferramenta poderá fazer uma tradução independente de contexto de código-para-código. Um exemplo (muito simples), ela poderá traduzir apply(f, args) em f(*args). Entretanto, a ferramente não poderá fazer análise de fluxo de dados ou inferência de tipo, então simplesmente assumirá que, neste exemplo, apply se refere a velha função built-in.

Desenvolvimento Transicional

O modelo recomendado de desenvolvimento para um projeto que precise suportar Python 2.6 e Python 3.0 simultaneamente é descrito a seguir:

0. Comece com excelentes testes de unidade (unit tests), o mais próximo possível de cobrir todas as possibilidades.
1. Porte o projeto para o Python 2.6.
2. Ative o modo de alertas do Py3k (Py3k warnings mode).
3. Teste e modifique até que nenhum alerta permaneça.
4. Use a ferramente 2to3 para converter o código-fonte para a sintaxe da versão 3.0 (Nâo edite manualmente a saída!!!).
5. Teste o código convertido sob a versão 3.0.
6. Se problemas forem achados, faça correções para a versão 2.6 do código-fonte e volte ao passo 3.
7. Quando for lançar, lançe tarballs separados da versão para 2.6 e para 3.0 (ou qualquer outra forma de arquivar que você use para releases).

A ferramenta de conversão produz código de alta qualidade, que muitas vezes são indistíguiveis de código convertido manualmente. Ainda assim, é fortemente recomendado não começar a modificar o código para a versão 3.0 até que você esteja pronto de reduzir o suporte para a versão 2.6 a pura manutenção (por exemplo, o momento em que você normalmente moveria o código 2.6 para um repositório de manutenção de toda forma).

É esperado que o passo 1 tome tanto trabalho quanto o esperado de se portar qualquer projeto para qualquer versão nova do Python. Nós estamos tentando fazer a transição da 2.5 para a 2.6 tão suave quanto possível.

Se a ferramenta de conversão e as compatibilidades futuras da versão 2.6 não funcionarem como esperado, executar do passo 2 ao passo 6 não deve dar muito mais trabalho do que a típica transição do Python 2.x to 2.(x+1).

Situação dos recursos individuais

Há mudanças demais para listar todas aqui; ao invés disso, eu irei me referir aos PEPs. De qualquer forma, eu gostaria de salientar alguns recursos que eu acho que sejam significantes ou que são interesse particular ou ainda controverso.

Unicode, codecs, e I/O

Nós estamos mudando para um modelho que já é conhecido pelo Java: strings (mutáveis) de texto são Unicode e dados binários são representados por um tipo de dados “byte” mutável e em separado. Em adição, o parser será mais amigável ao Unicode: a codificação padrão do código-fonte será UTF-8 e caracteres não-ASCII poderão ser usado em
identificadores. Ainda há algum debate sobre normalização, alfabetos específicos e quando que poderemos suportar razoavelmente scripts escritos da direita para a esquerda. De toda maneira, a biblioteca padrão continuará a usar somente caracteres ASCII para identificadores e limitará o uso de caracteres não-ASCII aos comentários e strings literais para testes de unidade (unit tests) para alguns recusos do Unicode e nome de autores.

Nós iremos usar “…” ou ‘…’ para literais Unicode e b”…” ou b’…’ para bytes literais. Por exemplo, b’abc’ é equivalente a criar um objeto bytes usando a expressão bytes([97, 98, 99]).

Nós estamos adotando uma aproximação diferente à respeito dos codecs: enquanto no Python 2, codecs podem aceitar tanto Unicode ou 8-bits como entrada e produzir ambos como saída, no Py3k, a codificação é sempre uma tradução de uma string Unicode (texto) para um array de bytes, e a decodificação sempre segue na direção oposta. Isso signifca que nós tivemos que tirar alguns codecs que não se encaixavam neste modelo, como por exemplo rot13, base64 e bz2 (estas conversões ainda são suportadas, só não mais pela API de codificação/decodificação).

Nova biblioteca de I/O

A biblioteca de I/O também está mudando devido a estas mudanças. Eu queria reescrever de qualquer forma, para remover a dependência que ela tem da biblioteca stdio do C. A nova distinção entre bytes e strings de texto requeriu uma mudança (sútil) na API, e os dois projetos eram levados de mão em mão. Na nova biblioteca, há uma distinção
clara entre streams binários (abertos com um modo como “rb” ou “wb”) e streams de texto (abertos com qualquer modo que não contenha “b”). Streams de texto tem um novo atributo, a codificação, que pode definido explicitamente quando o stream for aberto; se nenhuma codificação é especificada, um padrão específico do sistema será usado (o que pode pedir alguma adivinhação quando um arquivo já existente estiver sendo aberto).

Operações de leitura em streams binários retornan arrays de bytes, enquanto operações de leitura em streams de texto retornan strings (Unicode) de textos; o mesmo para as operações de escrita. Escrever uma string de texto para um stream binário ou um array de bytes para um stream de texto irá causar uma exceção.

Por outro lado, a API foi mantida compatível. Enquanto ainda há uma função built-in chamada open(), a definicação completa da nova biblioteca de I/O está disponível do novo módulo de io. Este módulo também contém classes bases abstratas (veja abaixo) para os vários tipos de stream, uma nova implementação do StringIO, e uma nova classe similar, a BytesIO, que funciona como a StringIO, mas implementa um stream binário, lendo e escrevendo arrays de bytes.

Imprimindo e Formatando

Mais dois recursos relacionados a I/O: a venerável instrução print agora se tornou uma função print() e o operador de formatação de string (%) será substituído por um novo método format() em objetos string.

Tornar print uma função usualmente fez algumas cabeças rolarem. Entretante, há varias vantagens: é bem mais fácil refatorar código usando funções print(), como por exemplo o pacote de logging. E a sintaxe do print sempre foi um tanto controversa, com sua semântica única para uma vírgula no final. Argumentos com palavra-chaves levam a melhor por cima destas coisas e tudo está bem.

De forma similar, o novo método format() evita alguns dos erros do velho operador %, especialmente ao comportamento supreendente de “%s” % x quando x é uma tupla e o erro frequentemente lamentado de acidentalmente de deixar o ’s’ final em %(name)s. O novo formato de strings usa {0}, {1}, {2}, … para referenciar argumentos posicionais para
o método format(), e {a}, {b}, … para referenciar argumentos por palavra-chave. Outros recursos incluem {a.b.c} para referenciar atributos e até {a[b]} para mapeamento ou acesso a sequências. Tamanho de campos podem ser especificados assim: {a:8}; esta notação também suporta que se passe outras opções de formatação.

O método format() é extensível em uma variade de dimensões: pode ser definindo método especial __format__(), tipos de dados podem sobreescrever como eles são formatados e como os parâmetros de formatação podem ser interpretados; você pode também criar classes customizadas de formatação, que podem ser usadas, por exempo, automaticamente provar variáveis locais como parâmetros para operações de formatação.

Mudanças ao sistema de Class e Type (Classes e Tipos)

Você deve ter adivinhado que as “classes clássicas” finalmente comeram poeira. O objeto built-in class é a classe base padrão para as novas classes. Isso dá espaço para uma variedade de novos recursos.

* Decorators de classes. Estes funcionam como decoratos de função:
@art_deco
class C:

* Assinaturas de função e de métodos podem agora ser “anotadas”. O core da linguagem não atribui nenhum significado a estas notações (somente fazer eles avaliáveis para instrospecção), mas alguns módulos da biblioteca padrão podem fazer isso; por exemplo, funções genéricas (veja abaixo) podem usar elas. A sintaxe é simples de ler:
def foobar(a: Integer, b: Sequence) -> String:

* Nova sintaxa de metaclasses. Em vez de definir uma variável __metaclass__ no corpo da classe, você deve agora especificar a metaclasse usando um parâmetro de palavra-chave no cabeçalho da classe, por exemplo:
class C(bases, metaclass=MyMeta):

* Dicionários de classes customizados. Se a metaclasse define um método __prepare__(), este será chamado antes de entra no corpo da classe, e o que quer que retorne será usado em vez do dicionário padrão como namespace no qual o corpo da classe é executado. Isso pode ser usado para, entre outros usos, implementar um tipo “struct” onde a ordem que os elementos são definidos é significante.

* Você pode espeficiar as bases dinamicamente, exemplo:
bases = (B1, B2)

class C(*bases):

* Outros parâmetros de palavra-chave também serão permitidos no cabeçalho da classe; estes serão para o método __new__ da metaclasse.

* Você pode sobrescrever os testes de isinstance() e issubclass(), definindo os métodos da classe chamados de __instancecheck__() ou __subclasscheck__(), respectivamente. Quando estes são definidos, isinstance(x, C) é equivalente a C.__instancecheck__(x)e issubclass(D, C) a C.__subclasscheck__(D).

* Classes-bases abstratas voluntárias (ABCs). SE você quer definir uma classe na qual suas instâncias se comportem como um mapeamento (por exemplo), você pode voluntariamente herdar da classe abc.Mapping. Por um lado, esta classe provê comportamentos mix-in utéis, substituindo a maior parte da funcionalidade das velhas classes UserDict e DictMixin.
Por outro lado, o uso sistemático de ABCs pode ajudar grandes frameworks a fazer a coisa certa com menos trabalho: no Python 2, não é sempre fácil saber quando um objeto deve ser uma sequência ou um mapeamento quando define um método __getitem__(). As seguintes classes ABCs são providas: Hashable, Iterable, Iterator, Sized, Container,
Callable; Set, MutableSet, Mapping, MutableMapping; Sequence, MutableSequence; Number, Complex, Real, Rational, Integer. O módulo io também define um número de ABCs, então pela primeira vez na história do PYthon nós teremos uma especificação para o antes nebuloso conceito de agir como arquivo (file-like). O poder do framework ABC reside na
habilidade (emprestada do Zope interfaces) em “registrar” uma classe concreta X como “herdando virtualmente de” um ABC Y, onde X e Y são escritos por autores completamente diferentes e aparecem em pacotes diferentes. (Para deixar claro, quando herança virtual é usada, o comportamento mix-in da classe Y não está disponível para a classe X; o único
efeito é que issubclass(X, Y) irá retornar True.)

* Para suportar a definição de ABCs que requere classes concretas implementem a interface completa, o decorator @abc.abstractmethod pode ser usado para declarar métodos abstratos (somente em classes nas quais suas metaclasses são ou derivam de abc.ABCMeta).

* Funções genéricas. A inclusão deste recurso, descrito no PEP 3124, é de alguma incerteza, já que o trabalho feito em cima do PEP parece estar praticamente inativo. Esperamos que o ritmo volte a ser constante. Suporta dispatch de funções baseadas no tipo de todos os argumentos, em vez do dispatch mais convencional baseado somente na classe do objeto alvo (self).

Outras mudanças significativas

Somente as mudanças de destaque

Reforma de Exceções (Exception)

* Strings de excepções foram cortadas (claro).
* Todas as exceções devem derivar de BaseException e preferivelmente de Exception.
* Estamos tirando StandardException.
* Exceções já não agem mais como sequências. Em vez disso, elas tem um atributo args que é a sequência de argumentos passados ao construtor.
* A sintaxe except E, e: muda para except E as e; isso evita confusão ocasionais como em except E1,E2:;
* A variável nomeada com o ‘as’ depois do claúsula de except é forçada a ser apagada após a saídaa da claúsula de except.
* sys.exc_info() se tornou redundante (ou talvez desapareça): em vez do mesmo, e.__class__ é o tipo de exceção e e.__traceback é o traceback.
* Atributos adicionais e opcionais __context__ são definidos para a exceção “anterior” quando uma exceção ocorre numa claúsula de except ou finally; __cause__ pode ser definida explicitamente quando estiver relançando uma exceção, usando raise E1 from E2.
* As variantas da antiga sintaxe raise como raise E, e e raise E, e, tb foram embora.

Reforma de Inteiros (Integer)

* Haverá somente um tipo built-in de inteiros, nomeado ‘int’, que terá o comportamento é o mesmo do ‘long’ no Python 2. O sufixo literal ‘L’ desaparece.
* 1/2 irá retornar 0.5, não 0. (Use 1//2 para isso.)
* A sintaxe de literais octais muda para 0o777, para evitar confundir desenvolvedores jovens.
* Literais binários: 0b101 == 5, bin(5) == ‘0b101′.

Iteradores e Iteráveis em vez de Listas
(Iterators or Iterables instead of Lists)

* dict.keys() e dict.items() retornam sets (visões, realmente); dict.values() retorna um contâiner iterável. A variante iter*() desaparece.
* range() retorna o tipo de objeto que xrange() costuma retornar. xrange() desaparece.
* zip(), map(), filter() retornam iteráveis (assim como suas contrapartes em itertools já fazem).

Miscelânea

* Ordem de comparações (<, <=, >, >=) irão levantar um TypeError por padrão em vez de retornar resultados arbitrários. Comparações de igualdade (==, !=) irão comparar a identidade dos objetos (is, is not) por padrão.
* A instrução nonlocal deixa você definir variávels em escopos exteriores (não-global).
* Set de literais: {1, 2, 3} e até set comprehensions: {x for x in y if P(x)}. Note que um set vazio é set(), já que {} é um dicionário vazio!
* reduce() foi embora. Isso não significa que eu não goste de funções de alta-ordem; isso simplesmente reflete que a maior parte do código que usa reduce() se torna mais legível quando reescrita usando o velho loop for (Exemplo.)
* lambda, por sua vez, vive.
* A sintaxe de apóstrofo, frequentemente difícil de ler, foi cortada (use repr()), assim como o operador <> (use !=; era uma violação flagrante do TOOWTDI – There Only One Way To Do It (Há somente uma maneira de fazer isto).
* A nível de C, haverá uma nova e melhorada API de buffer, que irá prover melhor integração com o numpy. (PEP 3118)

Reforma da Biblioteca (Library Reform)

Eu não quero falar muito sobre as mudanças na biblioteca padrão, este é um projeto que tomará seu caminho de fato após que a versão 3.0a1 estiver lançada, e eu não irei ficar olhando isto (o core da linguagem é tudo que posso manter). Está claro que nós já andamos removendo várias coisas não suportadas ou simplesmente datadas (por exemplo, muitos módulos aplicáveis somente sob SGI IRIX), e nós estamos tentando renomear módulos escritos com PalavrasCapitalizadas como StringIO ou UserDict, para ficar conforme a nomeação padrão de nomes de módulos descrita no PEP8 (que require uma palavra curta e sem caracteres maiuscúlos).

E finalmente

Eu já mencionei que lambda vive ? Ainda tenho pedidos ocasionais para preservá-lo, então achei que deveria mencionar isso duas vezes. Não se preocupe, estes pedidos foram aceitados por mais um ano agora.

Autor Original:
Guido Van Rossum
Tradutor:
Nicholas Amorim <nicholasamorim at gmail dot com>
Fonte:
http://www.artima.com/weblogs/viewpost.jsp?thread=208549

2 comments 20 Junho, 2007

Atma SCRUD

O trabalho para lançar o release 1.0 do Atma vai de vento em popa. Há preparativos por parte do Alexandre para o Atma suportar FastCGI e trabalhar lado-a-lado com o Lighttpd.

Eu por outro lado, estou trabalhando na interação direta com os usuários do atma. Estou criando um sistema de Scrud (Search, create, read, update, delete). Vejam este exemplo de código:

import atma.scrud as scrud

import orm# used to do deferred translations

_ = lambda a: a

class State(scrud.Scrud):
    table = orm.State
    createColumns = ['name', 'country', 'abbrev']
    readColumns = ['id','name', 'abbrev', 'country']
    searchColumns = ['name', 'country']
    resultColumns = ['id', 'name', 'abbrev']
    orderBy = 'name'

scrudColumns = [
        scrud.ScrudColumn('id', _('ID')),
        scrud.ScrudColumn('country', _('Country'), 'name'),
        scrud.ScrudColumn('name', _('State Name')),
        scrud.ScrudColumn('abbrev', _('Abbreviation'))
]

Este pedaço de código já cria o sistema de inclusão, edição, busca e deleção de registros de estados.

Explicando, você passa o mapeamento em table, declara as colunas do banco que deseja nos *Columns. Na variável scrudColumns, eu passo várias instâncias da classe scrudColumn, onde posso especializar as colunas, olha só:

scrud.ScrudColumn(‘name’, _(‘State Name’))

Aí, ‘name’ é a coluna do banco e ‘State Name’ é o label que ela vai ter quando criado o componente textinput para ela no html. Temos outro caso previsto, como a coluna ser uma chave estrangeira, caso disso:

scrud.ScrudColumn(‘country’, _(‘Country’), ‘name’),

O campo country é uma chave estrangeira para a tabela Country, apontando para o ID da tabela country. Mas não queremos mostrar IDs para o usuário, não é ? Então, o terceiro parâmetro é qual campo da tabela Country será exíbivel para o usuário no combo box. No caso, ‘name’ que é o nome do país.

Há inúmeras facilidades que irei mostrar ainda por aqui.

Página no sourceforge:

http://sourceforge.net/projects/atma

2 comments 8 Junho, 2007

Você sabia ?

http://video.google.com/videoplay?docid=-4562401385341459175

1 comment 28 Maio, 2007

Originando uma chamada com o PySt

import asterisk.manager as manager

m = manager.Manager()
m.connect('localhost', '5038')
m.login('user', 'password')response = m.originate(
    channel='sip/teste',
    exten='9999999',
    context='context-originate',
    caller_id='my_caller_id,
    priority='1',
)

m.close()

Add comment 15 Maio, 2007

Dica quase inútil – swap

O seu sistema tem uma ‘tendência’ a usar o swap. Para configurar esta tendência, edite o arquivo /proc/sys/vm/swappiness.

O arquivo contém somente um número. Se ‘0′, o sistema nunca acessa a swap.

PS: Lembrando que os desenvolvendores do kernel tem como padrão o número ‘60′.

Add comment 15 Maio, 2007

O que eu sou, eu não quero ser

Estou me sentindo sem vida.
:(
Sou C#.
Eu queria ser C ou Python. :(

You are C#. No matter how hard you try, you can't convince people that you are unique.  You're composed of others' traits.
Which Programming Language are You?

2 comments 15 Maio, 2007

Hello world!

#!/usr/bin/env python

print ‘hello’

2 comments 11 Abril, 2007


Categories

Feeds