Skip to content

Commit

Permalink
Adds pure Python script for FastCGI <-> WSGI gateway, in particular t…
Browse files Browse the repository at this point in the history
…o support Django.

Adds a getting started guide on how to setup the FastCGI script. This isn't fully complete, mainly because we need to figure out exactly how this should be setup. But it covers the basics of getting going. This is based upon the IIS/PHP setup instructions available here: http://learn.iis.net/page.aspx/246/using-fastcgi-to-host-php-applications-on-iis/
  • Loading branch information
Dino Viehland committed May 8, 2012
1 parent b380c8a commit 0b944a2
Show file tree
Hide file tree
Showing 24 changed files with 847 additions and 62 deletions.
41 changes: 41 additions & 0 deletions Release/Product/Python/Analysis/AnalysisValue.cs
Expand Up @@ -14,6 +14,7 @@

using System;
using System.Collections.Generic;
using Microsoft.PythonTools.Parsing;

namespace Microsoft.PythonTools.Analysis {
/// <summary>
Expand All @@ -25,6 +26,18 @@ public class AnalysisValue {
internal AnalysisValue() {
}

/// <summary>
/// Gets the name of the value if it has one, or null if it's a non-named item.
///
/// The name property here is typically the same value you'd get by accessing __name__
/// on the real Python object.
/// </summary>
public virtual string Name {
get {
return null;
}
}

/// <summary>
/// Gets a list of locations where this value is defined.
/// </summary>
Expand All @@ -42,5 +55,33 @@ public class AnalysisValue {
public virtual object GetConstantValue() {
return Type.Missing;
}

/// <summary>
/// Returns the constant value as a string. This returns a string if the constant
/// value is either a unicode or ASCII string.
/// </summary>
public string GetConstantValueAsString() {
var constName = GetConstantValue();
if (constName != null) {
string unicodeName = constName as string;
AsciiString asciiName;
if (unicodeName != null) {
return unicodeName;
} else if ((asciiName = constName as AsciiString) != null) {
return asciiName.String;
}
}
return null;
}

/// <summary>
/// Returns a list of key/value pairs stored in the this object which are retrivable using
/// indexing. For lists the key values will be integers (potentially constant, potentially not),
/// for dicts the key values will be arbitrary analysis values.
/// </summary>
/// <returns></returns>
public virtual IEnumerable<KeyValuePair<IEnumerable<AnalysisValue>, IEnumerable<AnalysisValue>>> GetItems() {
yield break;
}
}
}
60 changes: 60 additions & 0 deletions Release/Product/Python/Analysis/PythonAnalyzer.cs
Expand Up @@ -116,11 +116,34 @@ public PythonAnalyzer(IPythonInterpreterFactory interpreterFactory)
SpecializeFunction("__builtin__", "range", (n, unit, args) => unit.DeclaringModule.GetOrMakeNodeVariable(n, (nn) => new RangeInfo(_types.List, unit.ProjectState).SelfSet));
SpecializeFunction("__builtin__", "min", ReturnUnionOfInputs);
SpecializeFunction("__builtin__", "max", ReturnUnionOfInputs);
SpecializeFunction("__builtin__", "getattr", SpecialGetAttr);

// cached for quick checks to see if we're a call to clr.AddReference

SpecializeFunction("wpf", "LoadComponent", LoadComponent);
}

private ISet<Namespace> SpecialGetAttr(CallExpression call, AnalysisUnit unit, ISet<Namespace>[] args) {
ISet<Namespace> res = EmptySet<Namespace>.Instance;
bool madeSet = false;
if (args.Length >= 2) {
if (args.Length >= 3) {
// getattr(foo, 'bar', baz), baz is a possible return value.
res = args[2];
}

foreach (var value in args[0]) {
foreach (var name in args[1]) {
// getattr(foo, 'bar') - attempt to do the getattr and return the proper value
var strValue = name.GetConstantValueAsString();
if (strValue != null) {
res = res.Union(value.GetMember(call, unit, strValue), ref madeSet);
}
}
}
}
return res;
}

