Skip to content

Commit 0336332

Browse files
authored
Accept and merge RFC0035 on additions to #requires (#122)
* Add #requires RFC draft * Correct language area * More info on hashbangs * Add PR info for interactive #requires * Edit RFC inline with committee ruling * Move withdrawn proposals to the bottom * Accept and merge RFC0035 on #requires additions * Fix small typo in RFC0035
2 parents 5192823 + ae5a103 commit 0336332

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
RFC: RFC
3+
Author: Robert Holt
4+
Status: Draft-Accepted
5+
SupercededBy:
6+
Version: 0.2
7+
Area: Hash-requires
8+
Comments Due: 2018-05-15
9+
Plan to implement: Yes
10+
---
11+
12+
# \#Requires Additions
13+
14+
Currently, PowerShell's `#requires` statement (or pragma) supports the following parameters:
15+
16+
* `-Version <N>[.<n>]`, where a minimum PowerShell version can be specified
17+
* `-PSSnapin <PSSnapin-Name> [-Version <N><n>]`, where a required PowerShell Snapin can be specified
18+
* `-Modules { <Module-name> | <Hashtable> }`, where PowerShell modules that are required can be specified
19+
* `-ShellId <ShellId>`, where the required Shell ID can be specified
20+
* `-RunAsAdministrator`, where the script is required to be run as administrator
21+
22+
These features are documented in [about_Requires](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires?view=powershell-6), along with the statement that:
23+
24+
> You can use #Requires statements in any script. You
25+
> cannot use them in functions, cmdlets, or snap-ins.
26+
27+
Currently however, this is untrue, as `#requires`
28+
statements are allowed by the parser/tokenizer anywhere in
29+
a script and then effectively hoisted to the top of that
30+
script to be checked before any part of the script is
31+
executed, no matter where they are placed.
32+
33+
This RFC proposes the following changes:
34+
35+
* Emit a warning when parsing scripts where the `#requires`
36+
is not at the top, because of the hoisting behavior.
37+
* Add support for the following new parameters (each
38+
independently up for discussion):
39+
* `-OS {Windows | Linux | MacOS}`, where an
40+
operating system (or possibly combination of them) can
41+
be specified as required. See [this PowerShell issue](https://github.com/PowerShell/PowerShell/issues/3751).
42+
* `-MaximumPSVersion <V>[.<v>]`, where a maximum PowerShell
43+
version can be specified as required. See [this PowerShell issue](https://github.com/PowerShell/PowerShell/issues/2846).
44+
* `-MinimumPSVersion` as an alias of `-MinimumVersion`.
45+
46+
## Motivation
47+
48+
> As a PowerShell user, I will be warned about
49+
> `#requires` statements that won't behave the
50+
> way I might expect based on position.
51+
52+
> As a PowerShell user, I can specify that my script
53+
> `#requires` being run on a specific operating system,
54+
> so that I can effectively, efficiently and declaratively
55+
> guarantee that it is used only on systems I designed it
56+
> for.
57+
58+
> As a PowerShell user, I can specify that my script
59+
> `#requires` to be run in a version of PowerShell
60+
> lower than a given version, so that I can declaratively
61+
> prevent it from being run in an environment where
62+
> changes to PowerShell would cause unintended behavior.
63+
64+
## Specification
65+
66+
1. `#requires` statements appearing after any
67+
line that is not blank or a comment (i.e. any semantic statement)
68+
will generate a warning at parse-time about being hoisted to the top of the script.
69+
Other comments, such as hashbangs, and blank lines
70+
preceding a `#requires` will not generate this warning.
71+
2. `#requires` can take an `-OS` parameter,
72+
with possible arguments being `Windows`, `Linux` and `MacOS`.
73+
Multiple operating systems can be specified by providing arguments
74+
in an array syntax, such as `#requires -OS 'Linux','MacOS'`,
75+
with the meaning of **any** of the required operating systems.
76+
The check for a given operating system succeeds
77+
if-and-only-if the correspoding runtime PowerShell variable
78+
(`$IsWindows`, `$IsLinux` and `$IsMacOS`)
79+
executed on that system would be true.
80+
Requiring a given OS when the corresponding runtime variable is false results in
81+
a pre-execution error with a specific error message
82+
stating that the script is required to be run on a
83+
different operating system.
84+
3. `#requires` can take a `-MaximumPSVersion` parameter,
85+
with a major version and optional minor version,
86+
to define the maximum (inclusive) version of PowerShell it should run on.
87+
The version given does not need to correspond to any existing version of PowerShell,
88+
but will be compared in standard PowerShell version comparison logic.
89+
Executing a script required to be on a version of PowerShell strictly lower
90+
than the executing version results in a pre-execution error.
91+
92+
Finally, scripts with `#requires` in them should still
93+
be editable in contexts that do not satisfy their
94+
requirements. For example, a script with `#requires -OS
95+
MacOS` at the top should still allow a full editing user
96+
experience on Windows or Linux. For context, see [this
97+
PowerShell issue](https://github.com/PowerShell/PowerShell/issues/4549).
98+
99+
## Alternate Proposals and Considerations
100+
101+
* Given the suite of proposed changes to `#requires`, any
102+
other proposed parameters for `#requires` are worth
103+
including and discussing in this RFC. Possible
104+
considerations are:
105+
* `-LanguageMode`, where a script must be run in a given
106+
PowerShell language mode.
107+
* `-Architecture`, where a script must be run on a
108+
machine with a given processor architecture.
109+
* `-Platform`, rather than trying to use combining
110+
logic with `-OS`.
111+
* Another requires parameter, `-PSEdition`, also seems to have
112+
been added to the `#requires` functionality. However, it is
113+
currently [undocumented](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires?view=powershell-6) and
114+
there is an [open issue for it](https://github.com/PowerShell/PowerShell/issues/5908). It may
115+
be worth discussing in this RFC.
116+
117+
### Withdrawn proposals
118+
119+
* `-Assembly <Assembly-name>`, where a .NET assembly can
120+
be specified as required. See [this PowerShell #5022](https://github.com/PowerShell/PowerShell/issues/5022).
121+
**Withdrawn in favor of `using` statements.**
122+
* Only allow `#requires` at the top level of a script,
123+
before any lines that are not comments (i.e. with the
124+
intention that a hashbang can still work, just before
125+
any executable PowerShell code). Placing `#requires` anywhere
126+
after will cause a parse-time error. This would be a **breaking
127+
change**, albeit one that the documentation already claims to be
128+
in force.
129+
**Withdrawn on the basis that this could break many existing scripts.**
130+
Instead, a warning is proposed.
131+
* Using `#requires` in the interactive console will cause
132+
a parse-time error. This could be a **minor breaking
133+
change**, since currently PowerShell throws a [pipeline
134+
creation error](https://github.com/PowerShell/PowerShell/issues/3803).
135+
**Withdrawn since this is difficult to implement with little gain and breaks the layering of the parser.**

0 commit comments

Comments
 (0)