-
Notifications
You must be signed in to change notification settings - Fork 0
/
pythonpaste.org_deploy_sources_index.txt
843 lines (620 loc) · 31.6 KB
/
pythonpaste.org_deploy_sources_index.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
Paste Deployment
================
:author: Ian Bicking <[email protected]>
.. contents::
Documents:
.. toctree::
:maxdepth: 1
news
modules/loadwsgi
modules/config
modules/converters
license
.. comment:
The names used in sections should be more concrete, and it should
be clearer that they are just arbitrary names.
Introduction
说明
------------
Paste Deployment is a system for finding and configuring WSGI
applications and servers. For WSGI application consumers it provides
a single, simple function (``loadapp``) for loading a WSGI application
from a configuration file or a Python Egg. For WSGI application
providers it only asks for a single, simple entry point to your
application, so that application users don't need to be exposed to the
implementation details of your application.
Paste Deployment好似一个为找到和配置WSGI程序和服务器的系统。它为WSGI程序用户提供了一个
单独的,简单的函数(``loadapp``)以从一个WSGI配置文件或Python Egg中加载一个WSGI程序。
它只向WSGI程序的提供者索取一个单独的,简单的指向你的WSGI程序的entry point,因此程序使用者
无须暴露程序的实现细节。
The result is something a system administrator can install and manage
without knowing any Python, or the details of the WSGI application or
its container.
这样导致的结果是,系统管理员可以使用和管理此系统而无须知道Python的知识,或者WSGI程序实现的
细节或者它的容器。
Paste Deployment currently does not require other parts of `Paste
<http://pythonpaste.org>`_, and is distributed as a separate package.
Paste Deployment目前不需要`Paste<http://pythonpaste.org>`_的其它部分,并且别作为一
个独立的包。
To see updates that have been made to Paste Deploy see the `news file
<news.html>`_.
查看Paste Deploy的更多更新请查看`news file<news.html>`_。
Paste Deploy is released under the `MIT license
<http://www.opensource.org/licenses/mit-license.php>`_.
Paste Deploy是在`MIT license
<http://www.opensource.org/licenses/mit-license.php>`_许可下发布。
Status
现状
------
Paste Deploy has passed version 1.0. Paste Script is an actively
maintained project. As of 1.0, we'll make a strong effort to maintain
backward compatibility (this actually started happening long before
1.0, but now it is explicit). This will include deprecation warnings
when necessary. Major changes will take place under new functions or
with new entry points.
Paste Deploy已经超过了1.0版本。Paste Script是一个被活跃维护的项目。在10版本我们努力地保持
向后兼容(事实上这远在1.0版本之前就已经开始了,但现在它更明确了)。这将包含一些必要的反动告警。主
要的改变会在新的函数或新的entry ponts中实现。
Note that the most key aspect of Paste Deploy is the entry points it
defines (such as ``paste.app_factory``). Paste Deploy is not the only
consumer of these entry points, and many extensions can best take
place by utilizing the entry points instead of using Paste Deploy
directly. The entry points will not change; if changes are necessary,
new entry points will be defined.
Paste Deploy最关键的环节是声明的entry points(比如``paste.app_factory``)。Paste Deploy
不是entry points的唯一用户,并且很多扩展可以通过使用entry points来工作,而非直接使用Paste Deploy。
entry points不会改变;如果需要改变,新的entry points会被声明。
Installation
安装
------------
First install `setuptools
<http://peak.telecommunity.com/DevCenter/setuptools>`_.
首先安装`setuptools
<http://peak.telecommunity.com/DevCenter/setuptools>`_.
You can install Paste Deployment by installing `easy_install
<http://peak.telecommunity.com/DevCenter/EasyInstall>`_ and running::
你可以通过安装`easy_install
<http://peak.telecommunity.com/DevCenter/EasyInstall>`_ 并运行如下命令来安装Paste::
$ sudo easy_install.py PasteDeploy
If you want to track development, do::
如果你想跟踪开发,运行::
$ hg clone http://bitbucket.org/ianb/pastedeploy
$ cd pastedeploy
$ sudo python setup.py develop
This will install the package globally, but will load the files in the
checkout. You can also simply install ``PasteDeploy==dev``.
这会在全局安装paste,但是会加载检出的文件。你也可以简单地安装``PasteDeploy==dev``。
For downloads and other information see the `Cheese Shop PasteDeploy
page <http://cheeseshop.python.org/pypi/PasteDeploy>`_.
下载或其它的信息请查看`Cheese Shop PasteDeploy
page <http://cheeseshop.python.org/pypi/PasteDeploy>`_。
A complimentary package is `Paste Script </script/>`_. To install
that use ``easy_install PasteScript`` (or ``easy_install
PasteScript==dev``).
另一个附送的包是`Paste Script </script/>`_。要安装这个运行``easy_install PasteScript``
(or ``easy_install PasteScript==dev``)。
From the User Perspective
用户的看法
-------------------------
In the following sections, the Python API for using Paste Deploy is
given. This isn't what users will be using (but it is useful for
Python developers and useful for setting up tests fixtures).
在下面的单元中,提供了使用Paste Deploy的Python API接口。这不是用户将要使用的
(但是对Python开发和测试非常有用)。
The primary interaction with Paste Deploy is through its configuration
files. The primary thing you want to do with a configuration file is
serve it. To learn about serving configuration files, see `the
``paster serve`` command
<http://pythonpaste.org/script/#paster-serve>`_.
使用Paste Deploy主要是通过配置文件。对一个配置文件你主要要做的是server it。要得到serve配置文件
的更多信息,请查看`the ``paster serve`` command <http://pythonpaste.org/script/#paster-serve>`_.
The Config File
配置文件
~~~~~~~~~~~~~~~
A config file has different sections. The only sections Paste Deploy
cares about have prefixes, like ``app:main`` or ``filter:errors`` --
the part after the ``:`` is the "name" of the section, and the part
before gives the "type". Other sections are ignored.
不同的配置文件有不同的单元。Paste Deploy关注的单元都有前缀,比如``app:main``或者
``filter:errors``--``:``之后的部分是单元的"name",之前的则是"type".其他的单元忽略。
The format is a simple `INI format
<http://en.wikipedia.org/wiki/INI_file>`_: ``name = value``. You can
extend the value by indenting subsequent lines. ``#`` is a comment.
配置文件的格式是个简单的`INI format <http://en.wikipedia.org/wiki/INI_file>`_:
``name = value``。你可以通过缩进的新行来扩展值。``#``是注释。
Typically you have one or two sections, named "main": an application
section (``[app:main]``) and a server section (``[server:main]``).
``[composite:...]`` signifies something that dispatches to multiple
applications (example below).
代表性的你要有一个或两个单元,名叫"main":的程序单元(``[app:main]``)和server单元
(``[server:main]``)。``[composite:...]``表示要封发到多个程序(如下)。
Here's a typical configuration file that also shows off mounting
multiple applications using `paste.urlmap
<http://pythonpaste.org/module-paste.urlmap.html>`_::
这是一个典型的配置文件同时使用
`paste.urlmap <http://pythonpaste.org/module-paste.urlmap.html>`_封发给多个程序::
[composite:main]
use = egg:Paste#urlmap
/ = home
/blog = blog
/cms = config:cms.ini
[app:home]
use = egg:Paste#static
document_root = %(here)s/htdocs
[filter-app:blog]
use = egg:Authentication#auth
next = blogapp
roles = admin
htpasswd = /home/me/users.htpasswd
[app:blogapp]
use = egg:BlogApp
database = sqlite:/home/me/blog.db
I'll explain each section in detail now::
下面我将逐一解释每一个单元::
[composite:main]
use = egg:Paste#urlmap
/ = home
/blog = blog
/cms = config:cms.ini
That this is a ``composite`` section means it dispatches the request
to other applications. ``use = egg:Paste#urlmap`` means to use the
composite application named ``urlmap`` from the ``Paste`` package.
``urlmap`` is a particularly common composite application -- it uses a
path prefix to map your request to another application. These are
the applications like "home", "blog" and "config:cms.ini". The last
one just refers to another file ``cms.ini`` in the same directory.
这是一个``composite``单元,意味着它将封发请求到别的程序。``use = egg:Paster#urlmap``表示
使用``Paste``包中``urlmap``符合程序来执行封发。``urlmap``是一个特别的普通程序组建--它使用一
个路径前缀来将请求封发到别的程序中。有如"home", "blog"或"config:cms.ini"些程序。最后一个关联
到同目录中的另一个文件``cms.ini``.
Next up::
[app:home]
use = egg:Paste#static
document_root = %(here)s/htdocs
``egg:Paste#static`` is another simple application, in this case it
just serves up non-dynamic files. It takes one bit of configuration:
``document_root``. You can use variable substitution, which will pull
variables from the section ``[DEFAULT]`` (case sensitive!) with
markers like ``%(var_name)s``. The special variable ``%(here)s`` is
the directory containing the configuration file; you should use that
in lieu of relative filenames (which depend on the current directory,
which can change depending how the server is run).
``egg:Paste#static``是另一个简单的程序,它只服务于非动态的文件。它需要``document_root``
这项配置。你可以使用变量来代替,可以从``[DEFAULT]``中声明的变量中得到,比如``%(var_name)s``.
专用变量``$(here)s``是包含此配置文件的文件目录;你应该用它来替代相关的文件名(依赖于当前目录,
并可根据server运行方式改变)
Lastly::
[filter-app:blog]
use = egg:Authentication#auth
next = blogapp
roles = admin
htpasswd = /home/me/users.htpasswd
[app:blogapp]
use = egg:BlogApp
database = sqlite:/home/me/blog.db
The ``[filter-app:blog]`` section means that you want an application
with a filter applied. The application being filtered is indicated
with ``next`` (which refers to the next section). The
``egg:Authentication#auth`` filter doesn't actually exist, but one
could imagine it logs people in and checks permissions.
``[filter-app:blog]``单元表示你需要一个有过滤器的程序。被过滤的程序被``next``(关联到
新的单元)指出,``egg:Authentication#auth``过滤器事实上并不存在,但是你可以想象它校验
登录权限,并允许登录。
That last section is just a reference to an application that you
probably installed with ``easy_install BlogApp``, and one bit of
configuration you passed to it (``database``).
最后一个单元是到一个程序的关联,可能这是个你通过``easy_install BlogApp``安装的程序,
并且传入一点配置项给它(``database``)。
So, that's most of the features you'll use.
这些是你需要的大多数特征。
Basic Usage
基本用法
-----------
The basic way you'll use Paste Deployment is to load `WSGI
<http://www.python.org/peps/pep-0333.html>`_ applications. Many
Python frameworks now support WSGI, so applications written for these
frameworks should be usable.
你要使用Paste Deployment的最基本的方式是加载
`WSGI <http://www.python.org/peps/pep-0333.html>`_程序。许多Python框架现在
都支持WSGI,因此为这些框架所写的程序应该是可用的。
The primary function is ``paste.deploy.loadapp``. This loads an
application given a URI. You can use it like::
主要的函数是``paste.deploy.loadapp``。这加载一个被赋予URI的程序。你可以这样使用::
from paste.deploy import loadapp
wsgi_app = loadapp('config:/path/to/config.ini')
There's two URI formats currently supported: ``config:`` and ``egg:``.
目前支持两种URL的格式:``config:``和``egg:``。
``config:`` URIs
----------------
URIs that being with ``config:`` refer to configuration files. These
filenames can be relative if you pass the ``relative_to`` keyword
argument to ``loadapp()``.
``config:``格式的URI关联到配置文件。那些文件名会是相关的如果你传递``relative_to``
关键字参数给``loadapp()``。
.. note::
Filenames are never considered relative to the current working
directory, as that is a unpredictable location. Generally when
a URI has a context it will be seen as relative to that context;
for example, if you have a ``config:`` URI inside another
configuration file, the path is considered relative to the
directory that contains that configuration file.
文件名从未被考虑过关联到当前工作目录,因为这是一个未来不可预知的地点。通常当一个URI有上下文时,
它将被视为与此上下文关联;比如,如果你有一个``config:``的URI在另一个配置文件中,那么路径会被
认为与包含此配置文件的目录有关。
Config Format
~~~~~~~~~~~~~
Configuration files are in the INI format. This is a simple format
that looks like::
配置文件是INI格式。这是一个示例:
[section_name]
key = value
another key = a long value
that extends over multiple lines
All values are strings (no quoting is necessary). The keys and
section names are case-sensitive, and may contain punctuation and
spaces (though both keys and values are stripped of leading and
trailing whitespace). Lines can be continued with leading whitespace.
所有的值都是字符串(无须转义)。key名和单元名是区分大小写的,并且可能包含表单和空格(key和value
都被去掉开头和末尾的空格)。继续的一行可以以空格开头。
Lines beginning with ``#`` (preferred) or ``;`` are considered
comments.
以``#``(优先的)开头或以``;``开头的被视为是注释。
Applications
~~~~~~~~~~~~
You can define multiple applications in a single file; each
application goes in its own section. Even if you have just one
application, you must put it in a section.
你可以在一个文件中定义多个程序;每一个程序使用它的独立的单元。即使如果你只有一个程序,你必须将它放
在单元中。
Each section name defining an application should be prefixed with
``app:``. The "main" section (when just defining one application)
would go in ``[app:main]`` or just ``[app]``.
每一个声明一个程序的单元名需要以``app:``为前缀。"main"单元(当只是声明一个程序时)
会是``[app:main]``或仅仅是``[app]``。
There's two ways to indicate the Python code for the application. The
first is to refer to another URI or name::
有两种方式来指向此程序的Python代码。第一种是指向另一个URI或名::
[app:myapp]
use = config:another_config_file.ini#app_name
# or any URI:
[app:myotherapp]
use = egg:MyApp
# or even another section:
[app:mylastapp]
use = myotherapp
It would seem at first that this was pointless; just a way to point to
another location. However, in addition to loading the application
from that location, you can also add or change the configuration.
最初看来这样貌似是不得要领的;只是一个指向另一个程序的方法。还有加载此程序的路径,
你可以添加或修改配置。
The other way to define an application is to point exactly to some
Python code::
另一个声明一个程序的方式是直接指向Python代码的绝对地址::
[app:myapp]
paste.app_factory = myapp.modulename:app_factory
You must give an explicit *protocol* (in this case
``paste.app_factory``), and the value is something to import. In
this case the module ``myapp.modulename`` is loaded, and the
``app_factory`` object retrieved from it.
你必须提供一个精确的 *protocol* (在本例中是``paste.app_factory``),并且它的值是需要导入
的东西。在此清醒下模块``myapp.modulename``被加载,并且``app_factory``对象会通过它得到。
See `Defining Factories`_ for more about the protocols.
查看 `Defining Factories`_ 以得到关于protocols的更多信息。
Configuration
配置
~~~~~~~~~~~~~
Configuration is done through keys besides ``use`` (or the protocol
names). Any other keys found in the section will be passed as keyword
arguments to the factory. This might look like::
配置通过``use``(或者协议名)旁边的key来达到。单元中其它的key会被作为关键字参数传入factory。
这看起来是这样::
[app:blog]
use = egg:MyBlog
database = mysql://localhost/blogdb
blogname = This Is My Blog!
You can override these in other sections, like::
你可以在别的单元中重写这个,如::
[app:otherblog]
use = blog
blogname = The other face of my blog
This way some settings could be defined in a generic configuration
file (if you have ``use = config:other_config_file``) or you can
publish multiple (more specialized) applications just by adding a
section.
这样你可以在一个一般的配置文件中声明设置(如果你使用``use = config:other_config_file``)
或者你通过添加单元发布多个程序。
Global Configuration
全局配置
~~~~~~~~~~~~~~~~~~~~
Often many applications share the same configuration. While you can
do that a bit by using other config sections and overriding values,
often you want that done for a bunch of disparate configuration
values. And typically applications can't take "extra" configuration
parameters; with global configuration you do something equivalent to
"if this application wants to know the admin email, this is it".
通常多个程序共享一个配置文件。当你可以通过使用别的配置单元和重写值时,通常你希望为一组
不同的配置这样做。并且代表性地,程序不可以使用"extra"参数;和一些全局配置你会做些等同于
"如果程序需要知道管理员邮箱,那么它在这儿"
Applications are passed the global configuration separately, so they
must specifically pull values out of it; typically the global
configuration serves as the basis for defaults when no local
configuration is passed in.
程序单独地传递全局配置,因此它们必须专门地得到值;代表性地,当没有本地配置传入时,全局配置
表现位默认基本配置。
Global configuration to apply to every application defined in a file
should go in a special section named ``[DEFAULT]``. You can override
global configuration locally like::
提供给每一个文件中声明的所有程序的全局配置应该包含一个特定的单元``[DEFAULT]``。你可以重写
全局配置,如::
[DEFAULT]
admin_email = [email protected]
[app:main]
use = ...
set admin_email = [email protected]
That is, by using ``set`` in front of the key.
在key之前需要使用``set``。
Composite Applications
复合程序
~~~~~~~~~~~~~~~~~~~~~~
"Composite" applications are things that act like applications, but
are made up of other applications. One example would be a URL mapper,
where you mount applications at different URL paths. This might look
like::
"Composite"表现得与程序类似,但却是由其它的程序组合而成。例如一个URL的封发器,你将不同的程序
关联到对应的URL上。比如:
[composite:main]
use = egg:Paste#urlmap
/ = mainapp
/files = staticapp
[app:mainapp]
use = egg:MyApp
[app:staticapp]
use = egg:Paste#static
document_root = /path/to/docroot
The composite application "main" is just like any other application
from the outside (you load it with ``loadapp`` for instance), but it
has access to other applications defined in the configuration file.
复核程序的"main"与外部的其它程序相同(你通过``loadapp``加载来实例化的),但是复合程序
已经与文件内声明的其它程序相连接。
Other Objects
~~~~~~~~~~~~~
In addition to sections with ``app:``, you can define filters and
servers in a configuration file, with ``server:`` and ``filter:``
prefixes. You load these with ``loadserver`` and ``loadfilter``. The
configuration works just the same; you just get back different kinds
of objects.
除了``app:``这些单元之外,你还可以在配置中声明filters和servers,用``server:``和``filter:``
前缀。你需要通过``loadserver``和``loadfilter``来加载它们。这些配置的工作方式相同;你会等到
相应的对象。
Filter Composition
过滤器
~~~~~~~~~~~~~~~~~~
There are several ways to apply filters to applications. It mostly
depends on how many filters, and in what order you want to apply them.
有多种方法来在程序中应用filter。这主要取决于有多少filters,和你需要它们以何种顺序执行。
The first way is to use the ``filter-with`` setting, like::
第一种方法是使用``filter-with``,比如:
[app:main]
use = egg:MyEgg
filter-with = printdebug
[filter:printdebug]
use = egg:Paste#printdebug
# and you could have another filter-with here, and so on...
Also, two special section types exist to apply filters to your
applications: ``[filter-app:...]`` and ``[pipeline:...]``. Both of
these sections define applications, and so can be used wherever an
application is needed.
同时,你需要两个特定的单元来在程序中应用filters:``[filter-app:...]``和``[pipeline:...]``。
这两个单元都声明了程序,因此可以在任何需要的地方使用。
``filter-app`` defines a filter (just like you would in a
``[filter:...]`` section), and then a special key ``next`` which
points to the application to apply the filter to.
``filter-app``声明一个过滤器(如同你使用``[filter:...]``单元),然后需要一个特定的指向需求
此过滤器的程序的key``next``
``pipeline:`` is used when you need apply a number of filters. It
takes *one* configuration key ``pipeline`` (plus any global
configuration overrides you want). ``pipeline`` is a list of filters
ended by an application, like::
``pipeline``适合在你需要多个过滤器的时候使用。它使用一个配置关键字``pipeline``(以及所有你
需要重写的全局配置项目)。``pipeline``是一个过滤器的列表,并且以一个程序结束,如::
[pipeline:main]
pipeline = filter1 egg:FilterEgg#filter2 filter3 app
[filter:filter1]
...
Getting Configuration
~~~~~~~~~~~~~~~~~~~~~
If you want to get the configuration without creating the application,
you can use the ``appconfig(uri)`` function, which is just like the
``loadapp()`` function except it returns the configuration that would
be used, as a dictionary. Both global and local configuration is
combined into a single dictionary, but you can look at just one or the
other with the attributes ``.local_conf`` and ``.global_conf``.
如果你不想创建程序而得到配置,你可以使用``appconfig(uri)``函数,它与``loadapp()``类似,
只是它返回的是字典类型的配置。全局和本地配置都会被合并进一个单独的字典,但是你可以通过
``.local_conf``或``.global_conf``只得到你想要的。
``egg:`` URIs
-------------
`Python Eggs <http://peak.telecommunity.com/DevCenter/PythonEggs>`_
are a distribution and installation format produced by `setuptools
<http://peak.telecommunity.com/DevCenter/setuptools>`_ that adds
metadata to a normal Python package (among other things).
`Python Eggs <http://peak.telecommunity.com/DevCenter/PythonEggs>`_
是`setuptools <http://peak.telecommunity.com/DevCenter/setuptools>`_
系统的分发和安装格式,它将一些元数据连同其它的东西添加到普通的Python包中。
You don't need to understand a whole lot about Eggs to use them. If
you have a `distutils
<http://python.org/doc/current/lib/module-distutils.html>`_
``setup.py`` script, just change::
要使用Eggs你并不去要全面透彻地了解它。如果你有`distutils
<http://python.org/doc/current/lib/module-distutils.html>`_
``setup.py``脚本,那么将它改为::
from distutils.core import setup
to::
from setuptools import setup
Now when you install the package it will be installed as an egg.
现在当你安装包的时候,它会被以Egg的方式安装.
The first important part about an Egg is that it has a
*specification*. This is formed from the name of your distribution
(the ``name`` keyword argument to ``setup()``), and you can specify a
specific version. So you can have an egg named ``MyApp``, or
``MyApp==0.1`` to specify a specific version.
Egg首要的部分是*specification*。这是从你的分发程序中定义的名字合成的(``name``来自
``setup()``),你也可以指名版本。隐私你可以有一个egg名叫``MyApp``,或``MyApp==0.1``
来指名一个版本号。
The second is *entry points*. These are references to Python objects
in your packages that are named and have a specific protocol.
"Protocol" here is just a way of saying that we will call them with
certain arguments, and expect a specific return value. We'll talk
more about the protocols later_.
其次重要的是*entry points*。其中有关联到对应位置的Python对象的名和指定的协议。
这里的"Protocol"只是我们在调用对象的时候需要附随的一些参数,以及期待特定的返回值。
稍候我们将详细讨论protocols_。
.. _later: `Defining Factories`_
The important part here is how we define entry points. You'll add an
argument to ``setup()`` like::
此处最重要的是我们如何声明entry points。你需要添加一个变量给``setup()``,如::
setup(
name='MyApp',
...
entry_points={
'paste.app_factory': [
'main=myapp.mymodule:app_factory',
'ob2=myapp.mymodule:ob_factory'],
},
)
This defines two applications named ``main`` and ``ob2``. You can
then refer to these by ``egg:MyApp#main`` (or just ``egg:MyApp``,
since ``main`` is the default) and ``egg:MyApp#ob2``.
这里声明了两个程序:``main``和``ob2``。你可以通过``egg:MyApp#main``(或仅仅``egg:MyApp``,
因为``main``是默认的)和``egg:MyApp#ob2``来关联它们。
The values are instructions for importing the objects. ``main`` is
located in the ``myapp.mymodule`` module, in an object named
``app_factory``.
其中的value是为导入对象的指引。``main``是在``myapp.mymodule``模块的
``app_actory``定位的。
There's no way to add configuration to objects imported as Eggs.
没有别的类似Egg的方法可以将配置文件导入。
Defining Factories
------------------
This lets you point to factories (that obey the specific protocols we
mentioned). But that's not much use unless you can create factories
for your applications.
There's a few protocols: ``paste.app_factory``,
``paste.composite_factory``, ``paste.filter_factory``, and lastly
``paste.server_factory``. Each of these expects a callable (like a
function, method, or class).
``paste.app_factory``
~~~~~~~~~~~~~~~~~~~~~~
The application is the most common. You define one like::
def app_factory(global_config, **local_conf):
return wsgi_app
The ``global_config`` is a dictionary, and local configuration is
passed as keyword arguments. The function returns a WSGI application.
``paste.composite_factory``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Composites are just slightly more complex::
def composite_factory(loader, global_config, **local_conf):
return wsgi_app
The ``loader`` argument is an object that has a couple interesting
methods. ``get_app(name_or_uri, global_conf=None)`` return a WSGI
application with the given name. ``get_filter`` and ``get_server``
work the same way.
A more interesting example might be a composite factory that does
something. For instance, consider a "pipeline" application::
def pipeline_factory(loader, global_config, pipeline):
# space-separated list of filter and app names:
pipeline = pipeline.split()
filters = [loader.get_filter(n) for n in pipeline[:-1]]
app = loader.get_app(pipeline[-1])
filters.reverse() # apply in reverse order!
for filter in filters:
app = filter(app)
return app
Then we use it like::
[composite:main]
use = <pipeline_factory_uri>
pipeline = egg:Paste#printdebug session myapp
[filter:session]
use = egg:Paste#session
store = memory
[app:myapp]
use = egg:MyApp
``paste.filter_factory``
~~~~~~~~~~~~~~~~~~~~~~~~~
Filter factories are just like app factories (same signature), except
they return filters. Filters are callables that take a WSGI
application as the only argument, and return a "filtered" version of
that application.
Here's an example of a filter that checks that the ``REMOTE_USER`` CGI
variable is set, creating a really simple authentication filter::
def auth_filter_factory(global_conf, req_usernames):
# space-separated list of usernames:
req_usernames = req_usernames.split()
def filter(app):
return AuthFilter(app, req_usernames)
return filter
class AuthFilter(object):
def __init__(self, app, req_usernames):
self.app = app
self.req_usernames = req_usernames
def __call__(self, environ, start_response):
if environ.get('REMOTE_USER') in self.req_usernames:
return self.app(environ, start_response)
start_response(
'403 Forbidden', [('Content-type', 'text/html')])
return ['You are forbidden to view this resource']
``paste.filter_app_factory``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is very similar to ``paste.filter_factory``, except that it also
takes a ``wsgi_app`` argument, and returns a WSGI application. So if
you changed the above example to::
class AuthFilter(object):
def __init__(self, app, global_conf, req_usernames):
....
Then ``AuthFilter`` would serve as a filter_app_factory
(``req_usernames`` is a required local configuration key in this
case).
``paste.server_factory``
~~~~~~~~~~~~~~~~~~~~~~~~~
This takes the same signature as applications and filters, but returns
a server.
A server is a callable that takes a single argument, a WSGI
application. It then serves the application.
An example might look like::
def server_factory(global_conf, host, port):
port = int(port)
def serve(app):
s = Server(app, host=host, port=port)
s.serve_forever()
return serve
An implementation of ``Server`` is left to the user.
``paste.server_runner``
~~~~~~~~~~~~~~~~~~~~~~~~
Like ``paste.server_factory``, except ``wsgi_app`` is passed as the
first argument, and the server should run immediately.
Outstanding Issues
------------------
* Should add a ``python:`` scheme for loading objects out of modules
directly. It has to include the protocol somehow...?
* Should there be a "default" protocol for each type of object? Since
there's currently only one protocol, it seems like it makes sense
(in the future there could be multiple). Except that
``paste.app_factory`` and ``paste.composite_factory`` overlap
considerably.
* ConfigParser's INI parsing is kind of annoying. I'd like it both
more constrained and less constrained. Some parts are sloppy (like
the way it interprets ``[DEFAULT]``).
* ``config:`` URLs should be potentially relative to other locations,
e.g., ``config:$docroot/...``. Maybe using variables from
``global_conf``?
* Should other variables have access to ``global_conf``?
* Should objects be Python-syntax, instead of always strings? Lots of
code isn't usable with Python strings without a thin wrapper to
translate objects into their proper types.
* Some short-form for a filter/app, where the filter refers to the
"next app". Maybe like::
[app-filter:app_name]
use = egg:...
next = next_app
[app:next_app]
...