修訂 | 212744e62e62a75ee0a4b8705bc98b00f4559642 (tree) |
---|---|
時間 | 2024-02-13 03:20:53 |
作者 | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
ASIS/Start: PyPackages: DeploymentView/Design for the new packages
@@ -0,0 +1,163 @@ | ||
1 | +.. (C) 2023,2024 Albert Mietus. Part of CCastle project | |
2 | + | |
3 | +.. _AR_PyPackages: | |
4 | + | |
5 | +.. sidebar:: Note | |
6 | + | |
7 | + In this article we focus on the python implementation of CCastle Compiler, and use python terminology. Partly, | |
8 | + because it is needed to design that well, partly because this is a first step into the ultimate goal, the CCastle | |
9 | + implementation of all Castle :ref:`Workshop Tools <Workshop-Design>`. | |
10 | + |BR| | |
11 | + And, because “the zen of python” is a good inspiration, studding it seems wise. | |
12 | + | |
13 | +=============================== | |
14 | +Short: PyPackages (START/DRAFT) | |
15 | +=============================== | |
16 | + | |
17 | +Most of the AR-components as described in e.g ‘:ref:`AR_pipeline`’ are *plugins*: independent deplorable packages. | |
18 | +As there are two views of *packages* [#packaging]_, associated by how to use them: (1) *import* and (2) *distribution* | |
19 | +packages, we need to **design** this well. | |
20 | + | |
21 | +Seen from the ‘*4+1 Architectural View Model*’ [#4+1AR]_ this is part of the “Deployment view”. And as such, a valuable reason to describe & | |
22 | +study the options in details | |
23 | + | |
24 | +.. admonition:: Summary & Conclusions (ToDo) | |
25 | + | |
26 | + For those, that are not interested in de design-study, this is the result | |
27 | + | |
28 | + * The top-level namespace is ‘castle’, for all public, more-or-less official packages | |
29 | + * Only base packages (which can’t be a plugin) are located directly in ‘castle’ | |
30 | + |BR| | |
31 | + This is mainly the common intermediate langage (``castle.aigr``), and the code to load the plugins and put them in | |
32 | + the pipeline (``castle.monorail``). Also some generic “main/app” routines can be located there. | |
33 | + * Most packages are plugins and use a namespace that denotes the “location” in the pipeline; in plural form to | |
34 | + denotes the are options. | |
35 | + |BR| | |
36 | + ``castle.readers.<name>``, ``castle.transformers.<name>``, ``castle.writers.<name>`` (not *backends*, as only the | |
37 | + writer-part is part of Castle.) | |
38 | + * Use “pep 420” *native namespace packages* for all plugins. | |
39 | + |BR| | |
40 | + In short: do never put an `__init__.py` file in the shared namespaces -- Only the “main” packages is allowed to put | |
41 | + files there. | |
42 | + * Optional, auxiliary (plugin) packages are usually named (placed-in) ``castle.<loc>.plugins.<opt>``. | |
43 | + * Local (non public) extensions should normally *not* be in ‘castle’. | |
44 | + | |
45 | +Before we describe the design, let study the options, our needs and how others handle this. | |
46 | + | |
47 | +Importing | |
48 | +--------- | |
49 | + | |
50 | +When `import`\ing a package we (typical) use a hierarchical namespace to make the functionality of (a part of) the | |
51 | +package available. For example ``import castle.aigr`` will load that common package. | |
52 | +|BR| | |
53 | +It dotted name show :ref:`aigr<AIGR>` is part of castle. | |
54 | + | |
55 | +Packages that are optional, or where alternatives are available, are conveniently bundled in an extra ‘layer’: | |
56 | + | |
57 | +- ``from castle.readers import typicalReader as reader`` | |
58 | +- ``from castle.readers import mockReader as reader`` | |
59 | + |BR| | |
60 | + Although some would vote for ``from castle.readers.mocks import reader`` for the latter. | |
61 | + | |
62 | +The “dotted names” gives the user/sw-engineer an hint on which (sub)packages are available, and where it fits. Aside of | |
63 | +that, the name is not very important -- the functionality doesn't depend on it. | |
64 | + | |
65 | +.. note:: The functionality does not depend on the name! | |
66 | + | |
67 | + After a package is imported, all it’s functionality is available; always. The name of the (sub)package isn’t | |
68 | + relevant, nor is the (disk) location. | |
69 | + It is also possible to use castle-plugins when they are not located in the *castle.namespace*. As shown by the | |
70 | + next example: | |
71 | + |BR| | |
72 | + ``from myLocal.Hack import MyOwnReader as reader`` (not advised). | |
73 | + | |
74 | +Installing | |
75 | +---------- | |
76 | + | |
77 | +When `(pip) install`\ing a **distribution** package, typically a zip-file is downloaded, and extracte into a | |
78 | +directory. The name of that directory typically correspondes with the namespace, when importing. | |
79 | +|BR| | |
80 | +The developer of a distribution specifies (has to design) in which namespaces (“directory”) the functionality becomes | |
81 | +available. | |
82 | + | |
83 | +For small, simple packages this is straightforward. Typically, the *directories* ‘in’ the distribution (zipfile) match the | |
84 | +name(s) that are used to import it. | |
85 | +|BR| | |
86 | +For bigger packages --especially when using plugins, and multiple parties can contribute and (independently) distribute | |
87 | +sub-packages-- it a bit more complicated. All parties should agree on the name(s), to make is clear for the users. | |
88 | + | |
89 | +A typical user expect that all packages for CCastle become available in `castle.`, or something that is close to it | |
90 | +[#sphinxcontrib]_ | |
91 | + | |
92 | +Related | |
93 | +------- | |
94 | + | |
95 | +There is a clear relation between the tow kind of packages, and for small packages the are typical 1:1. All (importable) | |
96 | +sub-packages are in the same “zip. | |
97 | +|BR| | |
98 | +For bigger packages/distributions -- and certainly for when using “plugins”-- this is not the case. | |
99 | + | |
100 | +Namespaces Packages | |
101 | +------------------- | |
102 | + | |
103 | +It is possible to combine several *distribution packages* into one *importable* packages (structure). This is called | |
104 | +*namespace package(s)*. Since python-3.3 (pep 420), this is standardised in `Native namespace packages | |
105 | +<https://packaging.python.org/en/latest/guides/packaging-namespace-packages/#native-namespace-packages>`__. | |
106 | + | |
107 | +In short: each independent sub-package-developer should use of a common (same name), but “empty” top-directory. That | |
108 | +dir should be ‘in’ the distribution-package (aka the zipfile). That dir should only contain a (1) sub-dir. And all files | |
109 | +should be in that sub-dir. | |
110 | + | |
111 | +.. warning:: The name of that common directory should be aligned! | |
112 | + | |
113 | +XXXX | |
114 | + | |
115 | + | |
116 | + | |
117 | +Why? | |
118 | +==== | |
119 | + | |
120 | +Clarity | |
121 | +-------- | |
122 | + | |
123 | +It should be easy for the user to understand which package is related to CCastle and how it is related. Some packages are | |
124 | +mandatory (e.g :ref:`castle.aigr <AIGR>`) or are needed in de base-setup, others are (external) plugins. But packages | |
125 | +also have a place in the :ref:`AIGR pipeline <AR_pipeline>` -- it’s convenient to effortlessly tell *readers* and | |
126 | +*backends* (etc) aside. | |
127 | + | |
128 | +Ownership | |
129 | +--------- | |
130 | + | |
131 | +Each (distribution) package has an owner too. Typical, the have there own “code archive”, own “package-numbering” and | |
132 | +“release cycle”, ect. This also aplies to plugins! They should be (able to) deployed independently. | |
133 | +|BR| | |
134 | +In practice, “ownership” (like: who owns the code-archive, but also “when” to release) are the borders that define the | |
135 | +distribution-packages. | |
136 | + | |
137 | + | |
138 | + | |
139 | +------ | |
140 | + | |
141 | + | |
142 | +.. rubric:: Footnotes | |
143 | + | |
144 | +.. [#packaging] | |
145 | + .. seealso:: https://packaging.python.org/en/latest/tutorials/packaging-projects | |
146 | + | |
147 | +.. [#4+1AR] | |
148 | + I often use a “modern, OO variation of the standard `4+1 AR model <https://en.wikipedia.org/wiki/4+1_architectural_view_model>`__” | |
149 | + to describe architecture. As the `original paper <https://www.cs.ubc.ca/~gregor/teaching/papers/4+1view-architecture.pdf>`__ | |
150 | + comes from the pre-OO-era, its jargon is a bit outdated. | |
151 | + |BR| | |
152 | + See e.g. http://systemenbetermaken.nl/AR/ for some slides about it -- one-day I will make a blog .. | |
153 | + | |
154 | + | |
155 | +.. [#sphinxcontrib] | |
156 | + For example many extensions for “Sphinx” are available as a sub-package of ``sphinxcontrib``, where sphinx itself is | |
157 | + locates in ``sphinx`` (notice: `sphinxcontrib` is used, not `sphinx.contrib` -- possible because namespace-package | |
158 | + wheren’t available/standardised when sphinx(contrib) started.) | |
159 | + |BR| | |
160 | + In this location one can find mostly “standard extensions”. | |
161 | + | |
162 | + Other (independent) sphinx-additions are installed (aka can be found) in ``sphinx_<name>``. Despite those namespaces | |
163 | + (and directories) are completely independent for a human/user it clear the are related. |