/// <summary>
/// Reloads the modules from the interpreter.
Expand Down Expand Up @@ -378,6 +401,43 @@ class LazyModuleEnumerator {
return new MemberResult[0];
}

/// <summary>
/// Specializes the provided function in the given module name to return an instance of the given type.
///
/// The type is a fully qualified module name (e.g. thread.LockType).
/// </summary>
/// <param name="moduleName"></param>
/// <param name="name"></param>
/// <param name="returnType"></param>
public void SpecializeFunction(string moduleName, string name, string returnType) {
int lastDot;
if ((lastDot = returnType.LastIndexOf('.')) == -1) {
throw new ArgumentException(String.Format("Expected module.typename for return type, got '{0}'", returnType));
}

string retModule = returnType.Substring(0, lastDot);
string typeName = returnType.Substring(lastDot + 1);

SpecializeFunction(moduleName, name, (call, unit, types) => {
ModuleReference modRef;
if (Modules.TryGetValue(retModule, out modRef)) {
if (modRef.Module != null) {
ISet<Namespace> res = EmptySet<Namespace>.Instance;
bool madeSet = false;
foreach (var value in modRef.Module.GetMember(call, unit, typeName)) {
if (value is ClassInfo) {
res = res.Union(((ClassInfo)value).Instance.SelfSet, ref madeSet);
} else {
res = res.Union(value.SelfSet, ref madeSet);
}
}
return res;
}
}
return null;
});
}

public void SpecializeFunction(string moduleName, string name, Action<CallExpression, CallInfo> dlg) {
SpecializeFunction(moduleName, name, (call, unit, types) => { dlg(call, new CallInfo(types)); return null; });
}
Expand Down
6 changes: 6 additions & 0 deletions Release/Product/Python/Analysis/Values/BuiltinClassInfo.cs
Expand Up @@ -57,6 +57,12 @@ public BuiltinClassInfo(IPythonType classObj, PythonAnalyzer projectState)
return Instance.SelfSet;
}

public override string Name {
get {
return _type.Name;
}
}

public IEnumerable<ISet<Namespace>> GetMro() {
return new[] { SelfSet };
}
Expand Down
6 changes: 6 additions & 0 deletions Release/Product/Python/Analysis/Values/BuiltinFunctionInfo.cs
Expand Up @@ -56,6 +56,12 @@ public BuiltinFunctionInfo(IPythonFunction function, PythonAnalyzer projectState
}
}

public override string Name {
get {
return _function.Name;
}
}

