

- [小工具]生辰八字计算online(Ver.4)
- 带OAuth的twip安装手记
- 简单的Delphi对象管理器
虽然早就听说过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]
由于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]
《掺和比试》时得到的一个副产品。
原 理很简单,就是创建的对象放到一个池里,暂时不释放,再分配的时候可以重用。对于需要反复大量创建删除同一个类的对象时,或是创建对象成本很高的情况下, 这个东东有一定的作用。另外还弄了一个通用的对象管理,不提供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]



