Skip to content

Commit 6e10774

Browse files
committed
Merge branch 'master' into 3.6
2 parents 4e9e04a + bad9298 commit 6e10774

28 files changed

Lines changed: 667 additions & 357 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,4 @@ Binaries of IronPython 3 can be downloaded from the [release page](https://githu
8686
See the [building document](Documentation/building.md). Since the main development is on Windows, bugs on other platforms may inadvertently be introduced - please report them!
8787

8888
## Supported Platforms
89-
IronPython 3 targets .NET Framework 4.6, .NET Standard 2.0, .NET Core 3.1 and .NET 6.0. The support for .NET and .NET Core follow the lifecycle defined on [.NET and .NET Core Support Policy](https://dotnet.microsoft.com/platform/support/policy/dotnet-core).
89+
IronPython 3 targets .NET Framework 4.6.2, .NET Standard 2.0, .NET Core 3.1 and .NET 6.0. The support for .NET and .NET Core follow the lifecycle defined on [.NET and .NET Core Support Policy](https://dotnet.microsoft.com/platform/support/policy/dotnet-core).

Src/DLR

Submodule DLR updated 59 files

Src/IronPython.Modules/_ssl.cs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -485,12 +485,13 @@ TLSv1.1 no no yes no yes no
485485
TLSv1.2 no no yes no no yes
486486
*/
487487

488+
#pragma warning disable CA5397 // Do not use deprecated SslProtocols values
489+
#pragma warning disable CS0618 // Type or member is obsolete
490+
#pragma warning disable SYSLIB0039 // Type or member is obsolete
491+
488492
private static SslProtocols GetProtocolType(int protocol, int options) {
489493
SslProtocols result = SslProtocols.None;
490-
491494
switch (protocol) {
492-
#pragma warning disable CA5397 // Do not use deprecated SslProtocols values
493-
#pragma warning disable CS0618 // Type or member is obsolete
494495
case PythonSsl.PROTOCOL_SSLv2:
495496
result = SslProtocols.Ssl2;
496497
break;
@@ -500,33 +501,31 @@ private static SslProtocols GetProtocolType(int protocol, int options) {
500501
case PythonSsl.PROTOCOL_SSLv23:
501502
result = SslProtocols.Ssl2 | SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
502503
break;
503-
#pragma warning restore CS0618 // Type or member is obsolete
504504
case PythonSsl.PROTOCOL_TLSv1:
505505
result = SslProtocols.Tls;
506506
break;
507507
case PythonSsl.PROTOCOL_TLSv1_1:
508508
result = SslProtocols.Tls11;
509509
break;
510-
#pragma warning restore CA5397 // Do not use deprecated SslProtocols values
511510
case PythonSsl.PROTOCOL_TLSv1_2:
512511
result = SslProtocols.Tls12;
513512
break;
514513
default:
515514
throw new InvalidOperationException("bad ssl protocol type: " + protocol);
516515
}
517516
// Filter out requested protocol exclusions:
518-
#pragma warning disable CA5397 // Do not use deprecated SslProtocols values
519-
#pragma warning disable CS0618 // Type or member is obsolete
520517
result &= (options & PythonSsl.OP_NO_SSLv3) != 0 ? ~SslProtocols.Ssl3 : ~SslProtocols.None;
521518
result &= (options & PythonSsl.OP_NO_SSLv2) != 0 ? ~SslProtocols.Ssl2 : ~SslProtocols.None;
522-
#pragma warning restore CS0618 // Type or member is obsolete
523519
result &= (options & PythonSsl.OP_NO_TLSv1) != 0 ? ~SslProtocols.Tls : ~SslProtocols.None;
524520
result &= (options & PythonSsl.OP_NO_TLSv1_1) != 0 ? ~SslProtocols.Tls11 : ~SslProtocols.None;
525521
result &= (options & PythonSsl.OP_NO_TLSv1_2) != 0 ? ~SslProtocols.Tls12 : ~SslProtocols.None;
526-
#pragma warning restore CA5397 // Do not use deprecated SslProtocols values
527522
return result;
528523
}
529524

525+
#pragma warning restore SYSLIB0039 // Type or member is obsolete
526+
#pragma warning restore CS0618 // Type or member is obsolete
527+
#pragma warning restore CA5397 // Do not use deprecated SslProtocols values
528+
530529
public PythonTuple cipher() {
531530
if (_sslStream != null && _sslStream.IsAuthenticated) {
532531
return PythonTuple.MakeTuple(
@@ -540,19 +539,23 @@ public PythonTuple cipher() {
540539

541540
public object compression() => null; // TODO
542541

543-
private string ProtocolToPython() {
544-
switch (_sslStream.SslProtocol) {
545542
#pragma warning disable CA5397 // Do not use deprecated SslProtocols values
546543
#pragma warning disable CS0618 // Type or member is obsolete
544+
#pragma warning disable SYSLIB0039 // Type or member is obsolete
545+
546+
private string ProtocolToPython() {
547+
switch (_sslStream.SslProtocol) {
547548
case SslProtocols.Ssl2: return "SSLv2";
548549
case SslProtocols.Ssl3: return "TLSv1/SSLv3";
549-
#pragma warning restore CS0618 // Type or member is obsolete
550550
case SslProtocols.Tls: return "TLSv1";
551-
#pragma warning restore CA5397 // Do not use deprecated SslProtocols values
552551
default: return _sslStream.SslProtocol.ToString();
553552
}
554553
}
555554

555+
#pragma warning restore SYSLIB0039 // Type or member is obsolete
556+
#pragma warning restore CS0618 // Type or member is obsolete
557+
#pragma warning restore CA5397 // Do not use deprecated SslProtocols values
558+
556559
public object peer_certificate(bool binary_form) {
557560
var peerCert = _sslStream?.RemoteCertificate;
558561

Src/IronPython.Modules/re.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -747,23 +747,25 @@ static string ValidateString(object? str) {
747747
void AppendGroup(StringBuilder sb, int index) => sb.Append(_m.Groups[index].Value);
748748
}
749749

750-
private static bool IsGroupNumber(string name) {
751-
foreach (char c in name) {
752-
if (!char.IsNumber(c)) return false;
753-
}
754-
return true;
755-
}
756-
757750
[return: DictionaryTypeInfo(typeof(string), typeof(object))]
758751
public PythonDictionary groupdict(object? @default = null) {
759752
string[] groupNames = this.re._re.GetGroupNames();
760753
Debug.Assert(groupNames.Length == this._m.Groups.Count);
761754
PythonDictionary d = new PythonDictionary();
762755
for (int i = 0; i < groupNames.Length; i++) {
763-
if (IsGroupNumber(groupNames[i])) continue; // python doesn't report group numbers
764-
d[groupNames[i]] = re.GetGroupValue(_m.Groups[i], @default);
756+
var groupName = groupNames[i];
757+
if (IsGroupNumber(groupName)) continue; // python doesn't report group numbers
758+
if (groupName.StartsWith(_mangledNamedGroup, StringComparison.Ordinal)) continue; // don't include unnamed groups
759+
d[groupName] = re.GetGroupValue(_m.Groups[i], @default);
765760
}
766761
return d;
762+
763+
static bool IsGroupNumber(string name) {
764+
foreach (char c in name) {
765+
if (!char.IsNumber(c)) return false;
766+
}
767+
return true;
768+
}
767769
}
768770

769771
[return: SequenceTypeInfo(typeof(int))]

Src/IronPython/Compiler/Ast/ClassDefinition.cs

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections.Generic;
77
using System.Collections.ObjectModel;
8+
using System.Diagnostics;
89
using System.Diagnostics.CodeAnalysis;
910
using System.Linq;
1011
using System.Runtime.CompilerServices;
@@ -97,15 +98,16 @@ internal override bool HasLateBoundVariableSets {
9798
}
9899
}
99100

100-
internal override bool ExposesLocalVariable(PythonVariable variable) => true;
101+
internal override bool ExposesLocalVariable(PythonVariable variable) {
102+
Debug.Assert(variable.Name == "__class__");
103+
return true;
104+
}
101105

102-
private bool needClassCell { get; set; }
103106

104107
internal override bool TryBindOuter(ScopeStatement from, PythonReference reference, out PythonVariable variable) {
105108
if (reference.Name == "__class__") {
106-
needClassCell = true;
109+
ClassVariable = variable = EnsureClassVariable();
107110
ClassCellVariable = EnsureVariable("__classcell__");
108-
ClassVariable = variable = EnsureVariable(reference.Name);
109111
variable.AccessedInNestedScope = true;
110112
from.AddFreeVariable(variable, true);
111113
for (ScopeStatement scope = from.Parent; scope != this; scope = scope.Parent) {
@@ -124,18 +126,19 @@ internal override bool TryBindOuter(ScopeStatement from, PythonReference referen
124126
// Python semantics: The variables bound local in the class
125127
// scope are accessed by name - the dictionary behavior of classes
126128
if (TryGetVariable(reference.Name, out variable)) {
127-
// TODO: This results in doing a dictionary lookup to get/set the local,
128-
// when it should probably be an uninitialized check / global lookup for gets
129-
// and a direct set
130-
if (variable.Kind == VariableKind.Global) {
129+
if (variable.Kind is VariableKind.Global) {
131130
AddReferencedGlobal(reference.Name);
132-
} else if (variable.Kind == VariableKind.Local) {
131+
} else if (variable.Kind is VariableKind.Local) {
132+
// TODO: This results in doing a dictionary lookup to get/set the local,
133+
// when it should probably be an uninitialized check / global lookup for gets
134+
// and a direct set
133135
return null;
134-
}
135-
136-
if (variable.Kind != VariableKind.Nonlocal) {
136+
} else if (variable.Kind is VariableKind.Attribute) {
137+
return null; // fall back on LookupName/SetName in local context dict, which is faster than LookupGlobalVariable
138+
} else if (variable.Kind is VariableKind.Parameter) {
137139
return variable;
138140
}
141+
// else NonLocal: continue binding
139142
}
140143

141144
// Try to bind in outer scopes, if we have an unqualified exec we need to leave the
@@ -150,6 +153,20 @@ internal override bool TryBindOuter(ScopeStatement from, PythonReference referen
150153
return null;
151154
}
152155

156+
internal override PythonVariable EnsureVariable(string name) {
157+
if (TryGetVariable(name, out PythonVariable variable)) {
158+
return variable;
159+
}
160+
return CreateVariable(name, VariableKind.Attribute);
161+
}
162+
163+
internal PythonVariable EnsureClassVariable() {
164+
if (TryGetVariable("$__class__", out PythonVariable variable)) {
165+
return variable;
166+
}
167+
return CreateVariable("__class__", VariableKind.Local, "$__class__");
168+
}
169+
153170
internal override Ast LookupVariableExpression(PythonVariable variable) {
154171
// Emulates opcode LOAD_CLASSDEREF
155172
return Ast.Call(
@@ -242,6 +259,9 @@ static MSAst.Expression UnpackKeywordsHelper(MSAst.Expression context, ReadOnlyS
242259
}
243260
}
244261

262+
private MSAst.Expression SetLocalName(string name, MSAst.Expression expression)
263+
=> Ast.Call(AstMethods.SetName, LocalContext, Ast.Constant(name), expression);
264+
245265
private Microsoft.Scripting.Ast.LightExpression<Func<CodeContext, CodeContext>> MakeClassBody() {
246266
// we always need to create a nested context for class defs
247267

@@ -260,44 +280,41 @@ private Microsoft.Scripting.Ast.LightExpression<Func<CodeContext, CodeContext>>
260280
var createLocal = CreateLocalContext(_parentContextParam);
261281

262282
init.Add(Ast.Assign(LocalCodeContextVariable, createLocal));
263-
// __classcell__ == ClosureCell(__class__)
264-
if (needClassCell) {
265-
var exp = (ClosureExpression) GetVariableExpression(ClassVariable!);
266-
MSAst.Expression assignClassCell = AssignValue(GetVariableExpression(ClassCellVariable!), exp.ClosureCell);
267-
init.Add(assignClassCell);
268-
}
269-
270-
List<MSAst.Expression> statements = new List<MSAst.Expression>();
271-
// Create the body
272-
MSAst.Expression bodyStmt = Body;
273-
274283

275284
// __module__ = __name__
276-
MSAst.Expression modStmt = AssignValue(GetVariableExpression(ModVariable!), GetVariableExpression(ModuleNameVariable!));
285+
MSAst.Expression modStmt = SetLocalName("__module__", AstUtils.Convert(GetVariableExpression(ModuleNameVariable!), typeof(object)));
286+
287+
// TODO: set __qualname__
277288

289+
// __doc__ = """..."""
290+
MSAst.Expression? docStmt = null;
278291
string doc = GetDocumentation(Body);
279-
if (doc != null) {
280-
statements.Add(
281-
AssignValue(
282-
GetVariableExpression(DocVariable!),
283-
AstUtils.Constant(doc)
284-
)
285-
);
292+
if (doc is not null) {
293+
docStmt = SetLocalName("__doc__", Ast.Constant(doc, typeof(object)));
286294
}
287295

296+
// Create the body
297+
MSAst.Expression bodyStmt = Body;
288298
if (Body.CanThrow && GlobalParent.PyContext.PythonOptions.Frames) {
289299
bodyStmt = AddFrame(LocalContext, FuncCodeExpr, bodyStmt);
290300
locals.Add(FunctionStackVariable);
291301
}
292302

303+
// __classcell__ == ClosureCell(__class__)
304+
MSAst.Expression? assignClassCellStmt = null;
305+
if (ClassVariable is not null) {
306+
var exp = (ClosureExpression)GetVariableExpression(ClassVariable);
307+
assignClassCellStmt = AssignValue(GetVariableExpression(ClassCellVariable!), exp.ClosureCell);
308+
}
309+
293310
bodyStmt = WrapScopeStatements(
294311
Ast.Block(
295312
Ast.Block(init),
296-
statements.Count == 0 ?
297-
EmptyBlock :
298-
Ast.Block(new ReadOnlyCollection<MSAst.Expression>(statements)),
299313
modStmt,
314+
// __qualname__
315+
docStmt is not null ? docStmt : AstUtils.Empty(),
300316
bodyStmt,
317+
assignClassCellStmt is not null ? assignClassCellStmt : AstUtils.Empty(),
301318
LocalContext
302319
),
303320
Body.CanThrow

Src/IronPython/Compiler/Ast/PythonNameBinder.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,20 +118,20 @@ private void Bind(PythonAst unboundAst) {
118118
// Find all scopes and variables
119119
unboundAst.Walk(this);
120120

121-
// Bind
121+
// Bind scopes
122122
foreach (ScopeStatement scope in _scopes) {
123123
scope.Bind(this);
124124
}
125125

126-
// Finish the globals
126+
// Bind globals
127127
unboundAst.Bind(this);
128128

129-
// Finish Binding w/ outer most scopes first.
129+
// Finish binding w/ outer most scopes first.
130130
for (int i = _scopes.Count - 1; i >= 0; i--) {
131131
_scopes[i].FinishBind(this);
132132
}
133133

134-
// Finish the globals
134+
// Finish globals
135135
unboundAst.FinishBind(this);
136136

137137
// Run flow checker

Src/IronPython/Compiler/Ast/ScopeStatement.cs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ internal virtual MSAst.Expression GetParentClosureTuple() {
311311
throw new NotSupportedException();
312312
}
313313

314-
private bool TryGetAnyVariable(string name, out PythonVariable variable) {
314+
internal bool TryGetVariable(string name, out PythonVariable variable) {
315315
if (Variables != null) {
316316
return Variables.TryGetValue(name, out variable);
317317
} else {
@@ -320,15 +320,6 @@ private bool TryGetAnyVariable(string name, out PythonVariable variable) {
320320
}
321321
}
322322

323-
internal bool TryGetVariable(string name, out PythonVariable variable) {
324-
if (TryGetAnyVariable(name, out variable)) {
325-
return true;
326-
} else {
327-
variable = null;
328-
return false;
329-
}
330-
}
331-
332323
internal virtual bool TryBindOuter(ScopeStatement from, PythonReference reference, out PythonVariable variable) {
333324
// Hide scope contents by default (only functions expose their locals)
334325
variable = null;
@@ -381,7 +372,7 @@ internal virtual void FinishBind(PythonNameBinder binder) {
381372
if (Variables != null) {
382373
foreach (PythonVariable variable in Variables.Values) {
383374
if (!HasClosureVariable(closureVariables, variable) &&
384-
variable.Kind is not VariableKind.Global and not VariableKind.Nonlocal &&
375+
variable.Kind is VariableKind.Local or VariableKind.Parameter &&
385376
(variable.AccessedInNestedScope || ExposesLocalVariable(variable))) {
386377

387378
if (closureVariables == null) {
@@ -398,6 +389,8 @@ variable.Kind is not VariableKind.Global and not VariableKind.Nonlocal &&
398389
} else {
399390
_variableMapping[variable] = Ast.Parameter(typeof(object), variable.Name);
400391
}
392+
} else if (variable.Kind == VariableKind.Attribute) {
393+
_variableMapping[variable] = new LookupGlobalVariable(LocalContext, variable.Name, isLocal: true); // TODO: If no user-supplied dictionary is in place, optimize to use more efficient access, see CollectableCompilationMode
401394
}
402395
}
403396
}
@@ -461,15 +454,15 @@ private bool TryGetNonlocalStatement(string name, out NonlocalStatement node) {
461454
return _nonlocalVars?.TryGetValue(name, out node) ?? false;
462455
}
463456

464-
internal PythonVariable/*!*/ CreateVariable(string name, VariableKind kind) {
457+
internal PythonVariable/*!*/ CreateVariable(string name, VariableKind kind, string key = null) {
465458
EnsureVariables();
466-
Debug.Assert(!Variables.ContainsKey(name));
459+
Debug.Assert(!Variables.ContainsKey(key ?? name));
467460
PythonVariable variable;
468-
Variables[name] = variable = new PythonVariable(name, kind, this);
461+
Variables[key ?? name] = variable = new PythonVariable(name, kind, this);
469462
return variable;
470463
}
471464

472-
internal PythonVariable/*!*/ EnsureVariable(string name) {
465+
internal virtual PythonVariable/*!*/ EnsureVariable(string name) {
473466
PythonVariable variable;
474467
if (!TryGetVariable(name, out variable)) {
475468
return CreateVariable(name, VariableKind.Local);

Src/IronPython/Compiler/Ast/VariableKind.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ public enum VariableKind {
3535
///
3636
/// Provides a by-reference access to a local variable in an outer scope.
3737
/// </summary>
38-
Nonlocal
38+
Nonlocal,
39+
40+
/// <summary>
41+
/// Attrribute variable.
42+
///
43+
/// Like a local variable, but is stored directly in the context dictionary,
44+
/// rather than a closure cell.
45+
/// Should only appear in a class lambda.
46+
/// </summary>
47+
Attribute
3948
}
4049
}

Src/IronPython/Modules/_io.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,12 +1991,7 @@ public void __init__(
19911991
throw PythonOps.ValueError(string.Format("illegal newline value: " + newline));
19921992
}
19931993

1994-
if (encoding == null) {
1995-
encoding = PythonLocale.PreferredEncoding;
1996-
if (encoding == "") {
1997-
encoding = "ascii";
1998-
}
1999-
}
1994+
encoding ??= PythonLocale.PreferredEncoding;
20001995

20011996
if (errors == null) {
20021997
errors = "strict";

0 commit comments

Comments
 (0)