public override string Description {
get {
if (_function.IsBuiltin) {
Expand Down
Expand Up @@ -117,7 +117,7 @@ public BuiltinMethodInfo(IPythonFunction function, PythonMemberType memType, Pyt
}
}

public string Name { get { return _function.Name; } }
public override string Name { get { return _function.Name; } }

public override ILocatedMember GetLocatedMember() {
return _function as ILocatedMember;
Expand Down
2 changes: 1 addition & 1 deletion Release/Product/Python/Analysis/Values/BuiltinModule.cs
Expand Up @@ -76,7 +76,7 @@ public BuiltinModule(IPythonModule module, PythonAnalyzer projectState)
}
}

public string Name {
public override string Name {
get {
return _interpreterModule.Name;
}
Expand Down
6 changes: 6 additions & 0 deletions Release/Product/Python/Analysis/Values/ClassInfo.cs
Expand Up @@ -83,6 +83,12 @@ internal ClassInfo(AnalysisUnit unit, ClassDefinition klass)
}
}

public override string Name {
get {
return ClassDefinition.Name;
}
}

public VariableDef<ClassInfo> SubClasses {
get {
if (_subclasses == null) {
Expand Down
8 changes: 4 additions & 4 deletions Release/Product/Python/Analysis/Values/ConstantInfo.cs
Expand Up @@ -87,7 +87,7 @@ public ConstantInfo(IPythonConstant value, PythonAnalyzer projectState)
return SelfSet;
}

internal static ISet<Namespace> NumericOp(Node node, Namespace lhs, AnalysisUnit unit, PythonOperator operation, ISet<Namespace> rhs) {
internal static ISet<Namespace> NumericOp(Node node, BuiltinInstanceInfo lhs, AnalysisUnit unit, PythonOperator operation, ISet<Namespace> rhs) {
BuiltinTypeId curType = lhs.TypeId;
switch (operation) {
case PythonOperator.TrueDivide:
Expand All @@ -112,15 +112,15 @@ public ConstantInfo(IPythonConstant value, PythonAnalyzer projectState)
break;
case PythonOperator.Mod:
if (lhs.TypeId == BuiltinTypeId.Str || lhs.TypeId == BuiltinTypeId.Bytes) {
return lhs.SelfSet;
return lhs.ClassInfo.Instance;
}
goto case PythonOperator.Add;
case PythonOperator.Multiply:
if (curType == BuiltinTypeId.Str || curType == BuiltinTypeId.Bytes) {
foreach (var type in rhs) {
var rhsType = type.TypeId;
if (rhsType == BuiltinTypeId.Int || rhsType == BuiltinTypeId.Long) {
return lhs.SelfSet;
return lhs.ClassInfo.Instance;
}
}
} else if (curType == BuiltinTypeId.Int || curType == BuiltinTypeId.Long) {
Expand Down Expand Up @@ -243,7 +243,7 @@ public ConstantInfo(IPythonConstant value, PythonAnalyzer projectState)
}

public override string ToString() {
return "<ConstantInfo object '" + Description + "'>"; // " at " + hex(id(self))
return "<ConstantInfo object '" + Description + "'" + (_value == null ? "" : (" '" + _value.ToString() + "' ")) + ">"; // " at " + hex(id(self))
}

public override object GetConstantValue() {
Expand Down
27 changes: 25 additions & 2 deletions Release/Product/Python/Analysis/Values/DictionaryInfo.cs
Expand Up @@ -29,7 +29,7 @@ internal class DictionaryInfo : BuiltinInstanceInfo {
private VariableDef _keyValueTupleVariable;
private readonly ProjectEntry _declaringModule;
private readonly int _declVersion;
private SpecializedDictionaryMethod _getMethod, _itemsMethod, _keysMethod, _valuesMethod, _iterKeysMethod, _iterValuesMethod, _popMethod, _popItemMethod, _iterItemsMethod;
private SpecializedDictionaryMethod _getMethod, _itemsMethod, _keysMethod, _valuesMethod, _iterKeysMethod, _iterValuesMethod, _popMethod, _popItemMethod, _iterItemsMethod, _updateMethod;

public DictionaryInfo(ProjectEntry declaringModule)
: base(declaringModule.ProjectState._dictType) {
Expand All @@ -38,7 +38,6 @@ public DictionaryInfo(ProjectEntry declaringModule)
_declaringModule = declaringModule;
_declVersion = declaringModule.AnalysisVersion;
}


public override ISet<Namespace> GetIndex(Node node, AnalysisUnit unit, ISet<Namespace> index) {
return _valueTypes.Types;
Expand Down Expand Up @@ -123,6 +122,9 @@ public DictionaryInfo(ProjectEntry declaringModule)
res = GetOrMakeSpecializedMethod(ref _iterItemsMethod, "iteritems", method => new DictionaryItemsIterableBoundMethod(method, this));
}
break;
case "update":
res = GetOrMakeSpecializedMethod(ref _updateMethod, "update", method => new DictionaryUpdateBoundMethod(method, this));
break;
}

return res ?? base.GetMember(node, unit, name);
Expand Down Expand Up @@ -402,6 +404,27 @@ internal DictionaryKeyValueTupleBoundMethod(BuiltinMethodInfo method, Dictionary
}
}

class DictionaryUpdateBoundMethod : SpecializedDictionaryMethod {
internal DictionaryUpdateBoundMethod(BuiltinMethodInfo method, DictionaryInfo myDict)
: base(method, myDict) {
}

public override ISet<Namespace> Call(Node node, AnalysisUnit unit, ISet<Namespace>[] args, NameExpression[] keywordArgNames) {
if (args.Length >= 1) {
foreach (var type in args[0]) {
DictionaryInfo otherDict = type as DictionaryInfo;
if (otherDict != null) {
_myDict._valueTypes.AddTypes(node, unit, otherDict._valueTypes.Types);
_myDict._keyTypes.AddTypes(node, unit, otherDict._keyTypes.Types);
}
}
}
// TODO: Process keyword args and add those values to our dictionary, plus a string key

return EmptySet<Namespace>.Instance;
}
}

#endregion

public override string ToString() {
Expand Down
48 changes: 28 additions & 20 deletions Release/Product/Python/Analysis/Values/FunctionInfo.cs
Expand Up @@ -187,6 +187,12 @@ internal FunctionInfo(AnalysisUnit unit)
return false;
}

public override string Name {
get {
return FunctionDefinition.Name;
}
}

public override string Description {
get {
StringBuilder result;
Expand Down Expand Up @@ -219,29 +225,31 @@ internal FunctionInfo(AnalysisUnit unit)
get {
StringBuilder result = new StringBuilder();
bool first = true;
foreach (var ns in ReturnValue.Types) {
if (ns == null) {
continue;
}
if (ReturnValue.Types.Count <= 10) {
foreach (var ns in ReturnValue.Types) {
if (ns == null) {
continue;
}

if (ns.Push()) {
try {
if (ns.Description == null) {
continue;
}
if (ns.Push()) {
try {
if (ns.ShortDescription == null) {
continue;
}

if (first) {
result.Append(" -> ");
first = false;
} else {
result.Append(", ");
}
AppendDescription(result, ns);
} finally {
if (first) {
result.Append(" -> ");
first = false;
} else {
result.Append(", ");
}
AppendDescription(result, ns);
} finally {
ns.Pop();
}
} else {
result.Append("...");
} else {
result.Append("...");
}
}
}

Expand All @@ -255,7 +263,7 @@ internal FunctionInfo(AnalysisUnit unit)
} else {
DescriptionStack.Add(key);
try {
result.Append(key.Description);
result.Append(key.ShortDescription);
} finally {
DescriptionStack.Pop();
}
Expand Down
2 changes: 1 addition & 1 deletion Release/Product/Python/Analysis/Values/ModuleInfo.cs
Expand Up @@ -194,7 +194,7 @@ internal class ModuleInfo : Namespace, IReferenceableContainer, IModule {
}
}

public string Name {
public override string Name {
get { return _name; }
}

Expand Down
21 changes: 20 additions & 1 deletion Release/Product/Python/Analysis/Values/NamespaceSetExtensions.cs
Expand Up @@ -239,7 +239,26 @@ internal static class NamespaceSetExtensions {
Namespace type = null;
if (types.Count == 1) {
type = System.Linq.Enumerable.First(types);
} else if (types.Count > 0) {
} else if(types.Count == 2) {
var enumer = types.GetEnumerator();
Namespace first = null, second = null;
if (enumer.MoveNext()) {
first = enumer.Current;
}
if (enumer.MoveNext()) {
second = enumer.Current;
}

if (first != null && second != null) {
if (first.GetConstantValue() == null) {
return second;
} else if (second.GetConstantValue() == null) {
return first;
}
}
}

if (types.Count > 0) {
// simplify the types.
var set = new HashSet<Namespace>(types, TypeUnion.UnionComparer);
if (set.Count == 1) {
Expand Down

0 comments on commit 0b944a2

Please sign in to comment.