Browse files

sync to head of tfs for 0.9.5.0 (rc3)

  • Loading branch information...
1 parent 94ac739 commit c2a69ce30a8be06bb276e1f366533e8d5800c854 @jredville jredville committed Mar 12, 2010
Showing with 9,674 additions and 346 deletions.
  1. +3 −2 Merlin/External.LCA_RESTRICTED/Languages/Ruby/redist-libs/ruby/site_ruby/1.8/rubygems/platform.rb
  2. +2 −2 ...n/External.LCA_RESTRICTED/Languages/Ruby/redist-libs/ruby/site_ruby/1.8/rubygems/specification.rb
  3. +297 −62 Merlin/Main/Languages/IronPython/IronPython.Modules/_ssl.cs
  4. +446 −48 Merlin/Main/Languages/IronPython/IronPython.Modules/socket.cs
  5. +2 −0 Merlin/Main/Languages/IronPython/IronPython/Compiler/Ast/AstMethods.cs
  6. +24 −3 Merlin/Main/Languages/IronPython/IronPython/Compiler/Ast/BinaryExpression.Generated.cs
  7. +22 −0 Merlin/Main/Languages/IronPython/IronPython/Compiler/Ast/BinaryExpression.cs
  8. +30 −2 Merlin/Main/Languages/IronPython/IronPython/Compiler/Ast/ConstantExpression.cs
  9. +10 −4 Merlin/Main/Languages/IronPython/IronPython/Compiler/Parser.cs
  10. +6 −0 Merlin/Main/Languages/IronPython/IronPython/Compiler/Token.cs
  11. +3 −0 Merlin/Main/Languages/IronPython/IronPython/Compiler/Tokenizer.cs
  12. +4 −2 Merlin/Main/Languages/IronPython/IronPython/Lib/iptest/assert_util.py
  13. +0 −8 Merlin/Main/Languages/IronPython/IronPython/Modules/Builtin.Generated.cs
  14. +4 −1 Merlin/Main/Languages/IronPython/IronPython/Modules/Builtin.cs
  15. +6 −4 Merlin/Main/Languages/IronPython/IronPython/Runtime/Binding/MetaPythonType.Members.cs
  16. +0 −16 Merlin/Main/Languages/IronPython/IronPython/Runtime/Exceptions/PythonExceptions.Generated.cs
  17. +0 −2 Merlin/Main/Languages/IronPython/IronPython/Runtime/Exceptions/PythonExceptions.cs
  18. +22 −1 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/ComplexOps.cs
  19. +4 −49 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/LongOps.cs
  20. +11 −10 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/PythonOps.cs
  21. +1 −1 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/StringOps.cs
  22. +1 −1 Merlin/Main/Languages/IronPython/IronPython/Runtime/PythonContext.cs
  23. +20 −2 Merlin/Main/Languages/IronPython/IronPython/Runtime/StringFormatter.cs
  24. +1 −1 Merlin/Main/Languages/IronPython/IronPython/Runtime/Super.cs
  25. +3 −2 Merlin/Main/Languages/IronPython/IronPython/Runtime/Types/BuiltinFunction.cs
  26. +17 −3 Merlin/Main/Languages/IronPython/IronPython/Runtime/Types/OldClass.cs
  27. +7 −0 Merlin/Main/Languages/IronPython/IronPython/Runtime/Types/TypeCache.Generated.cs
  28. +1 −0 Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs
  29. +48 −0 Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/ClrTests.cs
  30. +3 −1 Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs
  31. +9 −5 Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ModuleOps.cs
  32. +10 −15 Merlin/Main/Languages/Ruby/Libs/rbconfig.rb
  33. +2,905 −0 Merlin/Main/Languages/Ruby/Public/CHANGELOG.txt
  34. +86 −0 Merlin/Main/Languages/Ruby/Public/LICENSE.CPL.txt
  35. +44 −0 Merlin/Main/Languages/Ruby/Public/LICENSE.MSPL.html
  36. +58 −0 Merlin/Main/Languages/Ruby/Public/LICENSE.Ruby.txt
  37. +46 −0 Merlin/Main/Languages/Ruby/Public/README.txt
  38. +64 −0 Merlin/Main/Languages/Ruby/Public/silverlight/README.txt
  39. +26 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/clock/python/app/app.py
  40. +88 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/clock/python/app/app.xaml
  41. +43 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/clock/python/index.html
  42. +29 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/clock/ruby/app/Silverlight.rb
  43. +44 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/clock/ruby/app/app.rb
  44. +88 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/clock/ruby/app/app.xaml
  45. +44 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/clock/ruby/index.html
  46. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/images/loading.gif
  47. +124 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/index.html
  48. +79 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/css/lightbox.css
  49. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/images/blank.gif
  50. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/images/close.gif
  51. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/images/closelabel.gif
  52. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/images/loading.gif
  53. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/images/next.gif
  54. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/images/nextlabel.gif
  55. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/images/prev.gif
  56. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/images/prevlabel.gif
  57. +903 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/js/effects.js
  58. +817 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/js/lightbox.js
  59. +1,785 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/js/prototype.js
  60. +45 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/lightbox/js/scriptaculous.js
  61. BIN Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/ruby/System.Json.dll
  62. +69 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/ruby/app.rb
  63. +75 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/ruby/render.rb
  64. +141 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/ruby/silverlight.rb
  65. +22 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/ruby/system-json.rb
  66. +86 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/photoviewer/stylesheets/screen.css
  67. +47 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/repl/python/console.css
  68. +100 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/repl/python/index.html
  69. +9 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/repl/python/python/app.py
  70. +47 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/repl/ruby/console.css
  71. +100 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/repl/ruby/index.html
  72. +8 −0 Merlin/Main/Languages/Ruby/Public/silverlight/samples/repl/ruby/ruby/app.rb
  73. +3 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/chr
  74. +1 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/chr.bat
  75. +42 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/sl
  76. +55 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/sl.bat
  77. +14 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/python/app/app.py
  78. +9 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/python/app/app.xaml
  79. +15 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/python/css/screen.css
  80. +114 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/python/index.html
  81. +32 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/python/js/error.js
  82. +15 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/ruby/app/app.rb
  83. +9 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/ruby/app/app.xaml
  84. +15 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/ruby/css/screen.css
  85. +114 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/ruby/index.html
  86. +32 −0 Merlin/Main/Languages/Ruby/Public/silverlight/script/templates/ruby/js/error.js
  87. +34 −0 Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Tokenizer.cs
  88. +3 −1 Merlin/Main/Languages/Ruby/Scripts/bin/ir
  89. +1 −1 Merlin/Main/Languages/Ruby/Tests/Interop/net/uncategorized_spec.rb
  90. +35 −16 Merlin/Main/Languages/Ruby/rakelib/package.rake
  91. +4 −65 Merlin/Main/Runtime/Microsoft.Dynamic/Math/BigIntegerV4.cs
  92. +88 −16 Merlin/Main/Runtime/Microsoft.Dynamic/Utils/MathUtils.cs
