文章分类
Editor's Choice
Recent Articles
  • [小工具]生辰八字计算online(Ver.4)
    作者:raptor | 2010-09-04 03:38:00 | 1个评论
  • 虽然早就听说过web.py,不过之前试过感觉还不太成熟,最近又去看了一下,貌似已经相当不错了,便拿来试了试,发现非常合我胃口,迅速决定抛弃用了一年多的web2py。

    这些年来从Django, TG1, Pylons, Web2py, TG2一路用过来,web.py是唯一一个web框架让我觉得:这就是我想要的。

    而理由只有一个:干净。

    本 来web2py已经相当接近我的要求了,除了它以外的另四个都需要安装,而且除了Django以外都需要easy_install那个家伙来安装一大堆的 依赖包,烦也烦死了,还好现在有VirtualEnv,不然真是搞死人。但是即使有VE也还是烦,每次安装都会碰到这样那样的问题,从来没有一次顺利过。 Django那套模式我不太适应,所以很早就不再用了。Web2py不提了,虽然不用安装这点比其它都好,但是DAL那是相当难用,自带的模板也不好用, 更烦的是URL映射太难看。在这些方面来说,TG/Pylons可以选择模板和ORM,Pylons的URL映射也可以做到Django那么灵活,但是 Pylons除了安装麻烦以外,需要自己做的事情实在太多。

    然而这些都还不是最根本的原因,最重要的还是它们都不够干净——创建一个空项目也要产生一大堆的代码,光是研究去掉哪些部分就要花N多的时间。

    而web.py没有这些问题,它不需要安装,不产生任何代码,可以根据需要选择ORM或是模板,非常的清爽干净。

    于是我用它来改写原来的《[小工具]生辰八字计算online(Ver.3)》,并且已经放到了GAE上:

    补充一些关于web.py发布到GAE上的几个注意事项:

    第一、运行程序的语句从原来的

    app.run()

    改为:

    main = app.cgirun()

    也就是用app.cgirun函数去把GAE默认的main函数替换掉;

    第二、需要预先把模板编译为Python代码:

    web/template.py --compile templates

    第三、在app.yaml里配置一下static和script,方法详见GAE文档。

    推送到[go4pro.org]

  • 带OAuth的twip安装手记
    作者:raptor | 2010-09-03 16:06:00 | 1个评论
  • 由于9月1日起,某网站不再提供BasicAuth方式的登录,必须使用OAuth,这就给中国网民带来了非常大的不便。因为还有好多第三方都是只支持BasicAuth的。

    不得已,只能自己弄个twip转一下API了。

    twip的文档实在是太那什么了,所以安装过程主要参考了这篇《轻松搭建oauth twip(PHP)》,不过不知道是版本问题还是别的原因,装好后出不来timeline,查了半天原来是一个小问题。

    主要的安装过程就不多废话了,看上面那篇链接就好,下面主要说一些注意事项。

    说明:全部以twip 3.1.2版本为例。

    第一是注册twitter application的时候,callback url要写全,类似于: https://yourdomain/twip/callback.php

    第二是要注意 oauth 目录要有 webserver 用户的写权限(最简单就是设置为777,但这样可能不够安全),但同时这个目录不可以通过web方式访问,即不能挂在任何一个域名下。这点上面那篇有说到,这里强调一下。

    第三是如果 twip 放的目录不是叫 twip 或者不是用子目录而是子域名的话,要到index.php里去改一下WEBROOT,如上面那篇文章所说。

    第四个就是我碰到的问题,.htaccess里需要加一行 RewriteBase /twip ,当然,如果你用子域名的话,这个就应该是 RewriteBase /

    配置好后访问twip首页,点sign in,然后allow一下,回到twip设置一个密码。这个密码是twip提供的BasicAuth密码,不必与你实际帐号密码一样。

    回到首页能够显示五条timeline内容的话说明成功,否则请查看服务器LOG查找原因。

    以后使用的话就直接在需要API的地方用 http://yourdomain/twip ,并且使用你的用户名及刚刚在twip上设置的密码(注意这个密码别搞错了)进行BasicAuth登录即可。

    推送到[go4pro.org]

  • 简单的Delphi对象管理器
    作者:raptor | 2010-08-17 21:44:00 | 0个评论
  • 掺和比试》时得到的一个副产品。

    原 理很简单,就是创建的对象放到一个池里,暂时不释放,再分配的时候可以重用。对于需要反复大量创建删除同一个类的对象时,或是创建对象成本很高的情况下, 这个东东有一定的作用。另外还弄了一个通用的对象管理,不提供POOL的缓冲,仅提供自动释放,纯粹是为了方便,这个可以不针对特定对象。

    使用方法:

    uses objmngr;
    ...
    Type
      TDummy = Class(....
        Constructor Create(...);
        Function Init(...) : TDummy;
        ...
      End;
    ...
    Var
      DummyPool : TMObjPool;
    ...
    Function TDummy.Init(...) : TDummy;
    Begin
      ...
      Result := Self;
    End;
    ...
    // Pool
    Var
      om : IMObjPoolManager;
    Begin
      om := TMObjPoolManager.Create(DummyPool, 50);
      d1 := (om.New As TDummy).Init(...);  //  Create new dummy object
      ...
    End;  //  om and all new dummy objects will be released automatically
    ...
    // Nopool
    Var
      om : IMObjManager;
    Begin
      om := TMObjManager.Create(50);
      d1 := om.New(TDummy.Create(...)) As TDummy;
      d2 := om.New(TOther.Create(...)) As TOther;
      ...
    End; // om and all managed objects will be release automatically
    ...
    Initialization
      DummyPool := TMObjPool.Create(TDummy, 5000);
    ...
    Finallization
      DummyPool.Free;

    注意:因为自动创建对象时无法确定构造函数参数,所以只能调用无参数的构造函数,如需初始化对象,则需要再定义一个Init函数供调用。因为Init函数取代了构造函数的功能,所以还需要它返回Self给调用者。

    管理单元objmngr.pas源码:

    unit objmngr;
    
    {$IFDEF FPC}{$mode objfpc}{$H+}{$ENDIF}
    
    interface
    
    uses
      Classes, SysUtils;
    
    Type
    
    TMBucket = Record
        Key : TObject;
        Value : TObject;
    end;
    
    PMBucket = ^TMBucket;
    
    TMHashMap = Class(TObject)
    Private
        FSize  : Integer;
        FItems : Array Of TMBucket;
    Protected
        Function HashFunc(Key : TObject) : Integer;
        Function FindKey(Key : TObject) : Integer;
        Function FindEmpty(Key : TObject) : Integer;
        Function GetItem(Key : TObject) : TObject;
    Public
        Constructor Create(ASize : Integer);
        Destructor Destroy; Override;
    
        Procedure AddItem(Key, Value : TObject);
        Procedure DelItem(Key : TObject);
        Function PopItem(Key : TObject) : TObject;
    
        Property Items[Key : TObject] : TObject Read GetItem;
    End;
    
    TMStack = Class(TObject)
    Private
        FData : Array Of TObject;
        FTop  : Integer;
    Public
        Constructor Create(ASize : Integer);
        Destructor Destroy; Override;
        Procedure Push(AObj : TObject);
        Function Pop : TObject;
        Function IsEmpty : Boolean;
    End;
    
    TMObjPool = Class(TObject)
    Private
        FMeta  : TClass;
        FPool  : Array Of TObject;
        FIndex : Integer;
        FMap   : TMHashMap;
        FFree  : TMStack;
    Public
        Constructor Create(AMeta : TClass; ASize : Integer);
        Destructor Destroy; Override;
    
        Function NewObj : TObject;
        Procedure FreeObj(AObj : TObject);
    End;
    
    IMObjPoolManager = Interface
        Function New : TObject;
    End;
    
    TMObjPoolManager = Class(TInterfacedObject, IMObjPoolManager)
    Private
        FPool : TMObjPool;
        FObjs : TMStack;
    Public
        Function New : TObject; Overload;
    
        Constructor Create(APool : TMObjPool; ASize : Integer = 1000);
        Destructor Destroy; Override;
    End;
    
    IMObjManager = Interface
        Function New(AObj : TObject) : TObject;
    End;
    
    TMObjManager = Class(TInterfacedObject, IMObjManager)
    Private
        FObjs : TMStack;
    Public
        Function New(AObj : TObject) : TObject; Overload;
    
        Constructor Create(ASize : Integer = 1000);
        Destructor Destroy; Override;
    End;
    
    implementation
    
    { TMHashMap }
    
    Constructor TMHashMap.Create(ASize : Integer);
    Begin
        FSize := ASize;
        SetLength(FItems, FSize);
        FillChar(FItems[0], FSize * SizeOf(TMBucket), 0);
    End;
    
    Destructor TMHashMap.Destroy;
    Begin
        SetLength(FItems, 0);
        Inherited;
    End;
    
    Function TMHashMap.HashFunc(Key : TObject) : Integer;
    Begin
        Result := Integer(Key) Mod FSize;
    End;
    
    Function TMHashMap.FindKey(Key : TObject) : Integer;
    Var
        i, n : Integer;
    Begin
        n := HashFunc(Key);
        Result := -1;
        If FItems[n].Key = Key Then
            Result := n
        Else
        Begin
            i := n;
            Repeat
                i := (i + 1) Mod FSize;
                If FItems[i].Key = Key Then
                Begin
                    Result := i;
                    Break;
                End;
            Until i = n;
        End;
    End;
    
    Function TMHashMap.FindEmpty(Key : TObject) : Integer;
    Var
        i, n : Integer;
    Begin
        n := HashFunc(Key);
        If Integer(FItems[n].Key) = 0 Then
            Result := n
        Else
        Begin
            i := n;
            Repeat
                i := (i + 1) Mod FSize;
                If Integer(FItems[i].Key) = 0 Then
                Begin
                    Result := i;
                    Exit;
                End;
            Until i = n;
            Raise Exception.Create('Map is full!');
        End;
    End;
    
    Function TMHashMap.GetItem(Key : TObject) : TObject;
    Var
        i : Integer;
    Begin
        i := FindKey(Key);
        If i >= 0 Then
            Result := FItems[i].Value
        Else
            Result := Nil;
    End;
    
    Procedure TMHashMap.AddItem(Key, Value : TObject);
    Var
        i : Integer;
    Begin
        i := FindEmpty(Key);
        FItems[i].Key   := Key;
        FItems[i].Value := Value;
    End;
    
    Procedure TMHashMap.DelItem(Key : TObject);
    Var
        i : Integer;
    Begin
        i := FindKey(Key);
        If i >= 0 Then
        Begin
            FItems[i].Key   := TObject(0);
            FItems[i].Value := Nil;
        End;
    End;
    
    Function TMHashMap.PopItem(Key : TObject) : TObject;
    Var
        i : Integer;
    Begin
        i := FindKey(Key);
        If i >= 0 Then
        Begin
            Result := FItems[i].Value;
            FItems[i].Key   := TObject(0);
            FItems[i].Value := Nil;
        End
        Else
            Result := Nil;
    End;
    
    { TMStack }
    
    Constructor TMStack.Create(ASize : Integer);
    Begin
        SetLength(FData, ASize);
        FTop := 0;
    end;
    
    Destructor TMStack.Destroy;
    Begin
        SetLength(FData, 0);
        Inherited;
    end;
    
    Procedure TMStack.Push(AObj : TObject);
    Begin
        FData[FTop] := AObj;
        Inc(FTop);
        If FTop >= Length(FData) Then
            Raise Exception.Create('Queue is full!');
    end;
    
    Function TMStack.Pop : TObject;
    Begin
        If FTop = 0 Then
            Raise Exception.Create('Queue is empty!');
        Dec(FTop);
        Result := FData[FTop];
    end;
    
    Function TMStack.IsEmpty : Boolean;
    Begin
        Result := (FTop = 0);
    end;
    
    { TMObjPool }
    
    Constructor TMObjPool.Create(AMeta : TClass; ASize : Integer);
    Begin
        FMeta  := AMeta;
        SetLength(FPool, ASize);
        FIndex := 0;
        FMap   := TMHashMap.Create(ASize * 4);
        FFree  := TMStack.Create(ASize);
    End;
    
    Destructor TMObjPool.Destroy;
    Var
       i : Integer;
    Begin
        FFree.Free;
        FMap.Free;
        For i := 0 To FIndex - 1 Do
            FPool[i].Free;
        Inherited;
    End;
    
    Function TMObjPool.NewObj : TObject;
    Var
        i : Integer;
    Begin
        If FFree.IsEmpty Then
        Begin
            Result := FMeta.Create;
            FPool[FIndex] := Result;
            i := FIndex;
            Inc(FIndex);
        End
        Else
        Begin
            i := Integer(FFree.Pop);
            Result := FPool[i];
        End;
        FMap.AddItem(Result, TObject(i));
    End;
    
    Procedure TMObjPool.FreeObj(AObj : TObject);
    Var
        i : Integer;
    Begin
        i := Integer(FMap.PopItem(AObj));
        FFree.Push(TObject(i));
    End;
    
    { TMObjPoolManager }
    
    Constructor TMObjPoolManager.Create(APool : TMObjPool; ASize : Integer);
    Begin
        FPool := APool;
        FObjs := TMStack.Create(ASize);
    End;
    
    Destructor TMObjPoolManager.Destroy;
    Begin
        While Not FObjs.IsEmpty Do
            FPool.FreeObj(FObjs.Pop);
        FObjs.Free;
        Inherited;
    end;
    
    Function TMObjPoolManager.New : TObject;
    Begin
        Result := FPool.NewObj;
        FObjs.Push(Result);
    end;
    
    { TMObjManager }
    
    constructor TMObjManager.Create(ASize: Integer);
    begin
        FObjs := TMStack.Create(ASize);
    end;
    
    destructor TMObjManager.Destroy;
    begin
        While Not FObjs.IsEmpty Do
            FObjs.Pop.Free;
        FObjs.Free;
        Inherited;
    end;
    
    function TMObjManager.New(AObj: TObject): TObject;
    begin
        FObjs.Push(AObj);
        Result := AObj;
    end;
    
    end.
    

    草草写就,应该还有优化的余地。

    推送到[go4pro.org]

2008 - 2009,Go4Pro.org
Creative Commons License
本作品采用知识共享署名-非商业性使用-禁止演绎 3.0 Unported许可协议进行许可。

Valid XHTML 1.0 Transitional  Valid CSS!