View
5 ...xternal.LCA_RESTRICTED/Languages/Ruby/redist-libs/ruby/site_ruby/1.8/rubygems/platform.rb
@@ -70,8 +70,8 @@ def initialize(arch)
when /hpux(\d+)/ then [ 'hpux', $1 ]
when /^java$/, /^jruby$/ then [ 'java', nil ]
when /^java([\d.]*)/ then [ 'java', $1 ]
- when /^\.net$/ then [ '.net', nil ]
- when /^\.net([\d.]*)/ then [ '.net', $1 ]
+ when /^dotnet$/ then [ 'dotnet', nil ]
+ when /^dotnet([\d.]*)/ then [ 'dotnet', $1 ]
when /linux/ then [ 'linux', $1 ]
when /mingw32/ then [ 'mingw32', nil ]
when /(mswin\d+)(\_(\d+))?/ then
@@ -150,6 +150,7 @@ def =~(other)
when /^i686-darwin(\d)/ then ['x86', 'darwin', $1 ]
when /^i\d86-linux/ then ['x86', 'linux', nil ]
when 'java', 'jruby' then [nil, 'java', nil ]
+ when /dotnet(\-(\d+\.\d+))?/ then ['universal','dotnet', $2 ]
when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2 ]
when 'powerpc-darwin' then ['powerpc', 'darwin', nil ]
when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1 ]
View
4 ...al.LCA_RESTRICTED/Languages/Ruby/redist-libs/ruby/site_ruby/1.8/rubygems/specification.rb
@@ -305,13 +305,13 @@ def self._load(str)
raise TypeError, "invalid Gem::Specification format #{array.inspect}"
end
- if array[8] == "universal-.net"
+ if array[8] == "universal-dotnet"
# When installing gems from a remote server that is using MRI, the gem information that is
# sent down to the local machine is incorrect since MRI is not able to parse the platform
# string of "universal-.net" until a patch is applied to RubyGems in Gem::Platform#initialize,
# similar to the way other platforms are handled in that method. IronRuby does include
# this patch. For now, we work around the problem.
- array[16] = Gem::Platform.new(["universal", ".net"]) if array[16] == Gem::Platform.new(["universal", "unknown"])
+ array[16] = Gem::Platform.new(["universal", "dotnet"]) if array[16] == Gem::Platform.new(["universal", "unknown"])
end
spec.instance_variable_set :@rubygems_version, array[0]
View
359 Merlin/Main/Languages/IronPython/IronPython.Modules/_ssl.cs
@@ -17,23 +17,33 @@
using System;
using System.IO;
-using System.Net.Sockets;
-using System.Net.Security;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using Microsoft.Scripting.Runtime;
+using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
+using System.Text;
+
+using Microsoft.Scripting.Utils;
+
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using IronPython.Runtime.Types;
-using Microsoft.Scripting;
-using System.Runtime.CompilerServices;
-/* [assembly: PythonModule("_ssl", typeof(IronPython.Modules.PythonSsl))] */
+
+[assembly: PythonModule("_ssl", typeof(IronPython.Modules.PythonSsl))]
namespace IronPython.Modules {
- public static partial class PythonSocket { // PythonSsl
- // public const string __doc__ = "Implementation module for SSL socket operations.";
+ public static class PythonSsl {
+ public const string __doc__ = "Implementation module for SSL socket operations.";
+ [SpecialName]
+ public static void PerformModuleReload(PythonContext/*!*/ context, PythonDictionary/*!*/ dict) {
+ var socket = context.GetBuiltinModule("socket");
+ var socketError = PythonSocket.GetSocketError(context, socket.__dict__);
+
+ context.EnsureModuleException("SSLError", socketError, dict, "SSLError", "ssl");
+
+ }
#region Stubs for RAND functions
// The RAND_ functions are effectively no-ops, as the BCL draws on system sources
@@ -51,81 +61,306 @@ public static partial class PythonSocket { // PythonSsl
#endregion
- public static PythonType SSLType = DynamicHelpers.GetPythonTypeFromType(typeof(ssl));
+ public static PythonType SSLType = DynamicHelpers.GetPythonTypeFromType(typeof(PythonSocket.ssl));
+
+ public static PythonSocket.ssl sslwrap(
+ CodeContext context,
+ PythonSocket.socket socket,
+ bool server_side,
+ [DefaultParameterValue(null)] string keyfile,
+ [DefaultParameterValue(null)] string certfile,
+ [DefaultParameterValue(PythonSsl.CERT_NONE)]int certs_mode,
+ [DefaultParameterValue(-1)]int protocol,
+ [DefaultParameterValue(null)]string cacertsfile) {
+ return new PythonSocket.ssl(
+ context,
+ socket,
+ server_side,
+ keyfile,
+ certfile,
+ certs_mode,
+ protocol,
+ cacertsfile
+ );
+ }
- public class ssl {
- private readonly SslStream _sslStream;
+ internal static PythonType SSLError(CodeContext/*!*/ context) {
+ return (PythonType)PythonContext.GetContext(context).GetModuleState("SSLError");
+ }
- internal bool CertValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
- return true; // Mimics behavior of CPython 2.5 SSL
- }
+ public static PythonDictionary _test_decode_cert(CodeContext context, string filename, [DefaultParameterValue(false)]bool complete) {
+ var cert = ReadCertificate(context, filename);
- public ssl(PythonSocket.socket sock, [DefaultParameterValue(null)] string keyfile, [DefaultParameterValue(null)] string certfile) {
- _sslStream = new SslStream(new NetworkStream(sock._socket, false), true, CertValidationCallback);
- _sslStream.AuthenticateAsClient(sock._hostName);
+ return CertificateToPython(context, cert, complete);
+ }
+
+ internal static PythonDictionary CertificateToPython(CodeContext context, X509Certificate cert, bool complete) {
+ var dict = new CommonDictionaryStorage();
+
+ dict.AddNoLock("notAfter", ToPythonDateFormat(cert.GetExpirationDateString()));
+ dict.AddNoLock("subject", IssuerToPython(context, cert.Subject));
+ if (complete) {
+ dict.AddNoLock("notBefore", ToPythonDateFormat(cert.GetEffectiveDateString()));
+ dict.AddNoLock("serialNumber", SerialNumberToPython(cert));
+ dict.AddNoLock("version", cert.GetCertHashString());
+ dict.AddNoLock("issuer", IssuerToPython(context, cert.Issuer));
}
- [Documentation("issuer() -> issuer_certificate\n\n"
- + "Returns a string that describes the issuer of the server's certificate. Only useful for debugging purposes."
- )]
- public string issuer() {
- X509Certificate remoteCertificate = _sslStream.RemoteCertificate;
- if (remoteCertificate != null) {
- return remoteCertificate.Issuer;
- } else {
- return String.Empty;
+ return new PythonDictionary(dict);
+ }
+
+ private static string ToPythonDateFormat(string date) {
+ return DateTime.Parse(date).ToUniversalTime().ToString("MMM d HH:mm:ss yyyy") + " GMT";
+ }
+
+ private static string SerialNumberToPython(X509Certificate cert) {
+ var res = cert.GetSerialNumberString();
+ for (int i = 0; i < res.Length; i++) {
+ if (res[i] != '0') {
+ return res.Substring(i);
}
}
+ return res;
+ }
+
+ private static PythonTuple IssuerToPython(CodeContext context, string issuer) {
+ var split = issuer.Split(',');
+ object[] res = new object[split.Length];
+ for(int i = 0; i<split.Length; i++) {
+ res[i] = PythonTuple.MakeTuple(
+ IssuerFieldToPython(context, split[i].Trim())
+ );
+
+ }
+ return PythonTuple.MakeTuple(res);
+ }
+
+ private static PythonTuple IssuerFieldToPython(CodeContext context, string p) {
+ if (String.Compare(p, 0, "CN=", 0, 3) == 0) {
+ return PythonTuple.MakeTuple("commonName", p.Substring(3));
+ } else if (String.Compare(p, 0, "OU=", 0, 3) == 0) {
+ return PythonTuple.MakeTuple("organizationalUnitName", p.Substring(3));
+ } else if (String.Compare(p, 0, "O=", 0, 2) == 0) {
+ return PythonTuple.MakeTuple("organizationName", p.Substring(2));
+ } else if (String.Compare(p, 0, "L=", 0, 2) == 0) {
+ return PythonTuple.MakeTuple("localityName", p.Substring(2));
+ } else if (String.Compare(p, 0, "S=", 0, 2) == 0) {
+ return PythonTuple.MakeTuple("stateOrProvinceName", p.Substring(2));
+ } else if (String.Compare(p, 0, "C=", 0, 2) == 0) {
+ return PythonTuple.MakeTuple("countryName", p.Substring(2));
+ } else if (String.Compare(p, 0, "E=", 0, 2) == 0) {
+ return PythonTuple.MakeTuple("email", p.Substring(2));
+ }
+
+ throw PythonExceptions.CreateThrowable(SSLError(context), "Unknown field: ", p);
+ }
+
+
+ internal static X509Certificate2 ReadCertificate(CodeContext context, string filename) {
+
+ string[] lines;
+ try {
+ lines = File.ReadAllLines(filename);
+ } catch (IOException) {
+ throw PythonExceptions.CreateThrowable(SSLError(context), "Can't open file ", filename);
+ }
- [Documentation("read([n]) -> buffer_read\n\n"
- + "If n is present, reads up to n bytes from the SSL connection. Otherwise, reads to EOF."
- )]
- public string read(CodeContext/*!*/ context, [DefaultParameterValue(Int32.MaxValue)] int n) {
- try {
- byte[] buffer = new byte[2048];
- MemoryStream result = new MemoryStream(n);
- while (true) {
- int readLength = (n < buffer.Length) ? n : buffer.Length;
- int bytes = _sslStream.Read(buffer, 0, readLength);
- if (bytes > 0) {
- result.Write(buffer, 0, bytes);
- n -= bytes;
+ X509Certificate2 cert = null;
+ RSACryptoServiceProvider key = null;
+ try {
+ for (int i = 0; i < lines.Length; i++) {
+ if (lines[i] == "-----BEGIN CERTIFICATE-----") {
+ var certStr = ReadToEnd(lines, ref i, "-----END CERTIFICATE-----");
+
+ try {
+ cert = new X509Certificate2(Convert.FromBase64String(certStr.ToString()));
+ } catch (Exception e) {
+ throw ErrorDecoding(context, filename, e);
}
- if (bytes == 0 || n == 0) {
- return result.ToArray().MakeString();
+ } else if (lines[i] == "-----BEGIN RSA PRIVATE KEY-----") {
+ var keyStr = ReadToEnd(lines, ref i, "-----END RSA PRIVATE KEY-----");
+
+ try {
+ var keyBytes = Convert.FromBase64String(keyStr.ToString());
+
+ key = ParsePkcs1DerEncodedPrivateKey(context, filename, keyBytes);
+ } catch (Exception e) {
+ throw ErrorDecoding(context, filename, e);
}
}
- } catch (Exception e) {
- throw PythonSocket.MakeException(context, e);
}
+ } catch (InvalidOperationException e) {
+ throw ErrorDecoding(context, filename, e.Message);
}
- [Documentation("server() -> server_certificate\n\n"
- + "Returns a string that describes the server's certificate. Only useful for debugging purposes."
- )]
- public string server() {
- X509Certificate remoteCertificate = _sslStream.RemoteCertificate;
- if (remoteCertificate != null) {
- return remoteCertificate.Subject;
- } else {
- return String.Empty;
+ if (cert != null) {
+ if (key != null) {
+ try {
+ cert.PrivateKey = key;
+ } catch(CryptographicException e) {
+ throw ErrorDecoding(context, filename, "cert and private key are incompatible", e);
+ }
}
+ return cert;
+ }
+ throw ErrorDecoding(context, filename, "certificate not found");
+ }
+
+ #region Private Key Parsing
+
+ const int ClassOffset = 6;
+ const int ClassMask = 0xc0;
+ const int ClassUniversal = 0x00 << ClassOffset;
+ const int ClassApplication = 0x01 << ClassOffset;
+ const int ClassContextSpecific = 0x02 << ClassOffset;
+ const int ClassPrivate = 0x03 << ClassOffset;
+
+ const int NumberMask = 0x1f;
+
+ const int UnivesalSequence = 0x10;
+ const int UniversalInteger = 0x02;
+ const int UniversalOctetString = 0x04;
+
+ private static RSACryptoServiceProvider ParsePkcs1DerEncodedPrivateKey(CodeContext context, string filename, byte[] x) {
+ // http://tools.ietf.org/html/rfc3447#appendix-A.1.2
+ // RSAPrivateKey ::= SEQUENCE {
+ // version Version,
+ // modulus INTEGER, -- n
+ // publicExponent INTEGER, -- e
+ // privateExponent INTEGER, -- d
+ // prime1 INTEGER, -- p
+ // prime2 INTEGER, -- q
+ // exponent1 INTEGER, -- d mod (p-1)
+ // exponent2 INTEGER, -- d mod (q-1)
+ // coefficient INTEGER, -- (inverse of q) mod p
+ // otherPrimeInfos OtherPrimeInfos OPTIONAL
+ // }
+
+ // read header for sequence
+ if ((x[0] & ClassMask) != ClassUniversal) {
+ throw ErrorDecoding(context, filename, "failed to find universal class");
+ } else if ((x[0] & NumberMask) != UnivesalSequence) {
+ throw ErrorDecoding(context, filename, "failed to read sequence header");
+ }
+
+ // read length of sequence
+ int offset = 1;
+ int len = ReadLength(x, ref offset);
+
+ // read version
+ int version = ReadUnivesalInt(x, ref offset);
+ if (version != 0) {
+ // unsupported version
+ throw new InvalidOperationException(String.Format("bad vesion: {0}", version));
+ }
+
+ // read in parameters and initialize provider
+ RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
+ RSAParameters parameters = new RSAParameters();
+
+ parameters.Modulus = ReadUnivesalIntAsBytes(x, ref offset);
+ parameters.Exponent = ReadUnivesalIntAsBytes(x, ref offset);
+ parameters.D = ReadUnivesalIntAsBytes(x, ref offset);
+ parameters.P = ReadUnivesalIntAsBytes(x, ref offset);
+ parameters.Q = ReadUnivesalIntAsBytes(x, ref offset);
+ parameters.DP = ReadUnivesalIntAsBytes(x, ref offset);
+ parameters.DQ = ReadUnivesalIntAsBytes(x, ref offset);
+ parameters.InverseQ = ReadUnivesalIntAsBytes(x, ref offset);
+
+ provider.ImportParameters(parameters);
+ return provider;
+ }
+
+ private static byte[] ReadUnivesalIntAsBytes(byte[] x, ref int offset) {
+ ReadIntType(x, ref offset);
+
+ int bytes = ReadLength(x, ref offset);
+
+ // we need to remove any leading 0 bytes which aren't part of a number. Including
+ // them causes our parsing to differ from certification parsing.
+ while (x[offset] == 0) {
+ bytes--;
+ offset++;
+ }
+
+ byte[] res = new byte[bytes];
+ for (int i = 0; i < res.Length; i++) {
+ res[i] = x[offset++];
+ }
+
+ return res;
+
+ }
+
+ private static void ReadIntType(byte[] x, ref int offset) {
+ int versionType = x[offset++];
+ if (versionType != UniversalInteger) {
+ throw new InvalidOperationException(String.Format("expected version, fonud {0}", versionType));
+ }
+ }
+ private static int ReadUnivesalInt(byte[] x, ref int offset) {
+ ReadIntType(x, ref offset);
+
+ return ReadInt(x, ref offset);
+ }
+
+ private static int ReadLength(byte[] x, ref int offset) {
+ int bytes = x[offset++];
+ if ((bytes & 0x80) == 0) {
+ return bytes;
+ }
+
+ return ReadInt(x, ref offset, bytes & ~0x80);
+
+ }
+
+ private static int ReadInt(byte[] x, ref int offset, int bytes) {
+ if (bytes + offset > x.Length) {
+ throw new InvalidOperationException();
}
- [Documentation("write(s) -> bytes_sent\n\n"
- + "Writes the string s through the SSL connection."
- )]
- public int write(CodeContext/*!*/ context, string data) {
- byte[] buffer = data.MakeByteArray();
- try {
- _sslStream.Write(buffer);
- return buffer.Length;
- } catch (Exception e) {
- throw PythonSocket.MakeException(context, e);
+ int res = 0;
+ for (int i = 0; i < bytes; i++) {
+ res = res << 8 | x[offset++];
+ }
+ return res;
+ }
+ /// <summary>
+ /// BER encoding of an integer value is the number of bytes
+ /// required to represent the integer followed by the bytes
+ /// </summary>
+ private static int ReadInt(byte[] x, ref int offset) {
+ int bytes = x[offset++];
+
+ return ReadInt(x, ref offset, bytes);
+ }
+
+ private static string ReadToEnd(string[] lines, ref int start, string end) {
+ StringBuilder key = new StringBuilder();
+ for (start++; start < lines.Length; start++) {
+ if (lines[start] == end) {
+ return key.ToString();
}
+ key.Append(lines[start]);
}
+ return null;
}
+ #endregion
+
+ private static Exception ErrorDecoding(CodeContext context, params object[] args) {
+ return PythonExceptions.CreateThrowable(SSLError(context), ArrayUtils.Insert("Error decoding PEM-encoded file ", args));
+ }
+
+ public const int CERT_NONE = 0;
+ public const int CERT_OPTIONAL = 1;
+ public const int CERT_REQUIRED = 2;
+
+ public const int PROTOCOL_SSLv2 = 0;
+ public const int PROTOCOL_SSLv3 = 1;
+ public const int PROTOCOL_SSLv23 = 2;
+ public const int PROTOCOL_TLSv1 = 3;
+
#region Exported constants
public const int SSL_ERROR_SSL = 1;
View
494 Merlin/Main/Languages/IronPython/IronPython.Modules/socket.cs
@@ -22,32 +22,32 @@
using System.IO;
using System.Net;
using System.Net.Sockets;
+using System.Net.Security;
using System.Runtime.InteropServices;
-using System.Dynamic;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Authentication;
using System.Text;
-using Microsoft.Scripting.Actions;
+using Microsoft.Scripting;
+using Microsoft.Scripting.Runtime;
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using IronPython.Runtime.Types;
-using Microsoft.Scripting;
-using Microsoft.Scripting.Runtime;
#if CLR2
using Microsoft.Scripting.Math;
#else
using System.Numerics;
#endif
-using BaseException = IronPython.Runtime.Exceptions.PythonExceptions.BaseException;
using PythonArray = IronPython.Modules.ArrayModule.array;
using SpecialNameAttribute = System.Runtime.CompilerServices.SpecialNameAttribute;
[assembly: PythonModule("socket", typeof(IronPython.Modules.PythonSocket))]
namespace IronPython.Modules {
- public static partial class PythonSocket {
+ public static class PythonSocket {
private static readonly object _defaultTimeoutKey = new object();
private static readonly object _defaultBufsizeKey = new object();
private const int DefaultBufferSize = 8192;
@@ -60,13 +60,16 @@ public static partial class PythonSocket {
context.SetModuleState(_defaultBufsizeKey, DefaultBufferSize);
- context.EnsureModuleException("sslerror", dict, "sslerror", "socket");
- PythonType socketErr = context.EnsureModuleException("socketerror", PythonExceptions.IOError, dict, "error", "socket");
+ PythonType socketErr = GetSocketError(context, dict);
context.EnsureModuleException("socketherror", socketErr, dict, "herror", "socket");
context.EnsureModuleException("socketgaierror", socketErr, dict, "gaierror", "socket");
context.EnsureModuleException("sockettimeout", socketErr, dict, "timeout", "socket");
}
+ internal static PythonType GetSocketError(PythonContext context, PythonDictionary dict) {
+ return context.EnsureModuleException("socketerror", PythonExceptions.IOError, dict, "error", "socket");
+ }
+
public const string __doc__ = "Implementation module for socket operations.\n\n"
+ "This module is a loose wrapper around the .NET System.Net.Sockets API, so you\n"
+ "may find the corresponding MSDN documentation helpful in decoding error\n"
@@ -122,16 +125,21 @@ public class socket : IWeakReferenceable {
private WeakRefTracker _weakRefTracker = null;
private int _referenceCount = 1;
public const string __module__ = "socket";
- private CodeContext/*!*/ _context;
+ internal CodeContext/*!*/ _context;
+ private int _timeout;
#endregion
#region Public API
- public socket(CodeContext/*!*/ context, [DefaultParameterValue(DefaultAddressFamily)] int addressFamily,
- [DefaultParameterValue(DefaultSocketType)] int socketType,
- [DefaultParameterValue(DefaultProtocolType)] int protocolType) {
+ public socket() {
+ }
+
+ public void __init__(CodeContext/*!*/ context, [DefaultParameterValue(DefaultAddressFamily)] int addressFamily,
+ [DefaultParameterValue(DefaultSocketType)] int socketType,
+ [DefaultParameterValue(DefaultProtocolType)] int protocolType,
+ [DefaultParameterValue(null)]socket _sock) {
System.Net.Sockets.SocketType type = (System.Net.Sockets.SocketType)Enum.ToObject(typeof(System.Net.Sockets.SocketType), socketType);
if (!Enum.IsDefined(typeof(System.Net.Sockets.SocketType), type)) {
throw MakeException(context, new SocketException((int)SocketError.SocketNotSupported));
@@ -145,36 +153,73 @@ public class socket : IWeakReferenceable {
throw MakeException(context, new SocketException((int)SocketError.ProtocolNotSupported));
}
- Socket newSocket;
- try {
- newSocket = new Socket(family, type, proto);
- } catch (SocketException e) {
- throw MakeException(context, e);
+ if (_sock == null) {
+ Socket newSocket;
+ try {
+ newSocket = new Socket(family, type, proto);
+ } catch (SocketException e) {
+ throw MakeException(context, e);
+ }
+
+ Initialize(context, newSocket);
+ } else {
+ _socket = _sock._socket;
+ _hostName = _sock._hostName;
+
+ // we now own the lifetime of the socket
+ GC.SuppressFinalize(_sock);
+ Initialize(context, _socket);
}
- Initialize(context, newSocket);
}
~socket() {
close(true, true);
}
+ public socket _sock {
+ get {
+ return this;
+ }
+ }
+
+
+ private IAsyncResult _acceptResult;
[Documentation("accept() -> (conn, address)\n\n"
+ "Accept a connection. The socket must be bound and listening before calling\n"
+ "accept(). conn is a new socket object connected to the remote host, and\n"
+ "address is the remote host's address (e.g. a (host, port) tuple for IPv4).\n"
+ "\n"
- + "Difference from CPython: accept() does not support timeouts in blocking mode.\n"
- + "If a timeout is set and the socket is in blocking mode, accept() will block\n"
- + "indefinitely until a connection is ready."
)]
public PythonTuple accept() {
socket wrappedRemoteSocket;
Socket realRemoteSocket;
try {
- realRemoteSocket = _socket.Accept();
+ if (_acceptResult != null && _acceptResult.IsCompleted) {
+ // previous async result has completed
+ realRemoteSocket = _socket.EndAccept(_acceptResult);
+ } else {
+ int timeoutTime = _timeout;
+ if (timeoutTime != 0) {
+ // use the existing or create a new async request
+ var asyncResult = _acceptResult ?? _socket.BeginAccept((x) => { }, null);
+
+ if (asyncResult.AsyncWaitHandle.WaitOne(timeoutTime)) {
+ // it's completed, end and throw it away
+ realRemoteSocket = _socket.EndAccept(asyncResult);
+ _acceptResult = null;
+ } else {
+ // save the async result for later incase it completes
+ _acceptResult = asyncResult;
+ throw PythonExceptions.CreateThrowable(timeout(_context), 0, "timeout");
+ }
+ } else {
+ realRemoteSocket = _socket.Accept();
+ }
+ }
} catch (Exception e) {
throw MakeException(_context, e);
}
+
wrappedRemoteSocket = new socket(_context, realRemoteSocket);
return PythonTuple.MakeTuple(wrappedRemoteSocket, wrappedRemoteSocket.getpeername());
}
@@ -205,12 +250,14 @@ public class socket : IWeakReferenceable {
internal void close(bool finalizing, bool removeAll) {
if (finalizing || removeAll || System.Threading.Interlocked.Decrement(ref _referenceCount) == 0) {
- lock (_handleToSocket) {
- WeakReference weakref;
- if (_handleToSocket.TryGetValue(_socket.Handle, out weakref)) {
- Socket target = (weakref.Target as Socket);
- if (target == _socket || target == null) {
- _handleToSocket.Remove(_socket.Handle);
+ if (_socket != null) {
+ lock (_handleToSocket) {
+ WeakReference weakref;
+ if (_handleToSocket.TryGetValue(_socket.Handle, out weakref)) {
+ Socket target = (weakref.Target as Socket);
+ if (target == _socket || target == null) {
+ _handleToSocket.Remove(_socket.Handle);
+ }
}
}
}
@@ -219,11 +266,13 @@ public class socket : IWeakReferenceable {
GC.SuppressFinalize(this);
}
- try {
- _socket.Close();
- } catch (Exception e) {
- if (!finalizing) {
- throw MakeException(_context, e);
+ if (_socket != null) {
+ try {
+ _socket.Close();
+ } catch (Exception e) {
+ if (!finalizing) {
+ throw MakeException(_context, e);
+ }
}
}
}
@@ -355,7 +404,7 @@ public class socket : IWeakReferenceable {
throw MakeException(_context, e);
}
}
-
+
[Documentation("makefile([mode[, bufsize]]) -> file object\n\n"
+ "Return a regular file object corresponding to the socket. The mode\n"
+ "and bufsize arguments are as for the built-in open() function.")]
@@ -416,7 +465,7 @@ public class socket : IWeakReferenceable {
public int recv_into(PythonArray buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
int bytesRead;
byte[] byteBuffer = new byte[byteBufferSize("recv_into", nbytes, buffer.__len__(), buffer.itemsize)];
-
+
try {
bytesRead = _socket.Receive(byteBuffer, (SocketFlags)flags);
} catch (Exception e) {
@@ -427,6 +476,30 @@ public class socket : IWeakReferenceable {
return bytesRead;
}
+
+ [Documentation("recv_into(bytearray, [nbytes[, flags]]) -> nbytes_read\n\n"
+ + "A version of recv() that stores its data into a bytearray rather than creating\n"
+ + "a new string. Receive up to buffersize bytes from the socket. If buffersize\n"
+ + "is not specified (or 0), receive up to the size available in the given buffer.\n\n"
+ + "See recv() for documentation about the flags.\n"
+ )]
+ public int recv_into(ByteArray buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
+ int bytesRead;
+ byte[] byteBuffer = new byte[byteBufferSize("recv_into", nbytes, buffer.Count, 1)];
+
+ try {
+ bytesRead = _socket.Receive(byteBuffer, (SocketFlags)flags);
+ } catch (Exception e) {
+ throw MakeException(_context, e);
+ }
+
+ for (int i = 0; i < bytesRead; i++) {
+ buffer[i] = byteBuffer[i];
+ }
+ return bytesRead;
+ }
+
+
[Documentation("recvfrom(bufsize[, flags]) -> (string, address)\n\n"
+ "Receive data from the socket, up to bufsize bytes. string is the data\n"
+ "received, and address (whose format is protocol-dependent) is the address of\n"
@@ -477,7 +550,7 @@ public class socket : IWeakReferenceable {
byte[] byteBuffer = new byte[byteBufferSize("recvfrom_into", nbytes, buffer.__len__(), buffer.itemsize)];
IPEndPoint remoteIPEP = new IPEndPoint(IPAddress.Any, 0);
EndPoint remoteEP = remoteIPEP;
-
+
try {
bytesRead = _socket.ReceiveFrom(byteBuffer, (SocketFlags)flags, ref remoteEP);
} catch (Exception e) {
@@ -695,6 +768,7 @@ public class socket : IWeakReferenceable {
}
_socket.Blocking = seconds > 0; // 0 timeout means non-blocking mode
_socket.SendTimeout = (int)(seconds * MillisecondsPerSecond);
+ _timeout = (int)(seconds * MillisecondsPerSecond);
}
} finally {
_socket.ReceiveTimeout = _socket.SendTimeout;
@@ -788,8 +862,8 @@ public class socket : IWeakReferenceable {
public override string ToString() {
try {
-
- return String.Format("<socket object, fd={0}, family={1}, type={2}, protocol={3}>",
+
+ return String.Format("<socket object, fd={0}, family={1}, type={2}, protocol={3}>",
fileno(), family, type, proto);
} catch {
return "<socket object, fd=?, family=?, type=, protocol=>";
@@ -853,7 +927,7 @@ public class socket : IWeakReferenceable {
} else {
settimeout((double)defaultTimeout / MillisecondsPerSecond);
}
- _hostName = null;
+
lock (_handleToSocket) {
_handleToSocket[socket.Handle] = new WeakReference(socket);
}
@@ -914,7 +988,8 @@ public class socket : IWeakReferenceable {
PythonTuple sockaddress = (PythonTuple)current[4];
socket socket = null;
try {
- socket = new socket(context, family, socktype, proto);
+ socket = new socket();
+ socket.__init__(context, family, socktype, proto, null);
if (timeout != _GLOBAL_DEFAULT_TIMEOUT) {
socket.settimeout(timeout);
}
@@ -945,7 +1020,7 @@ public class socket : IWeakReferenceable {
[DefaultParameterValue((int)SocketFlags.None)] int flags
) {
int numericPort;
-
+
if (port == null) {
numericPort = 0;
} else if (port is int) {
@@ -1266,7 +1341,7 @@ public class socket : IWeakReferenceable {
[Documentation("ntohl(x) -> integer\n\nConvert a 32-bit integer from network byte order to host byte order.")]
public static object ntohl(object x) {
int res = IPAddress.NetworkToHostOrder(SignInsensitiveToInt32(x));
-
+
if (res < 0) {
return (BigInteger)(uint)res;
} else {
@@ -1304,7 +1379,7 @@ public class socket : IWeakReferenceable {
/// </summary>
private static int SignInsensitiveToInt32(object x) {
BigInteger bigValue = Converter.ConvertToBigInteger(x);
-
+
if (bigValue < 0) {
throw PythonOps.OverflowError("can't convert negative number to unsigned long");
} else if (bigValue <= int.MaxValue) {
@@ -1710,7 +1785,7 @@ public class socket : IWeakReferenceable {
}
}
// Incorrect family will raise exception below
- } else {
+ } else {
IPHostEntry hostEntry = Dns.GetHostEntry(host);
List<IPAddress> addrs = new List<IPAddress>();
foreach (IPAddress ip in hostEntry.AddressList) {
@@ -1888,7 +1963,7 @@ class PythonUserSocketStream : Stream {
_dataSize += strData.Length;
if (_dataSize > _bufSize) {
Flush();
- }
+ }
}
protected override void Dispose(bool disposing) {
@@ -1912,8 +1987,9 @@ public _fileobject(CodeContext/*!*/ context, object socket, [DefaultParameterVal
_close = close;
Stream stream;
- socket s = (socket as socket);
- if (s != null && s._socket.Connected) {
+ // subtypes of socket need to go through the user defined methods
+ if (socket != null && socket.GetType() == typeof(socket) && ((socket)socket)._socket.Connected) {
+ socket s = (socket as socket);
_socket = s;
stream = new NetworkStream(s._socket);
} else {
@@ -1970,10 +2046,332 @@ public _fileobject(CodeContext/*!*/ context, object socket, [DefaultParameterVal
private static PythonType herror(CodeContext/*!*/ context) {
return (PythonType)PythonContext.GetContext(context).GetModuleState("socketherror");
}
-
+
private static PythonType timeout(CodeContext/*!*/ context) {
return (PythonType)PythonContext.GetContext(context).GetModuleState("sockettimeout");
}
+
+ public class ssl {
+ private readonly SslStream _sslStream;
+ private socket _socket;
+ private readonly X509Certificate2Collection _certCollection;
+ private readonly X509Certificate _cert;
+ private readonly int _protocol, _certsMode;
+ private readonly bool _validate, _serverSide;
+ private readonly CodeContext _context;
+ private Exception _validationFailure;
+
+ public ssl(CodeContext context, PythonSocket.socket sock, [DefaultParameterValue(null)] string keyfile, [DefaultParameterValue(null)] string certfile) {
+ _context = context;
+ _sslStream = new SslStream(new NetworkStream(sock._socket, false), true, CertValidationCallback);
+ _socket = sock;
+ _certCollection = new X509Certificate2Collection();
+ _protocol = -1;
+ _validate = false;
+ }
+
+ internal ssl(CodeContext context,
+ PythonSocket.socket sock,
+ bool server_side,
+ [DefaultParameterValue(null)] string keyfile,
+ [DefaultParameterValue(null)] string certfile,
+ [DefaultParameterValue(PythonSsl.CERT_NONE)]int certs_mode,
+ [DefaultParameterValue(-1)]int protocol,
+ string cacertsfile) {
+ if (sock == null) {
+ throw PythonOps.TypeError("expected socket object, got None");
+ }
+ if ((keyfile == null) != (certfile == null)) {
+ throw PythonExceptions.CreateThrowable(
+ PythonSsl.SSLError(context),
+ "When key or certificate is provided both must be provided"
+ );
+ }
+
+ _serverSide = server_side;
+ bool validate;
+ _certsMode = certs_mode;
+
+ RemoteCertificateValidationCallback callback;
+ switch (certs_mode) {
+ case PythonSsl.CERT_NONE:
+ validate = false;
+ callback = CertValidationCallback;
+ break;
+ case PythonSsl.CERT_OPTIONAL:
+ validate = true;
+ callback = CertValidationCallbackOptional;
+ break;
+ case PythonSsl.CERT_REQUIRED:
+ validate = true;
+ callback = CertValidationCallbackRequired;
+ break;
+ default:
+ throw new InvalidOperationException(String.Format("bad certs_mode: {0}", certs_mode));
+ }
+
+ if (certfile != null) {
+ _cert = PythonSsl.ReadCertificate(context, certfile);
+ }
+
+ if (server_side) {
+ _sslStream = new SslStream(
+ new NetworkStream(sock._socket, false),
+ true,
+ callback
+ );
+ } else {
+ _sslStream = new SslStream(
+ new NetworkStream(sock._socket, false),
+ true,
+ callback,
+ CertSelectLocal
+ );
+ }
+
+ _socket = sock;
+ _certCollection = cacertsfile != null ?
+ new X509Certificate2Collection(new[] { PythonSsl.ReadCertificate(context, cacertsfile) }) :
+ new X509Certificate2Collection();
+ _protocol = protocol;
+ _validate = validate;
+ _context = context;
+ }
+
+ internal bool CertValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
+ return true;
+ }
+
+ internal bool CertValidationCallbackOptional(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
+ if (!_serverSide) {
+ if (certificate != null && sslPolicyErrors != SslPolicyErrors.None) {
+ ValidateCertificate(certificate, chain, sslPolicyErrors);
+ }
+ }
+
+ return true;
+ }
+
+ internal X509Certificate CertSelectLocal(object sender, string targetHost, X509CertificateCollection collection, X509Certificate remoteCertificate, string[] acceptableIssuers) {
+ if (collection.Count > 0) {
+ return collection[0];
+ }
+ return null;
+ }
+
+ internal bool CertValidationCallbackRequired(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
+ if (!_serverSide) {
+ // client check
+ if (certificate == null) {
+ ValidationError(SslPolicyErrors.None);
+ } else if (sslPolicyErrors != SslPolicyErrors.None) {
+ ValidateCertificate(certificate, chain, sslPolicyErrors);
+ }
+ }
+
+ return true;
+ }
+
+ private void ValidateCertificate(X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
+ chain = new X509Chain();
+ chain.ChainPolicy.ExtraStore.AddRange(_certCollection);
+ chain.Build((X509Certificate2)certificate);
+ if (chain.ChainStatus.Length > 0) {
+ foreach (var elem in chain.ChainStatus) {
+ if (elem.Status == X509ChainStatusFlags.UntrustedRoot) {
+ bool isOk = false;
+ foreach (var cert in _certCollection) {
+ if (certificate.Issuer == cert.Subject) {
+ isOk = true;
+ }
+ }
+
+ if (isOk) {
+ continue;
+ }
+ }
+
+ ValidationError(sslPolicyErrors);
+ break;
+ }
+ }
+ }
+
+ private void ValidationError(object reason) {
+ _validationFailure = PythonExceptions.CreateThrowable(PythonSsl.SSLError(_context), "errors while validating certificate chain: ", reason.ToString());
+ }
+
+ public void do_handshake() {
+ try {
+ // make sure the remote side hasn't shutdown before authenticating so we don't
+ // hang if we're in blocking mode.
+ int available = _socket._socket.Available;
+ } catch (SocketException) {
+ throw PythonExceptions.CreateThrowable(PythonExceptions.IOError, "socket closed before handshake");
+ }
+
+ try {
+ if (_serverSide) {
+ _sslStream.AuthenticateAsServer(_cert, _certsMode == PythonSsl.CERT_REQUIRED, GetProtocolTypeServer(_protocol), false);
+ } else {
+
+ var collection = new X509CertificateCollection();
+
+ if (_cert != null) {
+ collection.Add(_cert);
+ }
+ _sslStream.AuthenticateAsClient(_socket._hostName, collection, GetProtocolTypeClient(_protocol), false);
+ }
+ } catch (AuthenticationException e) {
+ _socket._socket.Close();
+ throw PythonExceptions.CreateThrowable(PythonSsl.SSLError(_context), "errors while performing handshake: ", e.ToString());
+ }
+
+ if (_validationFailure != null) {
+ throw _validationFailure;
+ }
+ }
+
+ public socket shutdown() {
+ _sslStream.Close();
+ return _socket;
+ }
+
+ /* supported communication based upon what the client & server specify
+ * as per the CPython docs:
+ * client / server SSLv2 SSLv3 SSLv23 TLSv1
+ SSLv2 yes no yes* no
+ SSLv3 yes yes yes no
+ SSLv23 yes no yes no
+ TLSv1 no no yes yes
+ */
+
+ private static SslProtocols GetProtocolTypeServer(int type) {
+ switch (type) {
+ case PythonSsl.PROTOCOL_SSLv2: return SslProtocols.Ssl2;
+ case PythonSsl.PROTOCOL_SSLv3: return SslProtocols.Ssl3;
+ case -1:
+ case PythonSsl.PROTOCOL_SSLv23: return SslProtocols.Ssl2 | SslProtocols.Ssl3 | SslProtocols.Tls;
+ case PythonSsl.PROTOCOL_TLSv1: return SslProtocols.Tls;
+ default:
+ throw new InvalidOperationException("bad ssl protocol type: " + type);
+ }
+ }
+
+ private static SslProtocols GetProtocolTypeClient(int type) {
+ switch (type) {
+ case PythonSsl.PROTOCOL_SSLv2: return SslProtocols.Ssl2;
+ case -1:
+ case PythonSsl.PROTOCOL_SSLv3: return SslProtocols.Ssl3;
+ case PythonSsl.PROTOCOL_SSLv23: return SslProtocols.Ssl3 | SslProtocols.Ssl2;
+ case PythonSsl.PROTOCOL_TLSv1: return SslProtocols.Tls;
+ default:
+ throw new InvalidOperationException("bad ssl protocol type: " + type);
+ }
+ }
+
+ public PythonTuple cipher() {
+ if (_sslStream.IsAuthenticated) {
+ return PythonTuple.MakeTuple(
+ _sslStream.CipherAlgorithm.ToString(),
+ ProtocolToPython(),
+ _sslStream.CipherStrength
+ );
+ }
+ return null;
+ }
+
+ private string ProtocolToPython() {
+ switch (_sslStream.SslProtocol) {
+ case SslProtocols.Ssl2: return "SSLv2";
+ case SslProtocols.Ssl3: return "TLSv1/SSLv3";
+ case SslProtocols.Tls: return "TLSv1";
+ default: return _sslStream.SslProtocol.ToString();
+ }
+ }
+
+ public object peer_certificate(bool binary_form) {
+ var peerCert = _sslStream.RemoteCertificate;
+
+ if (peerCert != null) {
+ if (binary_form) {
+ return peerCert.GetRawCertData().MakeString();
+ } else if (_validate) {
+ return PythonSsl.CertificateToPython(_context, peerCert, true);
+ }
+ }
+ return null;
+ }
+
+ public int pending() {
+ return _socket._socket.Available;
+ }
+
+ [Documentation("issuer() -> issuer_certificate\n\n"
+ + "Returns a string that describes the issuer of the server's certificate. Only useful for debugging purposes."
+ )]
+ public string issuer() {
+ if (_sslStream.IsAuthenticated) {
+ X509Certificate remoteCertificate = _sslStream.RemoteCertificate;
+ if (remoteCertificate != null) {
+ return remoteCertificate.Issuer;
+ } else {
+ return String.Empty;
+ }
+ }
+ return String.Empty;
+ }
+
+ [Documentation("read([n]) -> buffer_read\n\n"
+ + "If n is present, reads up to n bytes from the SSL connection. Otherwise, reads to EOF."
+ )]
+ public string read(CodeContext/*!*/ context, [DefaultParameterValue(Int32.MaxValue)] int n) {
+ try {
+ byte[] buffer = new byte[2048];
+ MemoryStream result = new MemoryStream(n);
+ while (true) {
+ int readLength = (n < buffer.Length) ? n : buffer.Length;
+ int bytes = _sslStream.Read(buffer, 0, readLength);
+ if (bytes > 0) {
+ result.Write(buffer, 0, bytes);
+ n -= bytes;
+ }
+ if (bytes == 0 || n == 0 || bytes < readLength) {
+ return result.ToArray().MakeString();
+ }
+ }
+
+ } catch (Exception e) {
+ throw PythonSocket.MakeException(context, e);
+ }
+ }
+
+ [Documentation("server() -> server_certificate\n\n"
+ + "Returns a string that describes the server's certificate. Only useful for debugging purposes."
+ )]
+ public string server() {
+ if (_sslStream.IsAuthenticated) {
+ X509Certificate remoteCertificate = _sslStream.RemoteCertificate;
+ if (remoteCertificate != null) {
+ return remoteCertificate.Subject;
+ }
+ }
+ return String.Empty;
+ }
+
+ [Documentation("write(s) -> bytes_sent\n\n"
+ + "Writes the string s through the SSL connection."
+ )]
+ public int write(CodeContext/*!*/ context, string data) {
+ byte[] buffer = data.MakeByteArray();
+ try {
+ _sslStream.Write(buffer);
+ return buffer.Length;
+ } catch (Exception e) {
+ throw PythonSocket.MakeException(context, e);
+ }
+ }
+ }
}
}
#endif
View
2 Merlin/Main/Languages/IronPython/IronPython/Compiler/Ast/AstMethods.cs
@@ -92,6 +92,8 @@ static class AstMethods {
public static readonly MethodInfo GetClosureTupleFromContext = GetMethod((Func<CodeContext, MutableTuple>)PythonOps.GetClosureTupleFromContext);
public static readonly MethodInfo IsUnicode = GetMethod((Func<object, bool>)PythonOps.IsUnicode);
public static readonly MethodInfo PushFrame = GetMethod((Func<CodeContext, FunctionCode, List<FunctionStack>>)PythonOps.PushFrame);
+ public static readonly MethodInfo FormatUnicode = GetMethod((Func<CodeContext, string, object, string>)PythonOps.FormatUnicode);
+ public static readonly MethodInfo FormatString = GetMethod((Func<CodeContext, string, object, string>)PythonOps.FormatString);
private static MethodInfo GetMethod(Delegate x) {
return x.Method;
View
27 Merlin/Main/Languages/IronPython/IronPython/Compiler/Ast/BinaryExpression.Generated.cs
@@ -23,12 +23,15 @@
#if CLR2
using Microsoft.Scripting.Math;
+using Complex = Microsoft.Scripting.Math.Complex64;
#else
using System.Numerics;
#endif
namespace IronPython.Compiler.Ast {
public partial class BinaryExpression {
+ const int MaximumInlineStringLength = 1024 * 1024;
+
internal override ConstantExpression ConstantFold() {
Expression left = _left.ConstantFold();
Expression right = _right.ConstantFold();
@@ -108,6 +111,16 @@ public partial class BinaryExpression {
case PythonOperator.NotEquals: return new ConstantExpression(ScriptingRuntimeHelpers.BooleanToObject(BigIntegerOps.Compare((BigInteger)constLeft.Value, (BigInteger)constRight.Value) != 0));
}
}
+ if (constLeft.Value.GetType() == typeof(Complex)) {
+ switch (_op) {
+ case PythonOperator.Add: return new ConstantExpression(ComplexOps.Add((Complex)constLeft.Value, (Complex)constRight.Value));
+ case PythonOperator.Subtract: return new ConstantExpression(ComplexOps.Subtract((Complex)constLeft.Value, (Complex)constRight.Value));
+ case PythonOperator.Power: return new ConstantExpression(ComplexOps.Power((Complex)constLeft.Value, (Complex)constRight.Value));
+ case PythonOperator.Multiply: return new ConstantExpression(ComplexOps.Multiply((Complex)constLeft.Value, (Complex)constRight.Value));
+ case PythonOperator.Divide: return new ConstantExpression(ComplexOps.Divide((Complex)constLeft.Value, (Complex)constRight.Value));
+ case PythonOperator.TrueDivide: return new ConstantExpression(ComplexOps.TrueDivide((Complex)constLeft.Value, (Complex)constRight.Value));
+ }
+ }
// *** END GENERATED CODE ***
@@ -117,10 +130,18 @@ public partial class BinaryExpression {
return new ConstantExpression((string)constLeft.Value + (string)constRight.Value);
}
} else if (_op == PythonOperator.Multiply && constLeft != null && constRight != null) {
+ // 10000 check is to avoid creating massive strings in IL - there's a limit to the number of
+ // bytes of strings we get to have so we don't want to use them all up.
if (constLeft.Value.GetType() == typeof(string) && constRight.Value.GetType() == typeof(int)) {
- return new ConstantExpression(StringOps.Multiply((string)constLeft.Value, (int)constRight.Value));
- } else if(constLeft.Value.GetType() == typeof(int) && constRight.Value.GetType() == typeof(string)) {
- return new ConstantExpression(StringOps.Multiply((string)constRight.Value, (int)constLeft.Value));
+ var res = StringOps.Multiply((string)constLeft.Value, (int)constRight.Value);
+ if (res.Length < MaximumInlineStringLength) {
+ return new ConstantExpression(res);
+ }
+ } else if (constLeft.Value.GetType() == typeof(int) && constRight.Value.GetType() == typeof(string)) {
+ var res = StringOps.Multiply((string)constRight.Value, (int)constLeft.Value);
+ if (res.Length < MaximumInlineStringLength) {
+ return new ConstantExpression(res);
+ }
}
}
} catch (ArithmeticException) {
View
22 Merlin/Main/Languages/IronPython/IronPython/Compiler/Ast/BinaryExpression.cs
@@ -145,12 +145,34 @@ out tmp
}
public override MSAst.Expression Reduce() {
+ ConstantExpression leftConst;
if (!CanEmitWarning(_op)) {
var folded = ConstantFold();
if (folded != null) {
folded.Parent = Parent;
return AstUtils.Convert(folded.Reduce(), typeof(object));
}
+ }
+
+ if (_op == PythonOperator.Mod &&
+ (leftConst = _left as ConstantExpression) != null &&
+ leftConst.Value is string) {
+ MethodInfo method;
+ if (leftConst.IsUnicodeString) {
+ // u'foo' % ...
+ // we want this to perform unicode string formatting.
+ method = AstMethods.FormatUnicode;
+ } else {
+ // inline string formatting
+ method = AstMethods.FormatString;
+ }
+
+ return Expression.Call(
+ method,
+ Parent.LocalContext,
+ _left,
+ _right
+ );
}
if (NeedComparisonTransformation()) {
View
32 Merlin/Main/Languages/IronPython/IronPython/Compiler/Ast/ConstantExpression.cs
@@ -40,11 +40,29 @@ public class ConstantExpression : Expression {
_value = value;
}
+ internal static ConstantExpression MakeUnicode(string value) {
+ return new ConstantExpression(new UnicodeWrapper(value));
+ }
+
public object Value {
- get { return _value; }
+ get {
+ UnicodeWrapper wrapper;
+ if ((wrapper = _value as UnicodeWrapper) != null) {
+ return wrapper.Value;
+ }
+
+ return _value;
+ }
+ }
+
+ internal bool IsUnicodeString {
+ get {
+ return _value is UnicodeWrapper;
+ }
}
public override MSAst.Expression Reduce() {
+ UnicodeWrapper wrapper;
if (_value == Ellipsis.Value) {
return Ast.Property(
null,
@@ -56,6 +74,8 @@ public class ConstantExpression : Expression {
} else {
return Ast.Field(null, typeof(ScriptingRuntimeHelpers).GetField("False"));
}
+ } else if ((wrapper = _value as UnicodeWrapper) != null) {
+ return GlobalParent.Constant(wrapper.Value);
}
return GlobalParent.Constant(_value);
@@ -67,7 +87,7 @@ public class ConstantExpression : Expression {
public override Type Type {
get {
- return GlobalParent.CompilationMode.GetConstantType(_value);
+ return GlobalParent.CompilationMode.GetConstantType(Value);
}
}
@@ -96,5 +116,13 @@ public class ConstantExpression : Expression {
return false;
}
}
+
+ class UnicodeWrapper {
+ public readonly object Value;
+
+ public UnicodeWrapper(string value) {
+ Value = value;
+ }
+ }
}
}
View
14 Merlin/Main/Languages/IronPython/IronPython/Compiler/Parser.cs
@@ -1958,7 +1958,11 @@ public class Parser : IDisposable { // TODO: remove IDisposable
}
}
- ret = new ConstantExpression(cv);
+ if (t is UnicodeStringToken) {
+ ret = ConstantExpression.MakeUnicode((string)cv);
+ } else {
+ ret = new ConstantExpression(cv);
+ }
ret.SetLoc(start, GetEnd());
return ret;
default:
@@ -2025,11 +2029,13 @@ public class Parser : IDisposable { // TODO: remove IDisposable
NextToken();
Arg[] args = FinishArgListOrGenExpr();
- if (args == null) {
- return new CallExpression(ret, new Arg[0]);
+ CallExpression call;
+ if (args != null) {
+ call = FinishCallExpr(ret, args);
+ } else {
+ call = new CallExpression(ret, new Arg[0]);
}
- CallExpression call = FinishCallExpr(ret, args);
call.SetLoc(ret.Start, GetEnd());
ret = call;
break;
View
6 Merlin/Main/Languages/IronPython/IronPython/Compiler/Token.cs
@@ -112,6 +112,12 @@ public ConstantValueToken(object value)
}
}
+ sealed class UnicodeStringToken : ConstantValueToken {
+ public UnicodeStringToken(object value)
+ : base(value) {
+ }
+ }
+
public class IncompleteStringToken : ConstantValueToken {
private readonly bool _quote;
private readonly bool _isRaw;
View
3 Merlin/Main/Languages/IronPython/IronPython/Compiler/Tokenizer.cs
@@ -722,6 +722,9 @@ internal Tokenizer(ErrorSink errorSink, PythonCompilerOptions options, bool verb
if (!isBytes) {
contents = LiteralParser.ParseString(contents, isRaw, isUnicode || UnicodeLiterals, complete);
if (complete) {
+ if (isUnicode) {
+ return new UnicodeStringToken(contents);
+ }
return new ConstantValueToken(contents);
} else {
_state.IncompleteString = new IncompleteStringToken(contents, quote == '\'', isRaw, isUnicode, isTriple);
View
6 Merlin/Main/Languages/IronPython/IronPython/Lib/iptest/assert_util.py
@@ -594,16 +594,18 @@ def retry_on_failure(f, *args, **kwargs):
1. Wraps execution of the input function, f
2. If f() fails, it retries invoking it MAX_FAILURE_RETRY times
'''
- def t(*args, **kwargs):
+ def t(*args, **kwargs):
for i in xrange(MAX_FAILURE_RETRY):
try:
ret_val = f(*args, **kwargs)
return ret_val
except Exception, e:
print "retry_on_failure(%s): failed on attempt '%d':" % (f.__name__, i+1)
print e
+ excp_info = sys.exc_info()
continue
- raise e
+ # raise w/ excep info to preverve the original stack trace
+ raise excp_info[0], excp_info[1], excp_info[2]
return t
View
8 Merlin/Main/Languages/IronPython/IronPython/Modules/Builtin.Generated.cs
@@ -128,20 +128,12 @@ public static partial class Builtin {
public static PythonType UnicodeError {
get { return PythonExceptions.UnicodeError; }
}
-
-#if !SILVERLIGHT
public static PythonType UnicodeDecodeError {
get { return PythonExceptions.UnicodeDecodeError; }
}
-#endif // !SILVERLIGHT
-
-
-#if !SILVERLIGHT
public static PythonType UnicodeEncodeError {
get { return PythonExceptions.UnicodeEncodeError; }
}
-#endif // !SILVERLIGHT
-
public static PythonType UnicodeTranslateError {
get { return PythonExceptions.UnicodeTranslateError; }
}
View
5 Merlin/Main/Languages/IronPython/IronPython/Modules/Builtin.cs
@@ -96,7 +96,10 @@ public static partial class Builtin {
[Documentation("__import__(name, globals, locals, fromlist, level) -> module\n\nImport a module.")]
public static object __import__(CodeContext/*!*/ context, string name, [DefaultParameterValue(null)]object globals, [DefaultParameterValue(null)]object locals, [DefaultParameterValue(null)]object fromlist, [DefaultParameterValue(-1)]int level) {
- //!!! remove suppress in GlobalSuppressions.cs when CodePlex 2704 is fixed.
+ if (fromlist is string || fromlist is Extensible<string>) {
+ fromlist = new List<object> { fromlist };
+ }
+
IList from = fromlist as IList;
PythonContext pc = PythonContext.GetContext(context);
View
10 Merlin/Main/Languages/IronPython/IronPython/Runtime/Binding/MetaPythonType.Members.cs
@@ -314,6 +314,7 @@ public MetaGetBinderHelper(MetaPythonType type, DynamicMetaObjectBinder member,
_cb.AddCondition(
Ast.Call(
typeof(PythonOps).GetMethod("OldClassTryLookupOneSlot"),
+ AstUtils.Constant(pt),
AstUtils.Constant(pt.OldClass),
AstUtils.Constant(_symName),
_tmp
@@ -548,20 +549,21 @@ public FastGetBinderHelper(PythonType type, CodeContext context, PythonGetMember
}
protected override void AddOldClassAccess(PythonType pt) {
- _gets.Add(new OldClassDelegate(pt, _binder.Name).Target);
+ _gets.Add(new OldClassDelegate(Value, pt, _binder.Name).Target);
}
class OldClassDelegate {
- private readonly WeakReference _type;
+ private readonly WeakReference _type, _declType;
private readonly string _name;
- public OldClassDelegate(PythonType oldClass, string name) {
+ public OldClassDelegate(PythonType declType, PythonType oldClass, string name) {
_type = oldClass.GetSharedWeakReference();
+ _declType = declType.GetSharedWeakReference();
_name = name;
}
public bool Target(CodeContext context, object self, out object result) {
- return PythonOps.OldClassTryLookupOneSlot(((PythonType)_type.Target).OldClass, _name, out result);
+ return PythonOps.OldClassTryLookupOneSlot((PythonType)_declType.Target, ((PythonType)_type.Target).OldClass, _name, out result);
}
}
View
16 Merlin/Main/Languages/IronPython/IronPython/Runtime/Exceptions/PythonExceptions.Generated.cs
@@ -605,8 +605,6 @@ public partial class _SyntaxError : BaseException {
}
}
-
-#if !SILVERLIGHT
[MultiRuntimeAware]
private static PythonType UnicodeDecodeErrorStorage;
public static PythonType UnicodeDecodeError {
@@ -678,10 +676,6 @@ public partial class _UnicodeDecodeError : BaseException {
}
-#endif // !SILVERLIGHT
-
-
-#if !SILVERLIGHT
[MultiRuntimeAware]
private static PythonType UnicodeEncodeErrorStorage;
public static PythonType UnicodeEncodeError {
@@ -753,8 +747,6 @@ public partial class _UnicodeEncodeError : BaseException {
}
-#endif // !SILVERLIGHT
-
[MultiRuntimeAware]
private static PythonType UnicodeTranslateErrorStorage;
public static PythonType UnicodeTranslateError {
@@ -952,14 +944,10 @@ public partial class _UnicodeTranslateError : BaseException {
private static BaseException/*!*/ ToPythonHelper(System.Exception clrException) {
if (clrException is BytesWarningException) return new BaseException(BytesWarning);
- #if !SILVERLIGHT
if (clrException is DecoderFallbackException) return new _UnicodeDecodeError();
- #endif
if (clrException is DeprecationWarningException) return new BaseException(DeprecationWarning);
if (clrException is DivideByZeroException) return new BaseException(ZeroDivisionError);
- #if !SILVERLIGHT
if (clrException is EncoderFallbackException) return new _UnicodeEncodeError();
- #endif
if (clrException is EndOfStreamException) return new BaseException(EOFError);
if (clrException is FutureWarningException) return new BaseException(FutureWarning);
if (clrException is ImportWarningException) return new BaseException(ImportWarning);
@@ -1006,14 +994,10 @@ public partial class _UnicodeTranslateError : BaseException {
}
private static System.Exception/*!*/ ToClrHelper(PythonType/*!*/ type, string message) {
if (type == BytesWarning) return new BytesWarningException(message);
- #if !SILVERLIGHT
if (type == UnicodeDecodeError) return new DecoderFallbackException(message);
- #endif
if (type == DeprecationWarning) return new DeprecationWarningException(message);
if (type == ZeroDivisionError) return new DivideByZeroException(message);
- #if !SILVERLIGHT
if (type == UnicodeEncodeError) return new EncoderFallbackException(message);
- #endif
if (type == EOFError) return new EndOfStreamException(message);
if (type == FutureWarning) return new FutureWarningException(message);
if (type == ImportWarning) return new ImportWarningException(message);
View
2 Merlin/Main/Languages/IronPython/IronPython/Runtime/Exceptions/PythonExceptions.cs
@@ -833,7 +833,6 @@ public partial class _WindowsError : _EnvironmentError {
internal const int ERROR_INVALID_NAME = 123;
}
-#if !SILVERLIGHT
public partial class _UnicodeDecodeError : BaseException {
[PythonHidden]
@@ -864,7 +863,6 @@ public partial class _UnicodeEncodeError : BaseException {
}
}
}
-#endif
public partial class _SystemExit : BaseException {
public override void __init__(params object[] args) {
View
23 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/ComplexOps.cs
@@ -111,6 +111,22 @@ public static partial class ComplexOps {
}
#region Binary operators
+
+ [SpecialName]
+ public static Complex Add(Complex x, Complex y) {
+ return x + y;
+ }
+
+ [SpecialName]
+ public static Complex Subtract(Complex x, Complex y) {
+ return x - y;
+ }
+
+ [SpecialName]
+ public static Complex Multiply(Complex x, Complex y) {
+ return x * y;
+ }
+
[SpecialName]
public static Complex Divide(Complex x, Complex y) {
if (y.IsZero()) {
@@ -161,6 +177,11 @@ public static partial class ComplexOps {
return x.Pow(y);
}
+ [PythonHidden]
+ public static Complex Power(Complex x, Complex y) {
+ return op_Power(x, y);
+ }
+
// floordiv for complex numbers is deprecated in the Python 2.
// specification; this function implements the observable
// functionality in CPython 2.4:
@@ -234,7 +255,7 @@ public static partial class ComplexOps {
Complex right;
if (Converter.TryConvertToComplex(y, out right)) {
#if !CLR2
- if (y is BigInteger && double.IsInfinity(right.Real)) {
+ if (double.IsInfinity(right.Real) && (y is BigInteger || y is Extensible<BigInteger>)) {
throw new OverflowException("long int too large to convert to float");
}
#endif
View
53 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/LongOps.cs
@@ -907,10 +907,7 @@ [PythonHidden] public
[PythonHidden]
public static int GetByteCount(BigInteger self) {
- int index;
- byte[] bytes;
- GetHighestByte(self, out index, out bytes);
- return index + 1;
+ return self.GetByteCount();
}
#region 'Create' Methods
@@ -956,59 +953,17 @@ [PythonHidden] public
[CLSCompliant(false), PythonHidden]
public static uint[] GetWords(BigInteger self) {
- if (self.IsZero) {
- return new uint[] { 0 };
- }
-
- int hi;
- byte[] bytes;
- GetHighestByte(self, out hi, out bytes);
-
- uint[] result = new uint[(hi + 1 + 3) / 4];
- int i = 0;
- int j = 0;
- uint u = 0;
- int shift = 0;
- while (i < bytes.Length) {
- u |= (uint)bytes[i++] << shift;
- if (i % 4 == 0) {
- result[j++] = u;
- u = 0;
- }
- shift += 8;
- }
- if (u != 0) {
- result[j] = u;
- }
- return result;
+ return self.GetWords();
}
[CLSCompliant(false), PythonHidden]
public static uint GetWord(BigInteger self, int index) {
- return GetWords(self)[index];
+ return self.GetWord(index);
}
[PythonHidden]
public static int GetWordCount(BigInteger self) {
- return GetWords(self).Length;
- }
-
- private static byte GetHighestByte(BigInteger self, out int index, out byte[] byteArray) {
- byte[] bytes = BigInteger.Abs(self).ToByteArray();
- if (self.IsZero) {
- byteArray = bytes;
- index = 0;
- return 1;
- }
-
- int hi = bytes.Length;
- byte b;
- do {
- b = bytes[--hi];
- } while (b == 0);
- index = hi;
- byteArray = bytes;
- return b;
+ return self.GetWordCount();
}
#endregion
View
21 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/PythonOps.cs
@@ -239,9 +239,18 @@ public static partial class PythonOps {
ret = es.Value;
}
+
return ret;
}
+ public static string FormatString(CodeContext context, string str, object data) {
+ return new StringFormatter(context, str, data).Format();
+ }
+
+ public static string FormatUnicode(CodeContext context, string str, object data) {
+ return new StringFormatter(context, str, data, true).Format();
+ }
+
public static object Plus(object o) {
object ret;
@@ -3254,8 +3263,8 @@ public static partial class PythonOps {
return null;
}
- public static bool OldClassTryLookupOneSlot(OldClass self, string name, out object value) {
- return self.TryLookupOneSlot(name, out value);
+ public static bool OldClassTryLookupOneSlot(PythonType type, OldClass self, string name, out object value) {
+ return self.TryLookupOneSlot(type, name, out value);
}
public static bool OldInstanceTryGetBoundCustomMember(CodeContext context, OldInstance self, string name, out object value) {
@@ -3846,19 +3855,11 @@ public static partial class PythonOps {
}
public static Exception UnicodeDecodeError(string format, params object[] args) {
-#if SILVERLIGHT // EncoderFallbackException and DecoderFallbackException
- throw new NotImplementedException();
-#else
return new System.Text.DecoderFallbackException(string.Format(format, args));
-#endif
}
public static Exception UnicodeEncodeError(string format, params object[] args) {
-#if SILVERLIGHT // EncoderFallbackException and DecoderFallbackException
- throw new NotImplementedException();
-#else
return new System.Text.EncoderFallbackException(string.Format(format, args));
-#endif
}
public static Exception IOError(Exception inner) {
View
2 Merlin/Main/Languages/IronPython/IronPython/Runtime/Operations/StringOps.cs
@@ -214,7 +214,7 @@ public static class StringOps {
}
- internal static object FastNewUnicode(CodeContext context, object value, object encoding, object errors) {
+ internal static string FastNewUnicode(CodeContext context, object value, object encoding, object errors) {
string strErrors = errors as string;
if (strErrors == null) {
throw PythonOps.TypeError("unicode() argument 3 must be string, not {0}", PythonTypeOps.GetName(errors));
View
2 Merlin/Main/Languages/IronPython/IronPython/Runtime/PythonContext.cs
@@ -1161,7 +1161,7 @@ private sealed class OptimizedBuiltinHasher {
return CompilePythonCode(sourceCode, compilerOptions, ThrowingErrorSink.Default);
}
- internal object GetBuiltinModule(string name) {
+ internal PythonModule GetBuiltinModule(string name) {
lock (this) {
PythonModule mod = CreateBuiltinModule(name);
if (mod != null) {
View
22 Merlin/Main/Languages/IronPython/IronPython/Runtime/StringFormatter.cs
@@ -37,6 +37,7 @@ internal class StringFormatter {
const int UnspecifiedPrecision = -1; // Use the default precision
private readonly CodeContext/*!*/ _context;
+ private readonly bool _isUnicodeString; // true if the LHS is Unicode and we should call __unicode__ for formatting objects on the RHS
private object _data;
private int _dataIndex;
@@ -71,11 +72,18 @@ internal class StringFormatter {
}
#region Constructors
- public StringFormatter(CodeContext/*!*/ context, string str, object data) {
+
+ public StringFormatter(CodeContext/*!*/ context, string str, object data)
+ : this(context, str, data, false) {
+ }
+
+ public StringFormatter(CodeContext/*!*/ context, string str, object data, bool isUnicode) {
_str = str;
_data = data;
_context = context;
+ _isUnicodeString = isUnicode;
}
+
#endregion
#region Public API Surface
@@ -869,7 +877,17 @@ internal class StringFormatter {
}
private void AppendString() {
- string s = PythonOps.ToString(_opts.Value);
+ string s;
+ if (!_isUnicodeString) {
+ s = PythonOps.ToString(_context, _opts.Value);
+ } else {
+ object o = StringOps.FastNewUnicode(_context, _opts.Value);
+ s = o as string;
+ if (s == null) {
+ s = ((Extensible<string>)o).Value;
+ }
+ }
+
if (s == null) s = "None";
AppendString(s);
}
View
2 Merlin/Main/Languages/IronPython/IronPython/Runtime/Super.cs
@@ -160,7 +160,7 @@ public class Super : PythonTypeSlot, ICodeFormattable {
OldClass dt = pt.OldClass;
if (PythonOps.TryGetBoundAttr(context, dt, name, out value)) {
- value = dt.GetOldStyleDescriptor(context, value, self, DescriptorContext);
+ value = OldClass.GetOldStyleDescriptor(context, value, self, DescriptorContext);
return true;
}
}
View
5 Merlin/Main/Languages/IronPython/IronPython/Runtime/Types/BuiltinFunction.cs
@@ -604,11 +604,12 @@ internal class BindingResult {
if (target.Overload != null && target.Overload.IsProtected) {
Type declaringType = target.Overload.DeclaringType;
string methodName = target.Overload.Name;
-
+
+ string name = target.Overload.Name;
// report an error when calling a protected member
res = delegate(object[] callArgs, out bool shouldOptimize) {
shouldOptimize = false;
- throw PythonOps.TypeErrorForProtectedMember(declaringType, target.Overload.Name);
+ throw PythonOps.TypeErrorForProtectedMember(declaringType, name);
};
} else if (result.MetaObject.Expression.NodeType == ExpressionType.Throw) {
if (IsBinaryOperator && args.Length == 2) {
View
20 Merlin/Main/Languages/IronPython/IronPython/Runtime/Types/OldClass.cs
@@ -67,7 +67,7 @@ public sealed class OldClass :
[NonSerialized]
private List<OldClass> _bases;
- private PythonType _type = null;
+ private PythonType _type;
internal PythonDictionary _dict;
private int _attrs; // actually OldClassAttributes - losing type safety for thread safety
@@ -229,8 +229,12 @@ public sealed class OldClass :
return false;
}
- internal bool TryLookupOneSlot(string name, out object ret) {
- return _dict._storage.TryGetValue(name, out ret);
+ internal bool TryLookupOneSlot(PythonType lookingType, string name, out object ret) {
+ if (_dict._storage.TryGetValue(name, out ret)) {
+ ret = GetOldStyleDescriptor(TypeObject.Context.SharedContext, ret, null, lookingType);
+ return true;
+ }
+ return false;
}
internal string FullName {
@@ -254,6 +258,16 @@ public sealed class OldClass :
return PythonOps.GetUserDescriptor(self, instance, type);
}
+ internal static object GetOldStyleDescriptor(CodeContext context, object self, object instance, PythonType type) {
+ PythonTypeSlot dts = self as PythonTypeSlot;
+ object callable;
+ if (dts != null && dts.TryGetValue(context, instance, type, out callable)) {
+ return callable;
+ }
+
+ return PythonOps.GetUserDescriptor(self, instance, type);
+ }
+
internal bool HasFinalizer {
get {
return (_attrs & (int)OldClassAttributes.HasFinalizer) != 0;
View
7 Merlin/Main/Languages/IronPython/IronPython/Runtime/Types/TypeCache.Generated.cs
@@ -272,5 +272,12 @@ public static class TypeCache {
// *** END GENERATED CODE ***
#endregion
+
+ [Obsolete("use Complex instead")]
+ public static PythonType Complex64 {
+ get {
+ return Complex;