Compare commits
1 Commits
b4_big_upd
...
OLD_DATE_A
Author | SHA1 | Date | |
---|---|---|---|
|
ce3bd20052 |
146
include/wx/date.h
Normal file
146
include/wx/date.h
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: date.h
|
||||||
|
// Purpose: wxDate class
|
||||||
|
// Author: Julian Smart, Steve Marcus, Eric Simon, Chris Hill,
|
||||||
|
// Charles D. Price
|
||||||
|
// Modified by:
|
||||||
|
// Created: 01/02/97
|
||||||
|
// RCS-ID: $Id$
|
||||||
|
// Copyright: (c)
|
||||||
|
// Licence: wxWindows licence
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _WX_DATE_H_
|
||||||
|
#define _WX_DATE_H_
|
||||||
|
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#pragma interface "date.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "wx/object.h"
|
||||||
|
#include "wx/string.h"
|
||||||
|
|
||||||
|
#if wxUSE_TIMEDATE
|
||||||
|
// These lines necessary to stop VC++ 6 being confused about namespaces
|
||||||
|
class WXDLLEXPORT wxDate;
|
||||||
|
bool WXDLLEXPORT operator<(const wxDate &dt1, const wxDate &dt2);
|
||||||
|
bool WXDLLEXPORT operator<(const wxDate &dt1, const wxDate &dt2);
|
||||||
|
bool WXDLLEXPORT operator <= (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
bool WXDLLEXPORT operator > (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
bool WXDLLEXPORT operator >= (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
bool WXDLLEXPORT operator == (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
bool WXDLLEXPORT operator != (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
|
||||||
|
enum wxdate_format_type {wxMDY, wxDAY, wxMONTH, wxFULL, wxEUROPEAN};
|
||||||
|
|
||||||
|
#define wxNO_CENTURY 0x02
|
||||||
|
#define wxDATE_ABBR 0x04
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxDate : public wxObject
|
||||||
|
{
|
||||||
|
DECLARE_DYNAMIC_CLASS(wxDate)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
unsigned long julian; // see julDate(); days since 1/1/4713 B.C.
|
||||||
|
int month; // see NMonth()
|
||||||
|
int day; // see Day()
|
||||||
|
int year; // see NYear4()
|
||||||
|
int day_of_week; // see NDOW(); 1 = Sunday, ... 7 = Saturday
|
||||||
|
|
||||||
|
private:
|
||||||
|
int DisplayFormat;
|
||||||
|
unsigned char DisplayOptions;
|
||||||
|
|
||||||
|
void julian_to_mdy (); // convert julian day to mdy
|
||||||
|
void julian_to_wday (); // convert julian day to day_of_week
|
||||||
|
void mdy_to_julian (); // convert mdy to julian day
|
||||||
|
|
||||||
|
public:
|
||||||
|
wxDate ();
|
||||||
|
wxDate (long j);
|
||||||
|
wxDate (int m, int d, int y);
|
||||||
|
wxDate (const wxString& dat);
|
||||||
|
wxDate (const wxDate &dt);
|
||||||
|
|
||||||
|
#ifndef __SALFORDC__
|
||||||
|
operator wxString (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void operator = (const wxDate& date);
|
||||||
|
void operator = (const wxString& date);
|
||||||
|
|
||||||
|
wxDate operator + (long i);
|
||||||
|
wxDate operator + (int i);
|
||||||
|
|
||||||
|
wxDate operator - (long i);
|
||||||
|
wxDate operator - (int i);
|
||||||
|
|
||||||
|
long operator - (const wxDate &dt);
|
||||||
|
|
||||||
|
wxDate &operator += (long i);
|
||||||
|
wxDate &operator -= (long i);
|
||||||
|
|
||||||
|
wxDate &operator ++ (); // Prefix increment
|
||||||
|
wxDate &operator ++ (int); // Postfix increment
|
||||||
|
wxDate &operator -- (); // Prefix decrement
|
||||||
|
wxDate &operator -- (int); // Postfix decrement
|
||||||
|
|
||||||
|
friend bool WXDLLEXPORT operator < (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
friend bool WXDLLEXPORT operator <= (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
friend bool WXDLLEXPORT operator > (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
friend bool WXDLLEXPORT operator >= (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
friend bool WXDLLEXPORT operator == (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
friend bool WXDLLEXPORT operator != (const wxDate &dt1, const wxDate &dt2);
|
||||||
|
|
||||||
|
#if wxUSE_STD_IOSTREAM
|
||||||
|
friend ostream WXDLLEXPORT & operator << (ostream &os, const wxDate &dt);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wxString FormatDate (int type=-1) const;
|
||||||
|
void SetFormat (int format);
|
||||||
|
int SetOption (int option, bool enable=TRUE);
|
||||||
|
|
||||||
|
long GetJulianDate() const; // returns julian date
|
||||||
|
int GetDayOfYear() const; // returns relative date since Jan. 1
|
||||||
|
bool IsLeapYear() const; // returns TRUE if leap year, FALSE if not
|
||||||
|
|
||||||
|
// Version 4.0 Extension to Public Interface - CDP
|
||||||
|
|
||||||
|
// These 'Set's modify the date object and actually SET it
|
||||||
|
// They all return a reference to self (*this)
|
||||||
|
|
||||||
|
wxDate &Set(); // Sets to current system date
|
||||||
|
wxDate &Set(long lJulian);
|
||||||
|
wxDate &Set(int nMonth, int nDay, int nYear);
|
||||||
|
|
||||||
|
wxDate &AddWeeks(int nCount = 1); //
|
||||||
|
wxDate &AddMonths(int nCount = 1); // May also pass neg# to decrement
|
||||||
|
wxDate &AddYears(int nCount = 1); //
|
||||||
|
|
||||||
|
int GetDay() const; // Numeric Day of date object
|
||||||
|
int GetDaysInMonth(); // Number of days in month (1..31)
|
||||||
|
int GetFirstDayOfMonth() const; // First Day Of Month (1..7)
|
||||||
|
|
||||||
|
wxString GetDayOfWeekName(); // Character Day Of Week ('Sunday'..'Saturday')
|
||||||
|
int GetDayOfWeek() const; // (1..7)
|
||||||
|
|
||||||
|
int GetWeekOfMonth(); // Numeric Week Of Month (1..6)
|
||||||
|
int GetWeekOfYear(); // Numeric Week Of Year (1..52)
|
||||||
|
|
||||||
|
wxString GetMonthName(); // Character Month name
|
||||||
|
int GetMonth() const; // Month Number (1..12)
|
||||||
|
wxDate GetMonthStart(); // First Date Of Month
|
||||||
|
wxDate GetMonthEnd(); // Last Date Of Month
|
||||||
|
|
||||||
|
int GetYear() const; // eg. 1992
|
||||||
|
wxDate GetYearStart(); // First Date Of Year
|
||||||
|
wxDate GetYearEnd(); // Last Date Of Year
|
||||||
|
|
||||||
|
bool IsBetween(const wxDate& first, const wxDate& second) const;
|
||||||
|
|
||||||
|
wxDate Previous(int dayOfWeek) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // wxUSE_TIMEDATE
|
||||||
|
#endif
|
||||||
|
// _WX_DATE_H_
|
112
include/wx/time.h
Normal file
112
include/wx/time.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: time.h
|
||||||
|
// Purpose: wxTime class, from NIHCL
|
||||||
|
// Author: Julian Smart, after K. E. Gorlen
|
||||||
|
// Modified by:
|
||||||
|
// Created: 01/02/97
|
||||||
|
// RCS-ID: $Id$
|
||||||
|
// Copyright: (c) Julian Smart and Markus Holzem
|
||||||
|
// Licence: wxWindows licence
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _WX_TIMEH__
|
||||||
|
#define _WX_TIMEH__
|
||||||
|
|
||||||
|
#include "wx/object.h"
|
||||||
|
|
||||||
|
#if wxUSE_TIMEDATE
|
||||||
|
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#pragma interface "time.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxDate;
|
||||||
|
|
||||||
|
typedef unsigned short hourTy;
|
||||||
|
typedef unsigned short minuteTy;
|
||||||
|
typedef unsigned short secondTy;
|
||||||
|
typedef unsigned long clockTy;
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxTime: public wxObject
|
||||||
|
{
|
||||||
|
DECLARE_DYNAMIC_CLASS(wxTime)
|
||||||
|
|
||||||
|
public: // type definitions
|
||||||
|
enum tFormat { wx12h, wx24h };
|
||||||
|
enum tPrecision { wxStdMinSec, wxStdMin };
|
||||||
|
private:
|
||||||
|
static tFormat Format;
|
||||||
|
static tPrecision Precision;
|
||||||
|
|
||||||
|
clockTy sec; /* seconds since 1/1/1901 */
|
||||||
|
|
||||||
|
bool IsDST() const;
|
||||||
|
wxTime GetLocalTime() const;
|
||||||
|
private: // static member functions
|
||||||
|
static wxTime GetLocalTime(const wxDate& date, hourTy h=0, minuteTy m=0, secondTy s=0);
|
||||||
|
static wxTime GetBeginDST(unsigned year);
|
||||||
|
static wxTime GetEndDST(unsigned year);
|
||||||
|
public:
|
||||||
|
wxTime(); // current time
|
||||||
|
wxTime(clockTy s) { sec = s; }
|
||||||
|
void operator=(const wxTime& t) { sec = t.sec; } // Ordering required for some compilers
|
||||||
|
wxTime(const wxTime& t) { (*this) = t ; }
|
||||||
|
wxTime(hourTy h, minuteTy m, secondTy s =0, bool dst =FALSE);
|
||||||
|
wxTime(const wxDate&, hourTy h =0, minuteTy m =0, secondTy s=0, bool dst =FALSE);
|
||||||
|
|
||||||
|
// Convert to string
|
||||||
|
#ifndef __SALFORDC__
|
||||||
|
operator wxChar * (void);
|
||||||
|
operator wxDate() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool operator<(const wxTime& t) const { return sec < t.sec; }
|
||||||
|
bool operator<=(const wxTime& t) const { return sec <= t.sec; }
|
||||||
|
bool operator>(const wxTime& t) const { return sec > t.sec; }
|
||||||
|
bool operator>=(const wxTime& t) const { return sec >= t.sec; }
|
||||||
|
bool operator==(const wxTime& t) const { return sec == t.sec; }
|
||||||
|
bool operator!=(const wxTime& t) const { return sec != t.sec; }
|
||||||
|
friend wxTime operator+(const wxTime& t, long s) { return wxTime(t.sec+s); }
|
||||||
|
friend wxTime operator+(long s, const wxTime& t) { return wxTime(t.sec+s); }
|
||||||
|
long operator-(const wxTime& t) const { return sec - t.sec; }
|
||||||
|
wxTime operator-(long s) const { return wxTime(sec-s); }
|
||||||
|
void operator+=(long s) { sec += s; }
|
||||||
|
void operator-=(long s) { sec -= s; }
|
||||||
|
bool IsBetween(const wxTime& a, const wxTime& b) const;
|
||||||
|
|
||||||
|
/// Get day
|
||||||
|
int GetDay() const;
|
||||||
|
/// Get month
|
||||||
|
int GetMonth() const;
|
||||||
|
/// Get year
|
||||||
|
int GetYear() const;
|
||||||
|
/// Get day of week (0=Sunday 6=Saturday)
|
||||||
|
int GetDayOfWeek() const;
|
||||||
|
|
||||||
|
hourTy GetHour() const; // hour in local time
|
||||||
|
hourTy GetHourGMT() const; // hour in GMT
|
||||||
|
minuteTy GetMinute() const; // minute in local time
|
||||||
|
minuteTy GetMinuteGMT() const; // minute in GMT
|
||||||
|
secondTy GetSecond() const; // second in local time or GMT
|
||||||
|
clockTy GetSeconds() const { return sec; }
|
||||||
|
secondTy GetSecondGMT() const ;
|
||||||
|
wxTime Max(const wxTime&) const;
|
||||||
|
wxTime Min(const wxTime&) const;
|
||||||
|
static void SetFormat(const tFormat lFormat = wx12h,
|
||||||
|
const tPrecision lPrecision = wxStdMinSec);
|
||||||
|
wxChar *FormatTime() const;
|
||||||
|
/*
|
||||||
|
virtual int compare(const Object&) const;
|
||||||
|
virtual void deepenShallowCopy(); // {}
|
||||||
|
virtual unsigned hash() const;
|
||||||
|
virtual bool isEqual(const Object&) const;
|
||||||
|
virtual void printOn(ostream& strm =cout) const;
|
||||||
|
virtual const Class* species() const;
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
// wxUSE_TIMEDATE
|
||||||
|
#endif
|
||||||
|
// _WX_TIMEH__
|
||||||
|
|
656
src/common/date.cpp
Normal file
656
src/common/date.cpp
Normal file
@@ -0,0 +1,656 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: date.cpp
|
||||||
|
// Purpose: wxDate class
|
||||||
|
// Author:
|
||||||
|
// Originally inspired by Steve Marcus (CIS 72007,1233) 6/16/91
|
||||||
|
// Enhanced by Eric Simon (CIS 70540,1522) 6/29/91
|
||||||
|
// Further Enhanced by Chris Hill (CIS 72030,2606) 7/11/91
|
||||||
|
// Still Further Enhanced by Hill & Simon v3.10 8/05/91
|
||||||
|
// Version 4 by Charles D. Price 6/27/92
|
||||||
|
// Integrated into wxWindows by Julian Smart 9th July 1995
|
||||||
|
// Modified by:
|
||||||
|
// Created: 01/02/97
|
||||||
|
// RCS-ID: $Id$
|
||||||
|
// Copyright: (c) Julian Smart and Markus Holzem
|
||||||
|
// Licence: wxWindows licence
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#pragma implementation "date.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// For compilers that support precompilation, includes "wx.h".
|
||||||
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
|
#ifdef __BORLANDC__
|
||||||
|
#pragma hdrstop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if wxUSE_TIMEDATE
|
||||||
|
|
||||||
|
#include "wx/date.h"
|
||||||
|
#include "wx/intl.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "wx/ioswrap.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ABBR_LENGTH 3
|
||||||
|
|
||||||
|
static const wxChar *dayname[] = {
|
||||||
|
wxT("Sunday"), wxT("Monday"), wxT("Tuesday"), wxT("Wednesday"),
|
||||||
|
wxT("Thursday"), wxT("Friday"), wxT("Saturday")
|
||||||
|
};
|
||||||
|
|
||||||
|
static const wxChar *mname[] = {
|
||||||
|
wxT("January"), wxT("February"), wxT("March"), wxT("April"), wxT("May"), wxT("June"),
|
||||||
|
wxT("July"), wxT("August"), wxT("September"), wxT("October"), wxT("November"), wxT("December")
|
||||||
|
};
|
||||||
|
|
||||||
|
static int GauDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||||
|
|
||||||
|
IMPLEMENT_DYNAMIC_CLASS(wxDate, wxObject)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Constructors
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
wxDate::wxDate()
|
||||||
|
{
|
||||||
|
DisplayFormat=wxMDY;
|
||||||
|
DisplayOptions='\0';
|
||||||
|
month = day = year = day_of_week = 0;
|
||||||
|
julian = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate::wxDate (long j) : julian(j)
|
||||||
|
{
|
||||||
|
DisplayFormat=wxMDY;
|
||||||
|
DisplayOptions='\0';
|
||||||
|
julian_to_mdy ();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate::wxDate (int m, int d, int y) : month(m), day(d), year(y)
|
||||||
|
{
|
||||||
|
DisplayFormat=wxMDY;
|
||||||
|
DisplayOptions='\0';
|
||||||
|
mdy_to_julian ();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate::wxDate (const wxString& dat)
|
||||||
|
{
|
||||||
|
DisplayFormat=wxMDY;
|
||||||
|
DisplayOptions='\0';
|
||||||
|
if (wxStrcmp(dat, wxT("TODAY")) == 0 || wxStrcmp(dat, wxT("today")) == 0)
|
||||||
|
{
|
||||||
|
// Sets the current date
|
||||||
|
Set();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxChar buf[100];
|
||||||
|
wxStrcpy(buf, dat);
|
||||||
|
|
||||||
|
wxChar *save_ptr, *token = wxStrtok(buf,wxT("/-"),&save_ptr);
|
||||||
|
month = wxAtoi(token);
|
||||||
|
day = wxAtoi(wxStrtok((wxChar *) NULL,wxT("/-"),&save_ptr));
|
||||||
|
year = wxAtoi(wxStrtok((wxChar *) NULL,wxT(" "),&save_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
mdy_to_julian ();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate::wxDate (const wxDate &dt)
|
||||||
|
{
|
||||||
|
DisplayFormat=dt.DisplayFormat;
|
||||||
|
DisplayOptions=dt.DisplayOptions;
|
||||||
|
month = dt.month;
|
||||||
|
day = dt.day;
|
||||||
|
year = dt.year;
|
||||||
|
mdy_to_julian ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxDate::operator = (const wxDate &dt)
|
||||||
|
{
|
||||||
|
DisplayFormat=dt.DisplayFormat;
|
||||||
|
DisplayOptions=dt.DisplayOptions;
|
||||||
|
month = dt.month;
|
||||||
|
day = dt.day;
|
||||||
|
year = dt.year;
|
||||||
|
mdy_to_julian (); // wxUSE_TIMEDATE
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxDate::operator = (const wxString& dat)
|
||||||
|
{
|
||||||
|
DisplayFormat=wxMDY;
|
||||||
|
DisplayOptions='\0';
|
||||||
|
if (wxStrcmp(dat, wxT("TODAY")) == 0 || wxStrcmp(dat, wxT("today")) == 0)
|
||||||
|
{
|
||||||
|
// Sets the current date
|
||||||
|
Set();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxChar buf[100];
|
||||||
|
wxStrcpy(buf, dat);
|
||||||
|
|
||||||
|
wxChar *save_ptr, *token = wxStrtok(buf,wxT("/-"),&save_ptr);
|
||||||
|
month = wxAtoi(token);
|
||||||
|
day = wxAtoi(wxStrtok((wxChar *) NULL,wxT("/-"),&save_ptr));
|
||||||
|
year = wxAtoi(wxStrtok((wxChar *) NULL,wxT(" "),&save_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
mdy_to_julian ();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
// Conversion operations
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef __SALFORDC__
|
||||||
|
wxDate::operator wxString( void )
|
||||||
|
{
|
||||||
|
return FormatDate();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
// Date Arithmetic
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
wxDate wxDate::operator + (long i)
|
||||||
|
{
|
||||||
|
wxDate dp(julian + i);
|
||||||
|
return dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate wxDate::operator + (int i)
|
||||||
|
{
|
||||||
|
wxDate dp(julian + (long)i);
|
||||||
|
return dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate wxDate::operator - (long i)
|
||||||
|
{
|
||||||
|
wxDate dp(julian - i);
|
||||||
|
return dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate wxDate::operator - (int i)
|
||||||
|
{
|
||||||
|
wxDate dp(julian - (long)i);
|
||||||
|
return dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
long wxDate::operator - (const wxDate &dt)
|
||||||
|
{
|
||||||
|
return ( julian - dt.julian );
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate &wxDate::operator += (long i)
|
||||||
|
{
|
||||||
|
julian += i;
|
||||||
|
julian_to_mdy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate &wxDate::operator -= (long i)
|
||||||
|
{
|
||||||
|
julian -= i;
|
||||||
|
julian_to_mdy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate &wxDate::operator ++()
|
||||||
|
{
|
||||||
|
julian++;
|
||||||
|
julian_to_mdy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate &wxDate::operator ++(int)
|
||||||
|
{
|
||||||
|
julian++;
|
||||||
|
julian_to_mdy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate &wxDate::operator --()
|
||||||
|
{
|
||||||
|
julian--;
|
||||||
|
julian_to_mdy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate &wxDate::operator --(int)
|
||||||
|
{
|
||||||
|
julian--;
|
||||||
|
julian_to_mdy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
// Date comparison
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool WXDLLEXPORT operator < (const wxDate &dt1, const wxDate &dt2)
|
||||||
|
{
|
||||||
|
return ( dt1.julian < dt2.julian );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WXDLLEXPORT operator <= (const wxDate &dt1, const wxDate &dt2)
|
||||||
|
{
|
||||||
|
return ( (dt1.julian == dt2.julian) || (dt1.julian < dt2.julian) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WXDLLEXPORT operator > (const wxDate &dt1, const wxDate &dt2)
|
||||||
|
{
|
||||||
|
return ( dt1.julian > dt2.julian );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WXDLLEXPORT operator >= (const wxDate &dt1, const wxDate &dt2)
|
||||||
|
{
|
||||||
|
return ( (dt1.julian == dt2.julian) || (dt1.julian > dt2.julian) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WXDLLEXPORT operator == (const wxDate &dt1, const wxDate &dt2)
|
||||||
|
{
|
||||||
|
return ( dt1.julian == dt2.julian );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WXDLLEXPORT operator != (const wxDate &dt1, const wxDate &dt2)
|
||||||
|
{
|
||||||
|
return ( dt1.julian != dt2.julian );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if wxUSE_STD_IOSTREAM
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Ostream operations
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ostream WXDLLEXPORT & operator << (ostream &os, const wxDate &dt)
|
||||||
|
{
|
||||||
|
return os << dt.FormatDate().mb_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
// Conversion routines
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void wxDate::julian_to_wday (void)
|
||||||
|
{
|
||||||
|
// Correction by Peter Stadel <peters@jetcity.com>
|
||||||
|
day_of_week = (int)((julian - 2) % 7L);
|
||||||
|
/*
|
||||||
|
day_of_week = (int) ((julian + 2) % 7 + 1);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxDate::julian_to_mdy ()
|
||||||
|
{
|
||||||
|
long a,b,c,d,e,z,alpha;
|
||||||
|
z = julian+1;
|
||||||
|
// dealing with Gregorian calendar reform
|
||||||
|
if (z < 2299161L)
|
||||||
|
a = z;
|
||||||
|
else {
|
||||||
|
alpha = (long) ((z-1867216.25) / 36524.25);
|
||||||
|
a = z + 1 + alpha - alpha/4;
|
||||||
|
}
|
||||||
|
b = ( a > 1721423 ? a + 1524 : a + 1158 );
|
||||||
|
c = (long) ((b - 122.1) / 365.25);
|
||||||
|
d = (long) (365.25 * c);
|
||||||
|
e = (long) ((b - d) / 30.6001);
|
||||||
|
day = (int)(b - d - (long)(30.6001 * e));
|
||||||
|
month = (int)((e < 13.5) ? e - 1 : e - 13);
|
||||||
|
year = (int)((month > 2.5 ) ? (c - 4716) : c - 4715);
|
||||||
|
julian_to_wday ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxDate::mdy_to_julian (void)
|
||||||
|
{
|
||||||
|
int a,b=0;
|
||||||
|
int work_month=month, work_day=day, work_year=year;
|
||||||
|
// correct for negative year
|
||||||
|
if (work_year < 0)
|
||||||
|
work_year++;
|
||||||
|
if (work_month <= 2)
|
||||||
|
{ work_year--; work_month +=12; }
|
||||||
|
|
||||||
|
// deal with Gregorian calendar
|
||||||
|
if (work_year*10000. + work_month*100. + work_day >= 15821015.)
|
||||||
|
{
|
||||||
|
a = (int)(work_year/100.);
|
||||||
|
b = 2 - a + a/4;
|
||||||
|
}
|
||||||
|
julian = (long) (365.25*work_year) +
|
||||||
|
(long) (30.6001 * (work_month+1)) + work_day + 1720994L + b;
|
||||||
|
julian_to_wday ();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Format routine
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
wxString wxDate::FormatDate (int type) const
|
||||||
|
{
|
||||||
|
int actualType = type;
|
||||||
|
if (actualType == -1)
|
||||||
|
actualType = DisplayFormat;
|
||||||
|
|
||||||
|
wxChar buf[40];
|
||||||
|
|
||||||
|
memset( buf, '\0', sizeof(buf) );
|
||||||
|
switch ( actualType )
|
||||||
|
{
|
||||||
|
case wxDAY:
|
||||||
|
if ( (day_of_week < 1) || (day_of_week > 7) )
|
||||||
|
wxStrcpy(buf, _("invalid day"));
|
||||||
|
else
|
||||||
|
wxStrncpy( buf, wxGetTranslation(dayname[day_of_week-1]),
|
||||||
|
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
|
||||||
|
return wxString(buf);
|
||||||
|
|
||||||
|
case wxMONTH:
|
||||||
|
if ( (month < 1) || (month > 12) )
|
||||||
|
wxStrcpy(buf, _("invalid month"));
|
||||||
|
else
|
||||||
|
wxStrncpy( buf, wxGetTranslation(mname[month-1]),
|
||||||
|
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
|
||||||
|
return wxString(buf);
|
||||||
|
|
||||||
|
case wxFULL:
|
||||||
|
if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
|
||||||
|
(day_of_week > 7) )
|
||||||
|
{
|
||||||
|
wxStrcpy(buf, _("invalid date"));
|
||||||
|
return wxString(buf);
|
||||||
|
}
|
||||||
|
wxStrncpy( buf, wxGetTranslation(dayname[day_of_week-1]),
|
||||||
|
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
|
||||||
|
wxStrcat( buf, wxT(", "));
|
||||||
|
wxStrncat( buf, wxGetTranslation(mname[month-1]),
|
||||||
|
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
|
||||||
|
wxStrcat( buf, wxT(" "));
|
||||||
|
wxSprintf( buf+wxStrlen(buf), wxT("%d, %d"), day, abs(year) );
|
||||||
|
if (year < 0)
|
||||||
|
wxStrcat(buf,_(" B.C."));
|
||||||
|
return wxString(buf);
|
||||||
|
|
||||||
|
case wxEUROPEAN:
|
||||||
|
if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
|
||||||
|
(day_of_week > 7) )
|
||||||
|
{
|
||||||
|
wxStrcpy(buf, _("invalid date"));
|
||||||
|
return wxString(buf);
|
||||||
|
}
|
||||||
|
wxSprintf(buf,wxT("%d "), day);
|
||||||
|
wxStrncat(buf, wxGetTranslation(mname[month-1]),
|
||||||
|
(DisplayOptions & wxDATE_ABBR) ? ABBR_LENGTH : 9);
|
||||||
|
wxSprintf( buf+wxStrlen(buf), wxT(" %d"), abs(year) );
|
||||||
|
if (year < 0)
|
||||||
|
wxStrcat(buf, _(" B.C."));
|
||||||
|
return wxString(buf);
|
||||||
|
|
||||||
|
case wxMDY:
|
||||||
|
default:
|
||||||
|
if (day==0 || month==0 || year==0)
|
||||||
|
wxStrcpy(buf, _("invalid date"));
|
||||||
|
else
|
||||||
|
wxSprintf( buf+wxStrlen(buf), wxT("%1d/%1d/%02d"), month, day,
|
||||||
|
(DisplayOptions & wxNO_CENTURY) && (abs(year) > 1899)
|
||||||
|
? (abs(year) - (abs(year) / 100 * 100))
|
||||||
|
: (abs(year)) );
|
||||||
|
return wxString(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxDate::SetFormat( int format )
|
||||||
|
{
|
||||||
|
DisplayFormat = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxDate::SetOption( int option, bool action )
|
||||||
|
{
|
||||||
|
switch ( option )
|
||||||
|
{
|
||||||
|
case wxNO_CENTURY:
|
||||||
|
if ( action )
|
||||||
|
DisplayOptions |= wxNO_CENTURY;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DisplayOptions &= (~wxNO_CENTURY);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
case wxDATE_ABBR:
|
||||||
|
if ( action )
|
||||||
|
DisplayOptions |= wxDATE_ABBR;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DisplayOptions &= (~wxDATE_ABBR);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Miscellaneous Routines
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
long wxDate::GetJulianDate( void ) const
|
||||||
|
{
|
||||||
|
return julian;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxDate::GetDayOfYear( void ) const
|
||||||
|
{
|
||||||
|
wxDate temp( 1, 1, year );
|
||||||
|
|
||||||
|
return (int) (julian - temp.julian + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool wxDate::IsLeapYear( void ) const
|
||||||
|
{
|
||||||
|
return ( (year >= 1582) ?
|
||||||
|
(year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ):
|
||||||
|
(year % 4 == 0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version 4.0 Extension to Public Interface - CDP
|
||||||
|
|
||||||
|
wxDate& wxDate::Set()
|
||||||
|
{
|
||||||
|
//#ifdef __WXMSW__
|
||||||
|
#if 0
|
||||||
|
struct _dosdate_t sDate;
|
||||||
|
_dos_getdate(&sDate);
|
||||||
|
|
||||||
|
month = sDate.month;
|
||||||
|
day = sDate.day;
|
||||||
|
year = sDate.year;
|
||||||
|
|
||||||
|
mdy_to_julian();
|
||||||
|
#else
|
||||||
|
time_t now = time((time_t *) NULL);
|
||||||
|
struct tm *localTime = localtime(&now);
|
||||||
|
|
||||||
|
month = localTime->tm_mon + 1;
|
||||||
|
day = localTime->tm_mday;
|
||||||
|
year = localTime->tm_year + 1900;
|
||||||
|
|
||||||
|
mdy_to_julian ();
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate& wxDate::Set(
|
||||||
|
int nMonth,
|
||||||
|
int nDay,
|
||||||
|
int nYear)
|
||||||
|
{
|
||||||
|
month = nMonth;
|
||||||
|
year = nYear < 0 ? 9999 : nYear;
|
||||||
|
year = nYear > 9999 ? 0 : nYear;
|
||||||
|
day = nDay < GetDaysInMonth() ? nDay : GetDaysInMonth();
|
||||||
|
|
||||||
|
mdy_to_julian();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate &
|
||||||
|
wxDate::Set(long j)
|
||||||
|
{
|
||||||
|
julian = j;
|
||||||
|
|
||||||
|
julian_to_mdy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wxDate::GetDaysInMonth()
|
||||||
|
{
|
||||||
|
return GauDays[month-1] + (month==2 && IsLeapYear());
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxDate::GetFirstDayOfMonth() const
|
||||||
|
{
|
||||||
|
return wxDate(month, 1, year).GetDayOfWeek();
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxDate::GetDay() const
|
||||||
|
{
|
||||||
|
return day;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxDate::GetDayOfWeek() const
|
||||||
|
{
|
||||||
|
return day_of_week;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxDate::GetYear() const
|
||||||
|
{
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxDate::GetMonth() const
|
||||||
|
{
|
||||||
|
return month;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate& wxDate::AddWeeks(int nCount)
|
||||||
|
{
|
||||||
|
Set(julian + (long)nCount*7);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate& wxDate::AddMonths(int nCount)
|
||||||
|
{
|
||||||
|
month += nCount;
|
||||||
|
|
||||||
|
if (month < 1) {
|
||||||
|
month = 12;
|
||||||
|
year--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (month > 12) {
|
||||||
|
month = 1;
|
||||||
|
year++;
|
||||||
|
}
|
||||||
|
mdy_to_julian();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate& wxDate::AddYears(int nCount)
|
||||||
|
{
|
||||||
|
year += nCount;
|
||||||
|
mdy_to_julian();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxDate::GetWeekOfMonth()
|
||||||
|
{
|
||||||
|
// Abs day includes the days from previous month that fills up
|
||||||
|
// the begin. of the week.
|
||||||
|
int nAbsDay = day + GetFirstDayOfMonth()-1;
|
||||||
|
return (nAbsDay-GetDayOfWeek())/7 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxDate::GetWeekOfYear()
|
||||||
|
{
|
||||||
|
wxDate doTemp(1, 1, year);
|
||||||
|
return (int)(((julian - doTemp.julian+1)/7) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate wxDate::GetMonthStart()
|
||||||
|
{
|
||||||
|
return(wxDate(month, 1, year));
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate wxDate::GetMonthEnd()
|
||||||
|
{
|
||||||
|
return(wxDate(month+1, 1, year)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate wxDate::GetYearStart()
|
||||||
|
{
|
||||||
|
return(wxDate(1, 1, year));
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDate wxDate::GetYearEnd()
|
||||||
|
{
|
||||||
|
return(wxDate(1, 1, year+1)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString wxDate::GetMonthName()
|
||||||
|
{
|
||||||
|
return(FormatDate(wxMONTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString wxDate::GetDayOfWeekName()
|
||||||
|
{
|
||||||
|
return(FormatDate(wxDAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxDate::IsBetween(const wxDate& first, const wxDate& second) const
|
||||||
|
{
|
||||||
|
return (julian >= first.julian && julian <= second.julian);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is from NIHCL
|
||||||
|
wxDate wxDate::Previous(int dayOfWeek) const
|
||||||
|
{
|
||||||
|
int this_day_Of_Week, desired_day_Of_Week;
|
||||||
|
long j;
|
||||||
|
|
||||||
|
// Set the desired and current day of week to start at 0 (Monday)
|
||||||
|
// and end at 6 (Sunday).
|
||||||
|
|
||||||
|
desired_day_Of_Week = dayOfWeek - 1; // These functions return a value
|
||||||
|
this_day_Of_Week = GetDayOfWeek() - 1; // from 1-7. Subtract 1 for 0-6.
|
||||||
|
j = julian;
|
||||||
|
|
||||||
|
// Have to determine how many days difference from current day back to
|
||||||
|
// desired, if any. Special calculation under the 'if' statement to
|
||||||
|
// effect the wraparound counting from Monday (0) back to Sunday (6).
|
||||||
|
|
||||||
|
if (desired_day_Of_Week > this_day_Of_Week)
|
||||||
|
this_day_Of_Week += 7 - desired_day_Of_Week;
|
||||||
|
else
|
||||||
|
this_day_Of_Week -= desired_day_Of_Week;
|
||||||
|
j -= this_day_Of_Week; // Adjust j to set it at the desired day of week.
|
||||||
|
return wxDate(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
447
src/common/time.cpp
Normal file
447
src/common/time.cpp
Normal file
@@ -0,0 +1,447 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: time.cpp
|
||||||
|
// Purpose: wxTime class, from NIHCL
|
||||||
|
// Author: Julian Smart, after K. E. Gorlen
|
||||||
|
// Modified by:
|
||||||
|
// Created: 04/01/98
|
||||||
|
// RCS-ID: $Id$
|
||||||
|
// Copyright: (c) Julian Smart and Markus Holzem
|
||||||
|
// Licence: wxWindows license
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#pragma implementation "time.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Provides an object that represents a Time, stored as the number of
|
||||||
|
seconds since January 1, 1901, GMT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// For compilers that support precompilation, includes "wx.h".
|
||||||
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
|
#ifdef __BORLANDC__
|
||||||
|
#pragma hdrstop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "wx/setup.h"
|
||||||
|
|
||||||
|
#if wxUSE_TIMEDATE
|
||||||
|
|
||||||
|
#include "wx/time.h"
|
||||||
|
#include "wx/date.h"
|
||||||
|
#include "wx/utils.h"
|
||||||
|
#include "wx/intl.h"
|
||||||
|
|
||||||
|
#if wxUSE_STD_IOSTREAM
|
||||||
|
#include "wx/ioswrap.h"
|
||||||
|
#if wxUSE_IOSTREAMH
|
||||||
|
#include <iomanip.h>
|
||||||
|
#else
|
||||||
|
#include <iomanip>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
IMPLEMENT_DYNAMIC_CLASS(wxTime, wxObject)
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef WX_TIMEZONE
|
||||||
|
#define WX_TIMEZONE _timezone
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern long wxGetUTCTime(void);
|
||||||
|
bool wxGetTZandDST(long *timeZone, int *dstObserved)
|
||||||
|
{
|
||||||
|
time_t now;
|
||||||
|
struct tm *tm;
|
||||||
|
|
||||||
|
now = time((time_t *) NULL);
|
||||||
|
|
||||||
|
if (now != (time_t)-1)
|
||||||
|
{
|
||||||
|
tm = localtime(&now);
|
||||||
|
|
||||||
|
if ((tm) && (tm->tm_isdst > 0))
|
||||||
|
*dstObserved = 1;
|
||||||
|
}
|
||||||
|
*timeZone = WX_TIMEZONE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static long TIME_ZONE; /* seconds west of GMT */
|
||||||
|
static int DST_OBSERVED; /* flags U.S. daylight saving time observed */
|
||||||
|
|
||||||
|
static bool wxTimeInitialized = FALSE;
|
||||||
|
|
||||||
|
wxTime::tFormat wxTime::Format = wxTime::wx12h;
|
||||||
|
wxTime::tPrecision wxTime::Precision = wxTime::wxStdMinSec;
|
||||||
|
|
||||||
|
static const unsigned long seconds_in_day = 24*60*60L;
|
||||||
|
static const wxDate refDate(1,1,1901);
|
||||||
|
// static const wxDate maxDate(49709L); /* ((2**32)-1)/seconds_in_day -1 */
|
||||||
|
|
||||||
|
wxTime wxTime::GetLocalTime(const wxDate& date, hourTy h, minuteTy m, secondTy s)
|
||||||
|
/*
|
||||||
|
Return a local wxTime for the specified Standard Time date, hour, minute,
|
||||||
|
and second.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if (!wxTimeInitialized)
|
||||||
|
{
|
||||||
|
wxGetTZandDST(&TIME_ZONE, &DST_OBSERVED);
|
||||||
|
wxTimeInitialized = TRUE;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (!date.IsBetween(refDate,maxDate))
|
||||||
|
setError(NIHCL_DATERANGE,DEFAULT,
|
||||||
|
date.dayOfMonth(),date.nameOfMonth(),date.year());
|
||||||
|
*/
|
||||||
|
// The following line causes an error in GCC 2.1
|
||||||
|
// long daysBetween = date-refDate;
|
||||||
|
// ... but this seems to get round it.
|
||||||
|
wxDate tmp1(date);
|
||||||
|
wxDate tmp2(refDate);
|
||||||
|
long daysBetween = tmp1 - tmp2;
|
||||||
|
|
||||||
|
return wxTime(seconds_in_day*daysBetween + 60*60L*h + 60*m + s);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTime::wxTime()
|
||||||
|
/*
|
||||||
|
Construct a wxTime for this instant.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if (!wxTimeInitialized)
|
||||||
|
{
|
||||||
|
wxGetTZandDST(&TIME_ZONE, &DST_OBSERVED);
|
||||||
|
wxTimeInitialized = TRUE;
|
||||||
|
}
|
||||||
|
sec = wxGetUTCTime();
|
||||||
|
#ifdef __SALFORDC__
|
||||||
|
sec += (unsigned long) 2177452800; /* seconds from 1/1/01 to 1/1/70 */
|
||||||
|
#else
|
||||||
|
sec += 2177452800UL; /* seconds from 1/1/01 to 1/1/70 */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTime::wxTime(hourTy h, minuteTy m, secondTy s, bool dst)
|
||||||
|
/*
|
||||||
|
Construct a wxTime for today at the specified (local) hour, minute, and
|
||||||
|
second.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if (!wxTimeInitialized)
|
||||||
|
{
|
||||||
|
wxGetTZandDST(&TIME_ZONE, &DST_OBSERVED);
|
||||||
|
wxTimeInitialized = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sec = wxTime(wxDate(),h,m,s,dst).sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxTime::wxTime(const wxDate& date, hourTy h, minuteTy m, secondTy s, bool dst)
|
||||||
|
/*
|
||||||
|
Construct a wxTime for the specified (local) Date, hour, minute, and
|
||||||
|
second.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if (!wxTimeInitialized)
|
||||||
|
{
|
||||||
|
wxGetTZandDST(&TIME_ZONE, &DST_OBSERVED);
|
||||||
|
wxTimeInitialized = TRUE;
|
||||||
|
}
|
||||||
|
sec = GetLocalTime(date,h,m,s).sec-3600;
|
||||||
|
if (IsDST())
|
||||||
|
{
|
||||||
|
sec += 3600;
|
||||||
|
if (IsDST() || dst) sec -= 3600;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sec += 3600;
|
||||||
|
/*
|
||||||
|
if (IsDST()) setError(NIHCL_BADTIME,DEFAULT,
|
||||||
|
date.dayOfMonth(),date.nameOfMonth(),date.year(),
|
||||||
|
h,m,s,(dst?_("DST"):""));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
sec += TIME_ZONE; // adjust to GMT
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __SALFORDC__
|
||||||
|
wxTime::operator wxDate() const
|
||||||
|
/*
|
||||||
|
Convert a wxTime to a local wxDate
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
// return wxDate((int)(GetLocalTime().sec/seconds_in_day)); 4.2 cc bug
|
||||||
|
long daycount = (long)(GetLocalTime().sec/seconds_in_day);
|
||||||
|
|
||||||
|
wxDate date(1,1,1901);
|
||||||
|
date += daycount;
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool wxTime::IsBetween(const wxTime& a, const wxTime& b) const
|
||||||
|
{
|
||||||
|
return *this >= a && *this <= b;
|
||||||
|
}
|
||||||
|
|
||||||
|
hourTy wxTime::GetHour() const
|
||||||
|
/*
|
||||||
|
Return the hour of this wxTime in local time; i.e., adjust for
|
||||||
|
time zone and Daylight Savings Time.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return GetLocalTime().GetHourGMT();
|
||||||
|
}
|
||||||
|
|
||||||
|
hourTy wxTime::GetHourGMT() const
|
||||||
|
/*
|
||||||
|
Return the hour of this Time in GMT.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return (hourTy)((sec % 86400) / 3600);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTime wxTime::GetBeginDST(unsigned year)
|
||||||
|
/*
|
||||||
|
Return the local Standard Time at which Daylight Savings Time
|
||||||
|
begins in the specified year.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
// Previous Sunday
|
||||||
|
wxTime DSTtime(GetLocalTime(wxDate(3,31,year).Previous(1)+7,2));
|
||||||
|
if (year<=1986) {
|
||||||
|
// Previous Sunday
|
||||||
|
DSTtime = GetLocalTime(wxDate(4,30,year).Previous(1),2);
|
||||||
|
if (year==1974) DSTtime = GetLocalTime(wxDate(1,6,1974),2);
|
||||||
|
if (year==1975) DSTtime = GetLocalTime(wxDate(2,23,1975),2);
|
||||||
|
}
|
||||||
|
return DSTtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTime wxTime::GetEndDST(unsigned year)
|
||||||
|
/*
|
||||||
|
Return the local Standard Time at which Daylight Savings Time
|
||||||
|
ends in the specified year.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
wxTime STDtime(GetLocalTime(wxDate(10,31,year).Previous(1),2-1));
|
||||||
|
return STDtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxTime::IsDST() const
|
||||||
|
/*
|
||||||
|
Return TRUE if this local Standard Time should be adjusted
|
||||||
|
for Daylight Savings Time.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
long daycount = (long)(sec/seconds_in_day);
|
||||||
|
|
||||||
|
// At this point, daycount is the number of days from 1/1/1901.
|
||||||
|
// Need to convert to julian date (which starts at 1/1/4713 B.C.)
|
||||||
|
wxDate date(1,1,1901);
|
||||||
|
date += daycount;
|
||||||
|
|
||||||
|
unsigned year = date.GetYear();
|
||||||
|
if (DST_OBSERVED)
|
||||||
|
{
|
||||||
|
if (*this >= GetBeginDST(year))
|
||||||
|
if (*this < GetEndDST(year)) return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTime wxTime::GetLocalTime() const
|
||||||
|
/*
|
||||||
|
Adjusts this GM Time for local time zone and Daylight Savings Time.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
wxTime local_time(sec-TIME_ZONE);
|
||||||
|
if (local_time.IsDST()) local_time.sec += 3600;
|
||||||
|
return local_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
minuteTy wxTime::GetMinute() const
|
||||||
|
/*
|
||||||
|
Return the minute of this wxTime in local time; i.e., adjust
|
||||||
|
for time zone and Daylight Savings Time.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return GetLocalTime().GetMinuteGMT();
|
||||||
|
}
|
||||||
|
|
||||||
|
minuteTy wxTime::GetMinuteGMT() const
|
||||||
|
/*
|
||||||
|
Return the minute of this wxTime in GMT.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return (minuteTy)(((sec % 86400) % 3600) / 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
secondTy wxTime::GetSecond() const
|
||||||
|
/*
|
||||||
|
Return the second of this wxTime.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return (secondTy)(((sec % 86400) % 3600) % 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
secondTy wxTime::GetSecondGMT() const
|
||||||
|
/*
|
||||||
|
Return the minute of this wxTime in GMT.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return (secondTy)(((sec % 86400) % 3600) % 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxTime::GetDay() const
|
||||||
|
{
|
||||||
|
wxDate da((wxDate) *this);
|
||||||
|
return da.GetDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxTime::GetDayOfWeek() const
|
||||||
|
{
|
||||||
|
wxDate da((wxDate) *this);
|
||||||
|
return da.GetDayOfWeek();
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxTime::GetMonth() const
|
||||||
|
{
|
||||||
|
wxDate da((wxDate) *this);
|
||||||
|
return da.GetMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxTime::GetYear() const
|
||||||
|
{
|
||||||
|
wxDate da((wxDate) *this);
|
||||||
|
return da.GetYear();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTime wxTime::Max(const wxTime& t) const
|
||||||
|
{
|
||||||
|
if (t < *this) return *this;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTime wxTime::Min(const wxTime& t) const
|
||||||
|
{
|
||||||
|
if (t > *this) return *this;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __SALFORDC__
|
||||||
|
wxTime::operator wxChar *(void)
|
||||||
|
{
|
||||||
|
return FormatTime();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void wxTime::SetFormat(const wxTime::tFormat lFormat,
|
||||||
|
const wxTime::tPrecision lPrecision) {
|
||||||
|
|
||||||
|
wxTime::Format = lFormat;
|
||||||
|
wxTime::Precision = lPrecision;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxChar *wxTime::FormatTime() const {
|
||||||
|
static wxChar timeBuf[30];
|
||||||
|
unsigned hh(GetHour());
|
||||||
|
|
||||||
|
switch (Format) {
|
||||||
|
case wx12h:
|
||||||
|
hh -= 12;
|
||||||
|
break;
|
||||||
|
case wx24h:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Precision) {
|
||||||
|
case wxStdMinSec:
|
||||||
|
wxSprintf(timeBuf,wxT("%2d:%02d:%02d"),hh,GetMinute(),GetSecond());
|
||||||
|
break;
|
||||||
|
case wxStdMin:
|
||||||
|
wxSprintf(timeBuf,wxT("%2d:%02d"),hh,GetMinute());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Format == wx12h)
|
||||||
|
if (GetHour() <= 12)
|
||||||
|
wxStrcat(timeBuf,_("am"));
|
||||||
|
else
|
||||||
|
wxStrcat(timeBuf,_("pm"));
|
||||||
|
|
||||||
|
return timeBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
int wxTime::compare(const Object& ob) const
|
||||||
|
{
|
||||||
|
assertArgSpecies(ob,classDesc,"compare");
|
||||||
|
register clockTy t = castdown(ob).sec;
|
||||||
|
if (sec < t) return -1;
|
||||||
|
if (sec > t) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxTime::deepenShallowCopy() {}
|
||||||
|
|
||||||
|
unsigned wxTime::hash() const { return sec; }
|
||||||
|
|
||||||
|
bool wxTime::isEqual(const Object& ob) const
|
||||||
|
{
|
||||||
|
return ob.isSpecies(classDesc) && *this==castdown(ob);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Class* wxTime::species() const { return &classDesc; }
|
||||||
|
|
||||||
|
void wxTime::printOn(ostream& strm) const
|
||||||
|
{
|
||||||
|
register unsigned hh = GetHour();
|
||||||
|
wxDate(*this).printOn(strm);
|
||||||
|
strm << ' ' << ((hh <= 12) ? hh : hh-12) << ':'
|
||||||
|
<< setfill('0') << setw(2) << GetMinute() << ':'
|
||||||
|
<< setfill('0') << setw(2) << GetSecond() << ' ';
|
||||||
|
if (hh < 12) strm << _("am");
|
||||||
|
else strm << _("pm");
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTime::wxTime(OIOin& strm)
|
||||||
|
: BASE(strm)
|
||||||
|
{
|
||||||
|
unsigned long usec;
|
||||||
|
strm >> sec >> usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxTime::storer(OIOout& strm) const
|
||||||
|
{
|
||||||
|
BASE::storer(strm);
|
||||||
|
strm << sec << 0l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxTime::wxTime(OIOifd& fd)
|
||||||
|
: BASE(fd)
|
||||||
|
{
|
||||||
|
unsigned long usec;
|
||||||
|
fd >> sec >> usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxTime::storer(OIOofd& fd) const
|
||||||
|
{
|
||||||
|
BASE::storer(fd);
|
||||||
|
fd << sec << 0l;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
@@ -1,617 +0,0 @@
|
|||||||
0.9.4 (1/25/2004 to //2004)
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
Removed wxd decorators in favor of new SWIG-generated docstrings.
|
|
||||||
|
|
||||||
Removed docs tabs from crust interface:
|
|
||||||
* wxPython Docs
|
|
||||||
* wxSTC Docs
|
|
||||||
|
|
||||||
Fixed Calltip tab refresh problem on Windows.
|
|
||||||
|
|
||||||
shell.autoCompleteAutoHide added with default of False.
|
|
||||||
|
|
||||||
Changed default namespace of Shell to __main__.__dict__, instead of an
|
|
||||||
empty dictionary.
|
|
||||||
|
|
||||||
|
|
||||||
0.9.3 (9/25/2003 to 1/24/2004)
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
Fun and games with dynamic renaming. Details of any other changes
|
|
||||||
were lost in the confusion. I'll try to do better in the future.
|
|
||||||
|
|
||||||
|
|
||||||
0.9.2 (5/3/2003 to 9/25/2003)
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
Changed to the new prefix-less "wx" package::
|
|
||||||
|
|
||||||
import wx
|
|
||||||
|
|
||||||
instead of::
|
|
||||||
|
|
||||||
from wxPython import wx
|
|
||||||
|
|
||||||
Fixed typo in ``PyWrap.py``::
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main(sys.argv)
|
|
||||||
|
|
||||||
should have been::
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
||||||
Added pretty-print Display tab to Crust, based on suggestion from
|
|
||||||
Jason Whitlark.
|
|
||||||
|
|
||||||
Improved ``Can*`` checks in ``EditWindow``, since STC is too lenient,
|
|
||||||
particularly when it is set to read-only but returns True for
|
|
||||||
CanPaste() (seems like an STC bug to me)::
|
|
||||||
|
|
||||||
def CanCopy(self):
|
|
||||||
"""Return True if text is selected and can be copied."""
|
|
||||||
return self.GetSelectionStart() != self.GetSelectionEnd()
|
|
||||||
|
|
||||||
def CanCut(self):
|
|
||||||
"""Return True if text is selected and can be cut."""
|
|
||||||
return self.CanCopy() and self.CanEdit()
|
|
||||||
|
|
||||||
def CanEdit(self):
|
|
||||||
"""Return True if editing should succeed."""
|
|
||||||
return not self.GetReadOnly()
|
|
||||||
|
|
||||||
def CanPaste(self):
|
|
||||||
"""Return True if pasting should succeed."""
|
|
||||||
return stc.StyledTextCtrl.CanPaste(self) and self.CanEdit()
|
|
||||||
|
|
||||||
|
|
||||||
0.9.1 (3/21/2003 to 5/2/2003)
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
PyCrust is dead! Long live Py!
|
|
||||||
|
|
||||||
* Renamed ``PyCrust`` package to ``py``.
|
|
||||||
* Moved code to wxPython's CVS repository.
|
|
||||||
|
|
||||||
Fixed bug in ``introspect.py`` on introspecting objects occurring
|
|
||||||
immediately after a secondary prompt, like this::
|
|
||||||
|
|
||||||
>>> l = [1, 2, 3]
|
|
||||||
>>> for n in range(3):
|
|
||||||
... l. <-- failed to popup autocomplete list
|
|
||||||
|
|
||||||
Added documentation files:
|
|
||||||
|
|
||||||
* PyManual.txt
|
|
||||||
* wxPythonManual.txt
|
|
||||||
* wxPythonPackage.txt
|
|
||||||
* wxPythonExamples.txt
|
|
||||||
|
|
||||||
Added PyAlaMode and PyAlaCarte code editors.
|
|
||||||
|
|
||||||
Major refactoring to support ``editor`` and ``shell`` from the same
|
|
||||||
base.
|
|
||||||
|
|
||||||
Renamed program files:
|
|
||||||
|
|
||||||
* ``PyCrustApp.py`` to ``PyCrust.py``
|
|
||||||
* ``PyFillingApp.py`` to ``PyFilling.py``
|
|
||||||
* ``PyShellApp.py`` to ``PyShell.py``
|
|
||||||
* ``wrap.py`` to ``PyWrap.py``
|
|
||||||
|
|
||||||
Removed disabling of autocomplete for lists of 2000 items or more.
|
|
||||||
The current implementation of wxSTC can now handle lists this big.
|
|
||||||
|
|
||||||
Improved handling of ``sys.path`` to mimic the standard Python shell.
|
|
||||||
|
|
||||||
|
|
||||||
0.9 (2/27/2003 to 3/20/2003)
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
Added fontIncrease, fontDecrease, fontDefault signals, receivers and
|
|
||||||
keybindings::
|
|
||||||
|
|
||||||
Ctrl+] Increase font size.
|
|
||||||
Ctrl+[ Decrease font size.
|
|
||||||
Ctrl+= Default font size.
|
|
||||||
|
|
||||||
Continued enhancement of the decorator capability to provide better
|
|
||||||
documentation and docstrings for wxPython classes and functions.
|
|
||||||
|
|
||||||
Introduced new tabbed interface:
|
|
||||||
|
|
||||||
* Namespace
|
|
||||||
* Calltip
|
|
||||||
* Session
|
|
||||||
* Dispatcher
|
|
||||||
* wxPython Docs
|
|
||||||
* wxSTC Docs
|
|
||||||
|
|
||||||
``Filling.tree`` now expands tuples as well as lists. (It should have
|
|
||||||
done this all along, I just never noticed this omission before.)
|
|
||||||
|
|
||||||
Added this True/False test to all modules::
|
|
||||||
|
|
||||||
try:
|
|
||||||
True
|
|
||||||
except NameError:
|
|
||||||
True = 1==1
|
|
||||||
False = 1==0
|
|
||||||
|
|
||||||
Added ``wxd`` directory with decoration classes.
|
|
||||||
|
|
||||||
|
|
||||||
0.8.2 (1/5/2003 to 2/26/2003)
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
Wrapped ``sys.ps1``, ``sys.ps2``, and ``sys.ps3`` in ``str()``.
|
|
||||||
(Thanks, Kieran Holland.)
|
|
||||||
|
|
||||||
Fixed minor things found by PyChecker.
|
|
||||||
|
|
||||||
Changed locals to use ``__main__.__dict__`` and added code to clean up
|
|
||||||
the namespace, making it as close to the regular Python environment as
|
|
||||||
possible. This solves the problem of pickling and unpickling
|
|
||||||
instances of classes defined in the shell.
|
|
||||||
|
|
||||||
Made ``shell.PasteAndRun()`` a little more forgiving when it finds a
|
|
||||||
ps2 prompt line with no trailing space, such when you copy code from a
|
|
||||||
web page.
|
|
||||||
|
|
||||||
Improved autocomplete behavior by adding these to shell::
|
|
||||||
|
|
||||||
self.AutoCompSetAutoHide(False)
|
|
||||||
self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`')
|
|
||||||
|
|
||||||
Added ``decor`` directory, ``decorator.py``, ``stcDecor.py``, and
|
|
||||||
``stcConstants.py``. These all serve the purpose of adding docstrings
|
|
||||||
to existing wxPython classes, in particular the ``wxStyledTextCtrl``.
|
|
||||||
|
|
||||||
Added ``wrap.py``, a command line utility for running a wxPython app
|
|
||||||
with additional runtime-tools loaded, such as PyCrust (the only tool
|
|
||||||
at this point).
|
|
||||||
|
|
||||||
Flushed the clipboard Cut/Copy operations so that selections will
|
|
||||||
exist in the clipboard even after PyCrust has been closed.
|
|
||||||
|
|
||||||
Improved the suppression of docstrings for simple data types appearing
|
|
||||||
in the namespace viewer.
|
|
||||||
|
|
||||||
Better handling of autocompletion with numeric types; no
|
|
||||||
autocompletion when typing a dot after an integer. If the
|
|
||||||
autocompletion is desired, type a space before the dot::
|
|
||||||
|
|
||||||
func = 3 .
|
|
||||||
|
|
||||||
More Filling!!! The namespace tree is now dynamically updated.
|
|
||||||
|
|
||||||
|
|
||||||
0.8.1 (12/20/2002 to 12/25/2002)
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
Improved keyboard handling with Autocomplete active. You can now use
|
|
||||||
Enter as well as Tab to select an item from the list.
|
|
||||||
|
|
||||||
Disabled autocomplete for lists of 2000 items or more. The current
|
|
||||||
implementation of wxSTC can't handle lists this big.
|
|
||||||
|
|
||||||
Changed ``filling`` to always display docstrings for objects. This is
|
|
||||||
useful for objects whose docstrings have been decorated, rather than
|
|
||||||
coming directly from the source code. (Hmmm. Sounds like someone is
|
|
||||||
doing some decorating. I wonder where that would be helpful? <wink>)
|
|
||||||
|
|
||||||
Fixed handling of icon. Added ``images.py`` file.
|
|
||||||
|
|
||||||
|
|
||||||
0.8 (10/29/2002 to 12/16/2002)
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
Added "help" to startup banner info.
|
|
||||||
|
|
||||||
Made all ``wx`` and ``stc`` imports explicit. No more ``import *``.
|
|
||||||
|
|
||||||
Replaced use of the ``wx`` module's ``true`` and ``false`` with
|
|
||||||
Python's ``True`` and ``False``.
|
|
||||||
|
|
||||||
Changed ``introspect.getRoot()`` to use ``tokenize`` module. This
|
|
||||||
does a slightly better job than the previous parsing routine and the
|
|
||||||
code is clearer.
|
|
||||||
|
|
||||||
Improved handling of whitespace and empty types during introspection.
|
|
||||||
|
|
||||||
Fixed cut/copy clipboard problem under Linux. (Robin Dunn rocks!!!)
|
|
||||||
|
|
||||||
Added shell.about() which works like this::
|
|
||||||
|
|
||||||
>>> shell.about()
|
|
||||||
PyCrust Version: 0.8
|
|
||||||
Shell Revision: 1.80
|
|
||||||
Interpreter Revision: 1.15
|
|
||||||
Python Version: 2.2.2
|
|
||||||
wxPython Version: 2.3.3.1
|
|
||||||
Platform: linux2
|
|
||||||
|
|
||||||
Added copy plus and paste plus to shell menu.
|
|
||||||
|
|
||||||
Moved shell menu from ``shell.py`` to ``shellmenu.py``.
|
|
||||||
|
|
||||||
Added ``sys.stdin.readlines()`` support.
|
|
||||||
|
|
||||||
Added ``time.sleep()`` in ``readline()`` and ``OnIdle()`` event
|
|
||||||
handler to free up the CPU.
|
|
||||||
|
|
||||||
|
|
||||||
0.7.2 (2/22/2002 to 8/27/2002)
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
Tweaked ``getAttributeNames()`` to pick up a few more attributes::
|
|
||||||
|
|
||||||
'__bases__', '__class__', '__dict__', '__name__', 'func_closure',
|
|
||||||
'func_code', 'func_defaults', 'func_dict', 'func_doc',
|
|
||||||
'func_globals', 'func_name'
|
|
||||||
|
|
||||||
Added a tests directory and unit tests.
|
|
||||||
|
|
||||||
Improved support for empty types in the shell: ``[]``, ``()`` and
|
|
||||||
``{}`` as far as when call tips and autocompletion are available.
|
|
||||||
|
|
||||||
Added support for the other triple string - ``''''''``.
|
|
||||||
|
|
||||||
Refactored ``introspect.py`` to improve testability.
|
|
||||||
|
|
||||||
Improved call tips for unbound methods by leaving the "self"
|
|
||||||
parameter, since unbound methods require an instance be passed.
|
|
||||||
|
|
||||||
Fixed call tip bug where a tip was displayed when a "(" was typed
|
|
||||||
after an object that wasn't callable.
|
|
||||||
|
|
||||||
Fixed ``getAllAttributeNames`` when ``str(object)`` fails.
|
|
||||||
|
|
||||||
Added brace highlighting. (Thank you, Kevin Altis.)
|
|
||||||
|
|
||||||
Fixed problem displaying unicode objects in ``PyFilling``.
|
|
||||||
|
|
||||||
Changed how ``filling.py`` checks for expandable objects. Lists are
|
|
||||||
now expandable objects.
|
|
||||||
|
|
||||||
Made the key handling more robust when there is an active text
|
|
||||||
selection that includes text prior to the last primary prompt. Thanks
|
|
||||||
to Raul Cota for pointing this out.
|
|
||||||
|
|
||||||
Fixed wxSTC problem with brace highlighting and non-us keyboards.
|
|
||||||
(Thank you for the patch, Jean-Michel Fauth.)
|
|
||||||
|
|
||||||
Added ``busy = wxBusyCursor()`` to key points in ``shell`` and
|
|
||||||
``filling``.
|
|
||||||
|
|
||||||
Added ``OnCloseWindow`` handler to ``ShellFrame`` and ``CrustFrame``.
|
|
||||||
|
|
||||||
Default to ``SetWrapMode(1)`` for shell and namespace viewer.
|
|
||||||
|
|
||||||
Added ``shell.wrap()`` and ``shell.zoom()``.
|
|
||||||
|
|
||||||
Added autoCompleteKeys hooks for Raul Cota.
|
|
||||||
|
|
||||||
Cleaned up various little key handling bugs.
|
|
||||||
|
|
||||||
Changed input methods to get values from shell, rather than dialog
|
|
||||||
boxes. Renamed ``readIn`` to ``readline`` and ``readRaw`` to
|
|
||||||
``raw_input``.
|
|
||||||
|
|
||||||
|
|
||||||
0.7.1 (12/12/2001 to 2/21/2002)
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
Fixed ``OnChar()`` issues effecting European keyboards, as reported by
|
|
||||||
Jean-Michel Fauth.
|
|
||||||
|
|
||||||
Fixed ``introspect.py`` issue with xmlrpc objects reported by Kevin
|
|
||||||
Altis.
|
|
||||||
|
|
||||||
Fixed some introspect/PyFilling issues with regard to Python 2.2.
|
|
||||||
|
|
||||||
Fixed font background color as reported by Keith J. Farmer. (Thanks)
|
|
||||||
|
|
||||||
Fixed problem with call tips and autocompletion inside multiline
|
|
||||||
commands as report by Kevin Altis.
|
|
||||||
|
|
||||||
Improved ``OnKeyDown`` handling of cut/copy/paste operations based on
|
|
||||||
feedback from Syver Enstad. (Thanks)
|
|
||||||
|
|
||||||
Added a ``shell.help()`` method to display some help info.
|
|
||||||
|
|
||||||
Changed sort of items in the namespace viewer to case insensitive.
|
|
||||||
|
|
||||||
Changed ``attributes.sort(lambda x, y: cmp(x.upper(), y.upper()))`` in
|
|
||||||
advance of an upcoming fix to an autocompletion matching bug in wxSTC.
|
|
||||||
|
|
||||||
Improved support for ZODB by allowing namespace drilldown into BTrees.
|
|
||||||
|
|
||||||
Added ``shell.PasteAndRun()`` to support pasting multiple commands into
|
|
||||||
the shell from the clipboard. Ctrl+Shift+V or v.
|
|
||||||
|
|
||||||
Enter now always processes a command (or copies down a previous one.)
|
|
||||||
To insert a line break, press Ctrl+Enter.
|
|
||||||
|
|
||||||
Escape key clears the current, unexecuted command.
|
|
||||||
|
|
||||||
History retrieval changed to replace current command. Added new keys
|
|
||||||
to insert from history - Shift+Up and Shift+Down.
|
|
||||||
|
|
||||||
Better call tips on objects with ``__call__`` methods.
|
|
||||||
|
|
||||||
Improved call tip positioning calculation.
|
|
||||||
|
|
||||||
|
|
||||||
0.7 (10/15/2001 to 12/11/2001)
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
Changed how command history retrieval functions work. Added Alt-P,
|
|
||||||
Alt-N as keybindings for Retrieve-Previous, Retrieve-Next.
|
|
||||||
|
|
||||||
Added full support for multi-line commands, similar to IDLE.
|
|
||||||
|
|
||||||
Changed ``introspect.getAttributeNames()`` to do a case insensitive
|
|
||||||
sort.
|
|
||||||
|
|
||||||
Changed Cut/Copy/Paste to deal with prompts intelligently. Cut and
|
|
||||||
Copy remove all prompts. Paste can handle prompted or not-prompted
|
|
||||||
text.
|
|
||||||
|
|
||||||
Added ``CopyWithPrompts()`` method attached to Ctrl-Shift-C for those
|
|
||||||
times when you really do want all the prompts left intact.
|
|
||||||
|
|
||||||
Improved handling of the shell's read-only zone.
|
|
||||||
|
|
||||||
Changed ``CrustFrame.__init__`` parameter spec to include all
|
|
||||||
parameters allowed by a ``wxFrame``.
|
|
||||||
|
|
||||||
Changed ``FillingText`` to be read-only.
|
|
||||||
|
|
||||||
Renamed ``PyCrust.py`` to ``PyCrustApp.py`` to eliminate
|
|
||||||
package/module name conflicts that kept you from doing ``from PyCrust
|
|
||||||
import shell`` inside files located in the ``PyCrust`` directory.
|
|
||||||
|
|
||||||
Renamed ``PyFilling.py`` to ``PyFillingApp.py`` and ``PyShell.py`` to
|
|
||||||
``PyShellApp.py`` to maintain consistency.
|
|
||||||
|
|
||||||
Removed the ``__date__`` property from all modules.
|
|
||||||
|
|
||||||
Fixed bug in ``introspect.getCallTip()``, reported by Kevin Altis.
|
|
||||||
|
|
||||||
|
|
||||||
0.6.1 (9/19/2001 to 10/12/2001)
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
Changed ``Shell.run()`` to always position to the end of existing
|
|
||||||
text, as suggested by Raul Cota.
|
|
||||||
|
|
||||||
Changed ``introspect.getAllAttributeNames()`` to break circular
|
|
||||||
references in ``object.__class__``, which occurs in Zope/ZODB
|
|
||||||
extension classes.
|
|
||||||
|
|
||||||
Changed ``filling.FillingTree.getChildren()`` to introspect extension
|
|
||||||
classes.
|
|
||||||
|
|
||||||
Fixed minor bugs in ``introspect.getCallTip()`` that were interfering
|
|
||||||
with call tips for Zope/ZODB extension class methods.
|
|
||||||
|
|
||||||
In preparation for wxPython 2.3.2, added code to fix a font sizing
|
|
||||||
problem. Versions of wxPython prior to 2.3.2 had a sizing bug on Win
|
|
||||||
platform where the font was 2 points larger than what was specified.
|
|
||||||
|
|
||||||
Added a hack to ``introspect.getAllAttributeNames()`` to "wake up"
|
|
||||||
ZODB objects that are asleep - in a "ghost" state. Otherwise it
|
|
||||||
returns incomplete info.
|
|
||||||
|
|
||||||
|
|
||||||
0.6 (8/21/2001 to 9/12/2001)
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
Added ``PyFilling.py`` and ``filling.py``.
|
|
||||||
|
|
||||||
``PyShell.py`` and ``PyFilling.py`` can now be run standalone, as well
|
|
||||||
as ``PyCrust.py``.
|
|
||||||
|
|
||||||
Added ``crust.py`` and moved some code from ``PyCrust.py`` to it.
|
|
||||||
|
|
||||||
Added command history retrieval features submitted by Richie Hindle.
|
|
||||||
|
|
||||||
Changed ``shell.write()`` to replace line endings with OS-specific
|
|
||||||
endings. Changed ``shell.py`` and ``interpreter.py`` to use
|
|
||||||
``os.linesep`` in strings having hardcoded line endings.
|
|
||||||
|
|
||||||
Added ``shell.redirectStdin()``, ``shell.redirectStdout()`` and
|
|
||||||
``shell.redirectStderr()`` to allow the surrounding app to toggle
|
|
||||||
requests that the specified ``sys.std*`` be redirected to the shell.
|
|
||||||
These can also be run from within the shell itself, of course.
|
|
||||||
|
|
||||||
The shell now adds the current working directory "." to the search
|
|
||||||
path::
|
|
||||||
|
|
||||||
sys.path.insert(0, os.curdir)
|
|
||||||
|
|
||||||
Added support for distutils installations.
|
|
||||||
|
|
||||||
|
|
||||||
0.5.4 (8/17/2001 to 8/20/2001)
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
Changed default font size under Linux to::
|
|
||||||
|
|
||||||
'size' : 12,
|
|
||||||
'lnsize' : 10,
|
|
||||||
|
|
||||||
Changed ``Shell`` to expect a parameter referencing an Interpreter
|
|
||||||
class, rather than an intepreter instance, to facilitate subclassing
|
|
||||||
of Interpreter, which effectively broke when the Editor class was
|
|
||||||
eliminated.
|
|
||||||
|
|
||||||
Fixed ``PyCrustAlaCarte.py``, which had been broken by previous
|
|
||||||
changes.
|
|
||||||
|
|
||||||
Created ``InterpreterAlaCarte`` class as an example for use in the
|
|
||||||
demo.
|
|
||||||
|
|
||||||
Split ``PyCrust.py`` into ``PyCrust.py`` and ``PyShell.py`` in
|
|
||||||
anticipation of ``PyFilling.py``.
|
|
||||||
|
|
||||||
|
|
||||||
0.5.3 (8/16/2001)
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Added patch to ``PyCrust.py`` to fix wxPython bug::
|
|
||||||
|
|
||||||
wxID_SELECTALL = NewId() # This *should* be defined by wxPython.
|
|
||||||
|
|
||||||
|
|
||||||
0.5.2 (8/14/2001 to 8/15/2001)
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
Shortened module names by dropping "PyCrust" as a prefix.
|
|
||||||
|
|
||||||
Changed ``version`` to ``VERSION`` in ``version`` module.
|
|
||||||
|
|
||||||
Added Options menu to PyCrust application.
|
|
||||||
|
|
||||||
Eliminated the Editor class (and editor module) by merging with Shell.
|
|
||||||
This means that Shell "is a" wxStyledTextCtrl rather than "has a".
|
|
||||||
There just wasn't enough non-gui code to justify the separation.
|
|
||||||
Plus, Shell will be much easier for gui toolkits/designers to deal
|
|
||||||
with now.
|
|
||||||
|
|
||||||
|
|
||||||
0.5.1 (8/10/2001 to 8/14/2001)
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
Added ``introspect`` module.
|
|
||||||
|
|
||||||
Moved some functionality from ``PyCrustInterp`` to ``introspect``.
|
|
||||||
|
|
||||||
Changed ``introspect.getRoot()`` to no longer remove whitespace from
|
|
||||||
the command. This was a remnant of a previous approach that, when
|
|
||||||
left as part of the current approach, turned out to be a really bad
|
|
||||||
thing.
|
|
||||||
|
|
||||||
Changed ``introspect.getRoot()`` to allow commands of ``''``, ``""``,
|
|
||||||
``""""""``, ``[]``, ``()``, and ``{}`` to pass through. This allows
|
|
||||||
you to type them, followed by a dot, and get autocomplete options on
|
|
||||||
them.
|
|
||||||
|
|
||||||
Changed ``introspect.getRoot()`` to identify some situations where
|
|
||||||
strings shouldn't be considered roots. For example::
|
|
||||||
|
|
||||||
>>> import PyCrust # To illustrate the potential problem.
|
|
||||||
>>> len('PyCrust.py')
|
|
||||||
|
|
||||||
Typing the dot at the end of "PyCrust" in the second line above should
|
|
||||||
NOT result in an autocompletion list because "PyCrust" is part of a
|
|
||||||
string in this context, not a reference to the PyCrust module object.
|
|
||||||
Similar reasoning applies to call tips. For example::
|
|
||||||
|
|
||||||
>>> len('dir(')
|
|
||||||
|
|
||||||
Typing the left paren at the end of "dir" should NOT result in a call
|
|
||||||
tip.
|
|
||||||
|
|
||||||
Both features now behave properly in the examples given. However,
|
|
||||||
there is still the case where whitespace precedes the potential root
|
|
||||||
and that is NOT handled properly. For example::
|
|
||||||
|
|
||||||
>>> len('this is a dir(')
|
|
||||||
|
|
||||||
and::
|
|
||||||
|
|
||||||
>>> len('This is PyCrust.py')
|
|
||||||
|
|
||||||
More code needs to be written to handle more complex situations.
|
|
||||||
|
|
||||||
Added ``locals=None`` parameter to ``Shell.__init__()``.
|
|
||||||
|
|
||||||
Added support for magic attribute retrieval. Users can change this
|
|
||||||
with::
|
|
||||||
|
|
||||||
>>> shell.editor.autoCompleteIncludeMagic = 0
|
|
||||||
|
|
||||||
Added the ability to set filters on auto completion to exclude
|
|
||||||
attributes prefixed with a single or double underscore. Users can
|
|
||||||
exclude one or the other or both with::
|
|
||||||
|
|
||||||
>>> shell.editor.autoCompleteExcludeSingle = 1
|
|
||||||
>>> shell.editor.autoCompleteExcludeDouble = 1
|
|
||||||
|
|
||||||
|
|
||||||
0.5 (8/8/2001)
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Mostly just a final version change before creating a release.
|
|
||||||
|
|
||||||
|
|
||||||
0.4 (8/4/2001 to 8/7/2001)
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Changed version/revision handling.
|
|
||||||
|
|
||||||
Fixed bugs.
|
|
||||||
|
|
||||||
|
|
||||||
0.3 (8/2/2001 to 8/3/2001)
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Removed lots of cruft.
|
|
||||||
|
|
||||||
Added lots of docstrings.
|
|
||||||
|
|
||||||
Imported to CVS repository at SourceForge.
|
|
||||||
|
|
||||||
Added call tips.
|
|
||||||
|
|
||||||
|
|
||||||
0.2 (7/30/2001 to 8/2/2001)
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
Renamed several files.
|
|
||||||
|
|
||||||
Added command autocompletion.
|
|
||||||
|
|
||||||
Added menus to PyCrust.py: File, Edit and Help.
|
|
||||||
|
|
||||||
Added sample applications: ``PyCrustAlaCarte.py``,
|
|
||||||
``PyCrustAlaMode.py``, and ``PyCrustMinimus.py``.
|
|
||||||
|
|
||||||
|
|
||||||
0.1 (7/1/2001 to 7/19/2001)
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
Added basic syntax coloring much like Boa.
|
|
||||||
|
|
||||||
Added read-only logging much like IDLE.
|
|
||||||
|
|
||||||
Can retrieve a previous command by putting the cursor back on that
|
|
||||||
line and hitting enter.
|
|
||||||
|
|
||||||
Stdin and raw_input operate properly so you can now do ``help()`` and
|
|
||||||
``license()`` without hanging.
|
|
||||||
|
|
||||||
Redefined "quit", "exit", and "close" to display a better-than-nothing
|
|
||||||
response.
|
|
||||||
|
|
||||||
Home key honors the prompt.
|
|
||||||
|
|
||||||
Created SourceForge account, but nothing was posted.
|
|
||||||
|
|
||||||
|
|
||||||
In the beginning, there was pie... (7/1/2001)
|
|
||||||
---------------------------------------------
|
|
||||||
|
|
||||||
Blame it all on IDLE, Boa and PythonWin. I was using all three, got
|
|
||||||
frustrated with their dissimilarities, and began to let everyone know
|
|
||||||
how I felt. At the same time, Scintilla looked like an interesting
|
|
||||||
tool to build a shell around. And while I didn't receive much in the
|
|
||||||
way of positive feedback, let alone encouragement, I just couldn't let
|
|
||||||
go of the idea of a Scintilla-based Python shell. Then the PythonCard
|
|
||||||
project got to the point where they were talking about including a
|
|
||||||
shell in their development environment. That was all the incentive I
|
|
||||||
needed. PyCrust had to happen...
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.6 KiB |
@@ -1,36 +0,0 @@
|
|||||||
"""PyAlaCarte is a simple programmer's editor."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
from wx import py
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
class App(wx.App):
|
|
||||||
"""PyAlaCarte standalone application."""
|
|
||||||
|
|
||||||
def __init__(self, filename=None):
|
|
||||||
self.filename = filename
|
|
||||||
wx.App.__init__(self, redirect=False)
|
|
||||||
|
|
||||||
def OnInit(self):
|
|
||||||
wx.InitAllImageHandlers()
|
|
||||||
self.frame = py.editor.EditorFrame(filename=self.filename)
|
|
||||||
self.frame.Show()
|
|
||||||
self.SetTopWindow(self.frame)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def main(filename=None):
|
|
||||||
if not filename and len(sys.argv) > 1:
|
|
||||||
filename = sys.argv[1]
|
|
||||||
if filename:
|
|
||||||
filename = os.path.realpath(filename)
|
|
||||||
app = App(filename)
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@@ -1,36 +0,0 @@
|
|||||||
"""PyAlaMode is a programmer's editor."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
from wx import py
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
class App(wx.App):
|
|
||||||
"""PyAlaMode standalone application."""
|
|
||||||
|
|
||||||
def __init__(self, filename=None):
|
|
||||||
self.filename = filename
|
|
||||||
wx.App.__init__(self, redirect=False)
|
|
||||||
|
|
||||||
def OnInit(self):
|
|
||||||
wx.InitAllImageHandlers()
|
|
||||||
self.frame = py.editor.EditorNotebookFrame(filename=self.filename)
|
|
||||||
self.frame.Show()
|
|
||||||
self.SetTopWindow(self.frame)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def main(filename=None):
|
|
||||||
if not filename and len(sys.argv) > 1:
|
|
||||||
filename = sys.argv[1]
|
|
||||||
if filename:
|
|
||||||
filename = os.path.realpath(filename)
|
|
||||||
app = App(filename)
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@@ -1,35 +0,0 @@
|
|||||||
"""PyAlaModeTest is a programmer's editor."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
from wx import py
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
class App(wx.App):
|
|
||||||
"""PyAlaModeTest standalone application."""
|
|
||||||
|
|
||||||
def __init__(self, filename=None):
|
|
||||||
self.filename = filename
|
|
||||||
wx.App.__init__(self, redirect=False)
|
|
||||||
|
|
||||||
def OnInit(self):
|
|
||||||
wx.InitAllImageHandlers()
|
|
||||||
self.frame = py.editor.EditorShellNotebookFrame(filename=self.filename)
|
|
||||||
self.frame.Show()
|
|
||||||
self.SetTopWindow(self.frame)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def main(filename=None):
|
|
||||||
app = App(filename)
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
filename = None
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
filename = os.path.realpath(sys.argv[1])
|
|
||||||
main(filename)
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.6 KiB |
@@ -1,70 +0,0 @@
|
|||||||
"""PyCrust is a python shell and namespace browser application."""
|
|
||||||
|
|
||||||
# The next two lines, and the other code below that makes use of
|
|
||||||
# ``__main__`` and ``original``, serve the purpose of cleaning up the
|
|
||||||
# main namespace to look as much as possible like the regular Python
|
|
||||||
# shell environment.
|
|
||||||
import __main__
|
|
||||||
original = __main__.__dict__.keys()
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
|
|
||||||
class App(wx.App):
|
|
||||||
"""PyCrust standalone application."""
|
|
||||||
|
|
||||||
def OnInit(self):
|
|
||||||
import wx
|
|
||||||
from wx import py
|
|
||||||
wx.InitAllImageHandlers()
|
|
||||||
self.frame = py.crust.CrustFrame()
|
|
||||||
self.frame.SetSize((800, 600))
|
|
||||||
self.frame.Show()
|
|
||||||
self.SetTopWindow(self.frame)
|
|
||||||
return True
|
|
||||||
|
|
||||||
'''
|
|
||||||
The main() function needs to handle being imported, such as with the
|
|
||||||
pycrust script that wxPython installs:
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from wx.py.PyCrust import main
|
|
||||||
main()
|
|
||||||
'''
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""The main function for the PyCrust program."""
|
|
||||||
# Cleanup the main namespace, leaving the App class.
|
|
||||||
import __main__
|
|
||||||
md = __main__.__dict__
|
|
||||||
keepers = original
|
|
||||||
keepers.append('App')
|
|
||||||
for key in md.keys():
|
|
||||||
if key not in keepers:
|
|
||||||
del md[key]
|
|
||||||
# Create an application instance.
|
|
||||||
app = App(0)
|
|
||||||
# Mimic the contents of the standard Python shell's sys.path.
|
|
||||||
import sys
|
|
||||||
if sys.path[0]:
|
|
||||||
sys.path[0] = ''
|
|
||||||
# Add the application object to the sys module's namespace.
|
|
||||||
# This allows a shell user to do:
|
|
||||||
# >>> import sys
|
|
||||||
# >>> sys.app.whatever
|
|
||||||
sys.app = app
|
|
||||||
del sys
|
|
||||||
# Cleanup the main namespace some more.
|
|
||||||
if md.has_key('App') and md['App'] is App:
|
|
||||||
del md['App']
|
|
||||||
if md.has_key('__main__') and md['__main__'] is __main__:
|
|
||||||
del md['__main__']
|
|
||||||
# Start the wxPython event loop.
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
Binary file not shown.
Before Width: | Height: | Size: 706 B |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,35 +0,0 @@
|
|||||||
"""PyFilling is a python namespace inspection application."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
# We use this object to get more introspection when run standalone.
|
|
||||||
app = None
|
|
||||||
|
|
||||||
import filling
|
|
||||||
|
|
||||||
# These are imported just to have something interesting to inspect.
|
|
||||||
import crust
|
|
||||||
import interpreter
|
|
||||||
import introspect
|
|
||||||
import pseudo
|
|
||||||
import shell
|
|
||||||
import sys
|
|
||||||
import wx
|
|
||||||
|
|
||||||
class App(filling.App):
|
|
||||||
def OnInit(self):
|
|
||||||
filling.App.OnInit(self)
|
|
||||||
self.root = self.fillingFrame.filling.tree.root
|
|
||||||
return True
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Create and run the application."""
|
|
||||||
global app
|
|
||||||
app = App(0)
|
|
||||||
app.fillingFrame.filling.tree.Expand(app.root)
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@@ -1,71 +0,0 @@
|
|||||||
"""PyShell is a python shell application."""
|
|
||||||
|
|
||||||
# The next two lines, and the other code below that makes use of
|
|
||||||
# ``__main__`` and ``original``, serve the purpose of cleaning up the
|
|
||||||
# main namespace to look as much as possible like the regular Python
|
|
||||||
# shell environment.
|
|
||||||
import __main__
|
|
||||||
original = __main__.__dict__.keys()
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
|
|
||||||
class App(wx.App):
|
|
||||||
"""PyShell standalone application."""
|
|
||||||
|
|
||||||
def OnInit(self):
|
|
||||||
import wx
|
|
||||||
from wx import py
|
|
||||||
wx.InitAllImageHandlers()
|
|
||||||
self.frame = py.shell.ShellFrame()
|
|
||||||
self.frame.SetSize((750, 525))
|
|
||||||
self.frame.Show()
|
|
||||||
self.SetTopWindow(self.frame)
|
|
||||||
self.frame.shell.SetFocus()
|
|
||||||
return True
|
|
||||||
|
|
||||||
'''
|
|
||||||
The main() function needs to handle being imported, such as with the
|
|
||||||
pyshell script that wxPython installs:
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from wx.py.PyShell import main
|
|
||||||
main()
|
|
||||||
'''
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""The main function for the PyShell program."""
|
|
||||||
# Cleanup the main namespace, leaving the App class.
|
|
||||||
import __main__
|
|
||||||
md = __main__.__dict__
|
|
||||||
keepers = original
|
|
||||||
keepers.append('App')
|
|
||||||
for key in md.keys():
|
|
||||||
if key not in keepers:
|
|
||||||
del md[key]
|
|
||||||
# Create an application instance.
|
|
||||||
app = App(0)
|
|
||||||
# Cleanup the main namespace some more.
|
|
||||||
if md.has_key('App') and md['App'] is App:
|
|
||||||
del md['App']
|
|
||||||
if md.has_key('__main__') and md['__main__'] is __main__:
|
|
||||||
del md['__main__']
|
|
||||||
# Mimic the contents of the standard Python shell's sys.path.
|
|
||||||
import sys
|
|
||||||
if sys.path[0]:
|
|
||||||
sys.path[0] = ''
|
|
||||||
# Add the application object to the sys module's namespace.
|
|
||||||
# This allows a shell user to do:
|
|
||||||
# >>> import sys
|
|
||||||
# >>> sys.app.whatever
|
|
||||||
sys.app = app
|
|
||||||
del sys
|
|
||||||
# Start the wxPython event loop.
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@@ -1,48 +0,0 @@
|
|||||||
"""PyWrap is a command line utility that runs a wxPython program with
|
|
||||||
additional runtime-tools, such as PyCrust."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
from wx import py
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def wrap(app):
|
|
||||||
wx.InitAllImageHandlers()
|
|
||||||
frame = py.crust.CrustFrame()
|
|
||||||
frame.SetSize((750, 525))
|
|
||||||
frame.Show(True)
|
|
||||||
frame.shell.interp.locals['app'] = app
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
def main(modulename=None):
|
|
||||||
sys.path.insert(0, os.curdir)
|
|
||||||
if not modulename:
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
print "Please specify a module name."
|
|
||||||
raise SystemExit
|
|
||||||
modulename = sys.argv[1]
|
|
||||||
if modulename.endswith('.py'):
|
|
||||||
modulename = modulename[:-3]
|
|
||||||
module = __import__(modulename)
|
|
||||||
# Find the App class.
|
|
||||||
App = None
|
|
||||||
d = module.__dict__
|
|
||||||
for item in d.keys():
|
|
||||||
try:
|
|
||||||
if issubclass(d[item], wx.App):
|
|
||||||
App = d[item]
|
|
||||||
except (NameError, TypeError):
|
|
||||||
pass
|
|
||||||
if App is None:
|
|
||||||
print "No App class was found."
|
|
||||||
raise SystemExit
|
|
||||||
app = App()
|
|
||||||
wrap(app)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@@ -1,83 +0,0 @@
|
|||||||
=====================================
|
|
||||||
PyCrust - The Flakiest Python Shell
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
Half-baked by Patrick K. O'Brien (pobrien@orbtech.com)
|
|
||||||
|
|
||||||
Orbtech - "Your source for Python programming expertise."
|
|
||||||
Sample all our half-baked Python goods at www.orbtech.com.
|
|
||||||
|
|
||||||
|
|
||||||
What is PyCrust?
|
|
||||||
----------------
|
|
||||||
|
|
||||||
PyCrust is an interactive Python environment written in Python.
|
|
||||||
PyCrust components can run standalone or be integrated into other
|
|
||||||
development environments and/or other Python applications.
|
|
||||||
|
|
||||||
PyCrust comes with an interactive Python shell (PyShell), an
|
|
||||||
interactive namespace/object tree control (PyFilling) and an
|
|
||||||
integrated, split-window combination of the two (PyCrust).
|
|
||||||
|
|
||||||
|
|
||||||
What is PyCrust good for?
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Have you ever tried to bake a pie without one? Well, you shouldn't
|
|
||||||
build a Python program without a PyCrust either.
|
|
||||||
|
|
||||||
|
|
||||||
What else do I need to use PyCrust?
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
PyCrust requires Python 2.2 or later, and wxPython 2.4 or later.
|
|
||||||
PyCrust uses wxPython and the Scintilla wrapper (wxStyledTextCtrl).
|
|
||||||
Python is available at http://www.python.org/. wxPython is available
|
|
||||||
at http://www.wxpython.org/.
|
|
||||||
|
|
||||||
|
|
||||||
Where can I get the latest version of PyCrust?
|
|
||||||
----------------------------------------------
|
|
||||||
|
|
||||||
The latest production version ships with wxPython. The latest
|
|
||||||
developer version is available in the wxWindows CVS at:
|
|
||||||
http://cvs.wxwindows.org/viewcvs.cgi/
|
|
||||||
|
|
||||||
|
|
||||||
Where is the PyCrust project hosted?
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
The old answer was "At SourceForge, of course." The SourceForge
|
|
||||||
summary page is still available at:
|
|
||||||
http://sourceforge.net/projects/pycrust/
|
|
||||||
|
|
||||||
The new answer is that there is no longer a need for a separate
|
|
||||||
project. Simply install wxPython and you'll have everything you need.
|
|
||||||
|
|
||||||
|
|
||||||
I found a bug in PyCrust, what do I do with it?
|
|
||||||
-----------------------------------------------
|
|
||||||
|
|
||||||
You can send it to me at pobrien@orbtech.com.
|
|
||||||
|
|
||||||
|
|
||||||
I want a new feature added to PyCrust. Will you do it?
|
|
||||||
------------------------------------------------------
|
|
||||||
|
|
||||||
Flattery and money will get you anything. Short of that, you can send
|
|
||||||
me a request and I'll see what I can do.
|
|
||||||
|
|
||||||
|
|
||||||
Does PyCrust have a mailing list full of wonderful people?
|
|
||||||
----------------------------------------------------------
|
|
||||||
|
|
||||||
As a matter of fact, we do. Join the PyCrust mailing lists at:
|
|
||||||
http://sourceforge.net/mail/?group_id=31263
|
|
||||||
|
|
||||||
|
|
||||||
What is the CVS information for this README file?
|
|
||||||
-------------------------------------------------
|
|
||||||
|
|
||||||
$Date$
|
|
||||||
$Revision$
|
|
||||||
$Id$
|
|
@@ -1,20 +0,0 @@
|
|||||||
"""The py package, formerly the PyCrust package."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import buffer
|
|
||||||
import crust
|
|
||||||
import dispatcher
|
|
||||||
import document
|
|
||||||
import editor
|
|
||||||
import editwindow
|
|
||||||
import filling
|
|
||||||
import frame
|
|
||||||
import images
|
|
||||||
import interpreter
|
|
||||||
import introspect
|
|
||||||
import pseudo
|
|
||||||
import shell
|
|
||||||
import version
|
|
@@ -1,138 +0,0 @@
|
|||||||
"""Buffer class."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
from interpreter import Interpreter
|
|
||||||
import imp
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import document
|
|
||||||
|
|
||||||
|
|
||||||
class Buffer:
|
|
||||||
"""Buffer class."""
|
|
||||||
|
|
||||||
id = 0
|
|
||||||
|
|
||||||
def __init__(self, filename=None):
|
|
||||||
"""Create a Buffer instance."""
|
|
||||||
Buffer.id += 1
|
|
||||||
self.id = Buffer.id
|
|
||||||
self.interp = Interpreter(locals={})
|
|
||||||
self.name = ''
|
|
||||||
self.editors = {}
|
|
||||||
self.editor = None
|
|
||||||
self.modules = sys.modules.keys()
|
|
||||||
self.syspath = sys.path[:]
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
self.syspath.remove('')
|
|
||||||
except ValueError:
|
|
||||||
break
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
self.syspath.remove('.')
|
|
||||||
except ValueError:
|
|
||||||
break
|
|
||||||
self.open(filename)
|
|
||||||
|
|
||||||
def addEditor(self, editor):
|
|
||||||
"""Add an editor."""
|
|
||||||
self.editor = editor
|
|
||||||
self.editors[editor.id] = editor
|
|
||||||
|
|
||||||
def hasChanged(self):
|
|
||||||
"""Return True if text in editor has changed since last save."""
|
|
||||||
if self.editor:
|
|
||||||
return self.editor.hasChanged()
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def new(self, filepath):
|
|
||||||
"""New empty buffer."""
|
|
||||||
if not filepath:
|
|
||||||
return
|
|
||||||
if os.path.exists(filepath):
|
|
||||||
self.confirmed = self.overwriteConfirm(filepath)
|
|
||||||
else:
|
|
||||||
self.confirmed = True
|
|
||||||
|
|
||||||
def open(self, filename):
|
|
||||||
"""Open file into buffer."""
|
|
||||||
self.doc = document.Document(filename)
|
|
||||||
self.name = self.doc.filename or ('Untitled:' + str(self.id))
|
|
||||||
self.modulename = self.doc.filebase
|
|
||||||
# XXX This should really make sure filedir is first item in syspath.
|
|
||||||
# XXX Or maybe this should be moved to the update namespace method.
|
|
||||||
if self.doc.filedir and self.doc.filedir not in self.syspath:
|
|
||||||
# To create the proper context for updateNamespace.
|
|
||||||
self.syspath.insert(0, self.doc.filedir)
|
|
||||||
if self.doc.filepath and os.path.exists(self.doc.filepath):
|
|
||||||
self.confirmed = True
|
|
||||||
if self.editor:
|
|
||||||
text = self.doc.read()
|
|
||||||
self.editor._setBuffer(buffer=self, text=text)
|
|
||||||
|
|
||||||
def overwriteConfirm(filepath):
|
|
||||||
"""Confirm overwriting an existing file."""
|
|
||||||
return False
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
"""Save buffer."""
|
|
||||||
filepath = self.doc.filepath
|
|
||||||
if not filepath:
|
|
||||||
return # XXX Get filename
|
|
||||||
if not os.path.exists(filepath):
|
|
||||||
self.confirmed = True
|
|
||||||
if not self.confirmed:
|
|
||||||
self.confirmed = self.overwriteConfirm(filepath)
|
|
||||||
if self.confirmed:
|
|
||||||
self.doc.write(self.editor.getText())
|
|
||||||
if self.editor:
|
|
||||||
self.editor.setSavePoint()
|
|
||||||
|
|
||||||
def saveAs(self, filename):
|
|
||||||
"""Save buffer."""
|
|
||||||
self.doc = document.Document(filename)
|
|
||||||
self.name = self.doc.filename
|
|
||||||
self.modulename = self.doc.filebase
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
def updateNamespace(self):
|
|
||||||
"""Update the namespace for autocompletion and calltips.
|
|
||||||
|
|
||||||
Return True if updated, False if there was an error."""
|
|
||||||
if not self.interp or not hasattr(self.editor, 'getText'):
|
|
||||||
return False
|
|
||||||
syspath = sys.path
|
|
||||||
sys.path = self.syspath
|
|
||||||
text = self.editor.getText()
|
|
||||||
text = text.replace('\r\n', '\n')
|
|
||||||
text = text.replace('\r', '\n')
|
|
||||||
name = self.modulename or self.name
|
|
||||||
module = imp.new_module(name)
|
|
||||||
newspace = module.__dict__.copy()
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
code = compile(text, name, 'exec')
|
|
||||||
except:
|
|
||||||
raise
|
|
||||||
# return False
|
|
||||||
try:
|
|
||||||
exec code in newspace
|
|
||||||
except:
|
|
||||||
raise
|
|
||||||
# return False
|
|
||||||
else:
|
|
||||||
# No problems, so update the namespace.
|
|
||||||
self.interp.locals.clear()
|
|
||||||
self.interp.locals.update(newspace)
|
|
||||||
return True
|
|
||||||
finally:
|
|
||||||
sys.path = syspath
|
|
||||||
for m in sys.modules.keys():
|
|
||||||
if m not in self.modules:
|
|
||||||
del sys.modules[m]
|
|
@@ -1,218 +0,0 @@
|
|||||||
"""Crust combines the shell and filling into one control."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
|
|
||||||
import os
|
|
||||||
import pprint
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import dispatcher
|
|
||||||
import editwindow
|
|
||||||
from filling import Filling
|
|
||||||
import frame
|
|
||||||
from shell import Shell
|
|
||||||
from version import VERSION
|
|
||||||
|
|
||||||
|
|
||||||
class Crust(wx.SplitterWindow):
|
|
||||||
"""Crust based on SplitterWindow."""
|
|
||||||
|
|
||||||
name = 'Crust'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
|
||||||
size=wx.DefaultSize, style=wx.SP_3D,
|
|
||||||
name='Crust Window', rootObject=None, rootLabel=None,
|
|
||||||
rootIsNamespace=True, intro='', locals=None,
|
|
||||||
InterpClass=None, *args, **kwds):
|
|
||||||
"""Create Crust instance."""
|
|
||||||
wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
|
||||||
self.shell = Shell(parent=self, introText=intro,
|
|
||||||
locals=locals, InterpClass=InterpClass,
|
|
||||||
*args, **kwds)
|
|
||||||
self.editor = self.shell
|
|
||||||
if rootObject is None:
|
|
||||||
rootObject = self.shell.interp.locals
|
|
||||||
self.notebook = wx.Notebook(parent=self, id=-1)
|
|
||||||
self.shell.interp.locals['notebook'] = self.notebook
|
|
||||||
self.filling = Filling(parent=self.notebook,
|
|
||||||
rootObject=rootObject,
|
|
||||||
rootLabel=rootLabel,
|
|
||||||
rootIsNamespace=rootIsNamespace)
|
|
||||||
# Add 'filling' to the interpreter's locals.
|
|
||||||
self.shell.interp.locals['filling'] = self.filling
|
|
||||||
self.notebook.AddPage(page=self.filling, text='Namespace', select=True)
|
|
||||||
self.display = Display(parent=self.notebook)
|
|
||||||
self.notebook.AddPage(page=self.display, text='Display')
|
|
||||||
# Add 'pp' (pretty print) to the interpreter's locals.
|
|
||||||
self.shell.interp.locals['pp'] = self.display.setItem
|
|
||||||
self.calltip = Calltip(parent=self.notebook)
|
|
||||||
self.notebook.AddPage(page=self.calltip, text='Calltip')
|
|
||||||
self.sessionlisting = SessionListing(parent=self.notebook)
|
|
||||||
self.notebook.AddPage(page=self.sessionlisting, text='Session')
|
|
||||||
self.dispatcherlisting = DispatcherListing(parent=self.notebook)
|
|
||||||
self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher')
|
|
||||||
## from wxd import wx_
|
|
||||||
## self.wxdocs = Filling(parent=self.notebook,
|
|
||||||
## rootObject=wx_,
|
|
||||||
## rootLabel='wx',
|
|
||||||
## rootIsNamespace=False,
|
|
||||||
## static=True)
|
|
||||||
## self.notebook.AddPage(page=self.wxdocs, text='wxPython Docs')
|
|
||||||
## from wxd import stc_
|
|
||||||
## self.stcdocs = Filling(parent=self.notebook,
|
|
||||||
## rootObject=stc_.StyledTextCtrl,
|
|
||||||
## rootLabel='StyledTextCtrl',
|
|
||||||
## rootIsNamespace=False,
|
|
||||||
## static=True)
|
|
||||||
## self.notebook.AddPage(page=self.stcdocs, text='StyledTextCtrl Docs')
|
|
||||||
self.SplitHorizontally(self.shell, self.notebook, 300)
|
|
||||||
self.SetMinimumPaneSize(1)
|
|
||||||
|
|
||||||
|
|
||||||
class Display(editwindow.EditWindow):
|
|
||||||
"""STC used to display an object using Pretty Print."""
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
|
||||||
size=wx.DefaultSize,
|
|
||||||
style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER,
|
|
||||||
static=False):
|
|
||||||
"""Create Display instance."""
|
|
||||||
editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
|
|
||||||
# Configure various defaults and user preferences.
|
|
||||||
self.SetReadOnly(True)
|
|
||||||
self.SetWrapMode(False)
|
|
||||||
if not static:
|
|
||||||
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
|
||||||
|
|
||||||
def push(self, command, more):
|
|
||||||
"""Receiver for Interpreter.push signal."""
|
|
||||||
self.Refresh()
|
|
||||||
|
|
||||||
def Refresh(self):
|
|
||||||
if not hasattr(self, "item"):
|
|
||||||
return
|
|
||||||
self.SetReadOnly(False)
|
|
||||||
text = pprint.pformat(self.item)
|
|
||||||
self.SetText(text)
|
|
||||||
self.SetReadOnly(True)
|
|
||||||
|
|
||||||
def setItem(self, item):
|
|
||||||
"""Set item to pretty print in the notebook Display tab."""
|
|
||||||
self.item = item
|
|
||||||
self.Refresh()
|
|
||||||
|
|
||||||
|
|
||||||
class Calltip(wx.TextCtrl):
|
|
||||||
"""Text control containing the most recent shell calltip."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1):
|
|
||||||
style = (wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2)
|
|
||||||
wx.TextCtrl.__init__(self, parent, id, style=style)
|
|
||||||
self.SetBackgroundColour(wx.Colour(255, 255, 232))
|
|
||||||
dispatcher.connect(receiver=self.display, signal='Shell.calltip')
|
|
||||||
|
|
||||||
def display(self, calltip):
|
|
||||||
"""Receiver for Shell.calltip signal."""
|
|
||||||
## self.SetValue(calltip) # Caused refresh problem on Windows.
|
|
||||||
self.Clear()
|
|
||||||
self.AppendText(calltip)
|
|
||||||
|
|
||||||
|
|
||||||
class SessionListing(wx.TextCtrl):
|
|
||||||
"""Text control containing all commands for session."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1):
|
|
||||||
style = (wx.TE_MULTILINE | wx.TE_READONLY |
|
|
||||||
wx.TE_RICH2 | wx.TE_DONTWRAP)
|
|
||||||
wx.TextCtrl.__init__(self, parent, id, style=style)
|
|
||||||
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
|
||||||
|
|
||||||
def push(self, command, more):
|
|
||||||
"""Receiver for Interpreter.push signal."""
|
|
||||||
if command and not more:
|
|
||||||
self.SetInsertionPointEnd()
|
|
||||||
start, end = self.GetSelection()
|
|
||||||
if start != end:
|
|
||||||
self.SetSelection(0, 0)
|
|
||||||
self.AppendText(command + '\n')
|
|
||||||
|
|
||||||
|
|
||||||
class DispatcherListing(wx.TextCtrl):
|
|
||||||
"""Text control containing all dispatches for session."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1):
|
|
||||||
style = (wx.TE_MULTILINE | wx.TE_READONLY |
|
|
||||||
wx.TE_RICH2 | wx.TE_DONTWRAP)
|
|
||||||
wx.TextCtrl.__init__(self, parent, id, style=style)
|
|
||||||
dispatcher.connect(receiver=self.spy)
|
|
||||||
|
|
||||||
def spy(self, signal, sender):
|
|
||||||
"""Receiver for Any signal from Any sender."""
|
|
||||||
text = '%r from %s' % (signal, sender)
|
|
||||||
self.SetInsertionPointEnd()
|
|
||||||
start, end = self.GetSelection()
|
|
||||||
if start != end:
|
|
||||||
self.SetSelection(0, 0)
|
|
||||||
self.AppendText(text + '\n')
|
|
||||||
|
|
||||||
|
|
||||||
class CrustFrame(frame.Frame):
|
|
||||||
"""Frame containing all the PyCrust components."""
|
|
||||||
|
|
||||||
name = 'CrustFrame'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyCrust',
|
|
||||||
pos=wx.DefaultPosition, size=wx.DefaultSize,
|
|
||||||
style=wx.DEFAULT_FRAME_STYLE,
|
|
||||||
rootObject=None, rootLabel=None, rootIsNamespace=True,
|
|
||||||
locals=None, InterpClass=None, *args, **kwds):
|
|
||||||
"""Create CrustFrame instance."""
|
|
||||||
frame.Frame.__init__(self, parent, id, title, pos, size, style)
|
|
||||||
intro = 'PyCrust %s - The Flakiest Python Shell' % VERSION
|
|
||||||
intro += '\nSponsored by Orbtech - '
|
|
||||||
intro += 'Your source for Python programming expertise.'
|
|
||||||
self.SetStatusText(intro.replace('\n', ', '))
|
|
||||||
self.crust = Crust(parent=self, intro=intro,
|
|
||||||
rootObject=rootObject,
|
|
||||||
rootLabel=rootLabel,
|
|
||||||
rootIsNamespace=rootIsNamespace,
|
|
||||||
locals=locals,
|
|
||||||
InterpClass=InterpClass, *args, **kwds)
|
|
||||||
self.shell = self.crust.shell
|
|
||||||
# Override the filling so that status messages go to the status bar.
|
|
||||||
self.crust.filling.tree.setStatusText = self.SetStatusText
|
|
||||||
# Override the shell so that status messages go to the status bar.
|
|
||||||
self.shell.setStatusText = self.SetStatusText
|
|
||||||
# Fix a problem with the sash shrinking to nothing.
|
|
||||||
self.crust.filling.SetSashPosition(200)
|
|
||||||
# Set focus to the shell editor.
|
|
||||||
self.shell.SetFocus()
|
|
||||||
|
|
||||||
def OnClose(self, event):
|
|
||||||
"""Event handler for closing."""
|
|
||||||
self.crust.shell.destroy()
|
|
||||||
self.Destroy()
|
|
||||||
|
|
||||||
def OnAbout(self, event):
|
|
||||||
"""Display an About window."""
|
|
||||||
title = 'About PyCrust'
|
|
||||||
text = 'PyCrust %s\n\n' % VERSION + \
|
|
||||||
'Yet another Python shell, only flakier.\n\n' + \
|
|
||||||
'Half-baked by Patrick K. O\'Brien,\n' + \
|
|
||||||
'the other half is still in the oven.\n\n' + \
|
|
||||||
'Shell Revision: %s\n' % self.shell.revision + \
|
|
||||||
'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
|
|
||||||
'Platform: %s\n' % sys.platform + \
|
|
||||||
'Python Version: %s\n' % sys.version.split()[0] + \
|
|
||||||
'wxPython Version: %s\n' % wx.VERSION_STRING + \
|
|
||||||
('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:]))
|
|
||||||
dialog = wx.MessageDialog(self, text, title,
|
|
||||||
wx.OK | wx.ICON_INFORMATION)
|
|
||||||
dialog.ShowModal()
|
|
||||||
dialog.Destroy()
|
|
@@ -1,260 +0,0 @@
|
|||||||
"""Provides global signal dispatching services."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import exceptions
|
|
||||||
import types
|
|
||||||
import weakref
|
|
||||||
|
|
||||||
|
|
||||||
class DispatcherError(exceptions.Exception):
|
|
||||||
def __init__(self, args=None):
|
|
||||||
self.args = args
|
|
||||||
|
|
||||||
|
|
||||||
class Parameter:
|
|
||||||
"""Used to represent default parameter values."""
|
|
||||||
def __repr__(self):
|
|
||||||
return self.__class__.__name__
|
|
||||||
|
|
||||||
class Any(Parameter): pass
|
|
||||||
Any = Any()
|
|
||||||
|
|
||||||
class Anonymous(Parameter): pass
|
|
||||||
Anonymous = Anonymous()
|
|
||||||
|
|
||||||
|
|
||||||
connections = {}
|
|
||||||
senders = {}
|
|
||||||
_boundMethods = weakref.WeakKeyDictionary()
|
|
||||||
|
|
||||||
|
|
||||||
def connect(receiver, signal=Any, sender=Any, weak=True):
|
|
||||||
"""Connect receiver to sender for signal.
|
|
||||||
|
|
||||||
If sender is Any, receiver will receive signal from any sender.
|
|
||||||
If signal is Any, receiver will receive any signal from sender.
|
|
||||||
If sender is None, receiver will receive signal from Anonymous.
|
|
||||||
If signal is Any and sender is None, receiver will receive any
|
|
||||||
signal from Anonymous.
|
|
||||||
If signal is Any and sender is Any, receiver will receive any
|
|
||||||
signal from any sender.
|
|
||||||
If weak is true, weak references will be used."""
|
|
||||||
if signal is None:
|
|
||||||
raise DispatcherError, 'signal cannot be None'
|
|
||||||
if weak:
|
|
||||||
receiver = safeRef(receiver)
|
|
||||||
senderkey = id(sender)
|
|
||||||
signals = {}
|
|
||||||
if connections.has_key(senderkey):
|
|
||||||
signals = connections[senderkey]
|
|
||||||
else:
|
|
||||||
connections[senderkey] = signals
|
|
||||||
# Keep track of senders for cleanup.
|
|
||||||
if sender not in (None, Any):
|
|
||||||
def remove(object, senderkey=senderkey):
|
|
||||||
_removeSender(senderkey=senderkey)
|
|
||||||
# Skip objects that can not be weakly referenced, which means
|
|
||||||
# they won't be automatically cleaned up, but that's too bad.
|
|
||||||
try:
|
|
||||||
weakSender = weakref.ref(sender, remove)
|
|
||||||
senders[senderkey] = weakSender
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
receivers = []
|
|
||||||
if signals.has_key(signal):
|
|
||||||
receivers = signals[signal]
|
|
||||||
else:
|
|
||||||
signals[signal] = receivers
|
|
||||||
try:
|
|
||||||
receivers.remove(receiver)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
receivers.append(receiver)
|
|
||||||
|
|
||||||
def disconnect(receiver, signal=Any, sender=Any, weak=True):
|
|
||||||
"""Disconnect receiver from sender for signal.
|
|
||||||
|
|
||||||
Disconnecting is not required. The use of disconnect is the same as for
|
|
||||||
connect, only in reverse. Think of it as undoing a previous connection."""
|
|
||||||
if signal is None:
|
|
||||||
raise DispatcherError, 'signal cannot be None'
|
|
||||||
if weak:
|
|
||||||
receiver = safeRef(receiver)
|
|
||||||
senderkey = id(sender)
|
|
||||||
try:
|
|
||||||
receivers = connections[senderkey][signal]
|
|
||||||
except KeyError:
|
|
||||||
raise DispatcherError, \
|
|
||||||
'No receivers for signal %r from sender %s' % (signal, sender)
|
|
||||||
try:
|
|
||||||
receivers.remove(receiver)
|
|
||||||
except ValueError:
|
|
||||||
raise DispatcherError, \
|
|
||||||
'No connection to receiver %s for signal %r from sender %s' % \
|
|
||||||
(receiver, signal, sender)
|
|
||||||
_cleanupConnections(senderkey, signal)
|
|
||||||
|
|
||||||
def send(signal, sender=Anonymous, **kwds):
|
|
||||||
"""Send signal from sender to all connected receivers.
|
|
||||||
|
|
||||||
Return a list of tuple pairs [(receiver, response), ... ].
|
|
||||||
If sender is not specified, signal is sent anonymously."""
|
|
||||||
senderkey = id(sender)
|
|
||||||
anykey = id(Any)
|
|
||||||
# Get receivers that receive *this* signal from *this* sender.
|
|
||||||
receivers = []
|
|
||||||
try:
|
|
||||||
receivers.extend(connections[senderkey][signal])
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
# Add receivers that receive *any* signal from *this* sender.
|
|
||||||
anyreceivers = []
|
|
||||||
try:
|
|
||||||
anyreceivers = connections[senderkey][Any]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
for receiver in anyreceivers:
|
|
||||||
if receivers.count(receiver) == 0:
|
|
||||||
receivers.append(receiver)
|
|
||||||
# Add receivers that receive *this* signal from *any* sender.
|
|
||||||
anyreceivers = []
|
|
||||||
try:
|
|
||||||
anyreceivers = connections[anykey][signal]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
for receiver in anyreceivers:
|
|
||||||
if receivers.count(receiver) == 0:
|
|
||||||
receivers.append(receiver)
|
|
||||||
# Add receivers that receive *any* signal from *any* sender.
|
|
||||||
anyreceivers = []
|
|
||||||
try:
|
|
||||||
anyreceivers = connections[anykey][Any]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
for receiver in anyreceivers:
|
|
||||||
if receivers.count(receiver) == 0:
|
|
||||||
receivers.append(receiver)
|
|
||||||
# Call each receiver with whatever arguments it can accept.
|
|
||||||
# Return a list of tuple pairs [(receiver, response), ... ].
|
|
||||||
responses = []
|
|
||||||
for receiver in receivers:
|
|
||||||
if type(receiver) is weakref.ReferenceType \
|
|
||||||
or isinstance(receiver, BoundMethodWeakref):
|
|
||||||
# Dereference the weak reference.
|
|
||||||
receiver = receiver()
|
|
||||||
if receiver is None:
|
|
||||||
# This receiver is dead, so skip it.
|
|
||||||
continue
|
|
||||||
response = _call(receiver, signal=signal, sender=sender, **kwds)
|
|
||||||
responses += [(receiver, response)]
|
|
||||||
return responses
|
|
||||||
|
|
||||||
def _call(receiver, **kwds):
|
|
||||||
"""Call receiver with only arguments it can accept."""
|
|
||||||
## if type(receiver) is types.InstanceType:
|
|
||||||
if hasattr(receiver, '__call__') and \
|
|
||||||
(hasattr(receiver.__call__, 'im_func') or hasattr(receiver.__call__, 'im_code')):
|
|
||||||
# receiver is a class instance; assume it is callable.
|
|
||||||
# Reassign receiver to the actual method that will be called.
|
|
||||||
receiver = receiver.__call__
|
|
||||||
if hasattr(receiver, 'im_func'):
|
|
||||||
# receiver is a method. Drop the first argument, usually 'self'.
|
|
||||||
fc = receiver.im_func.func_code
|
|
||||||
acceptable = fc.co_varnames[1:fc.co_argcount]
|
|
||||||
elif hasattr(receiver, 'func_code'):
|
|
||||||
# receiver is a function.
|
|
||||||
fc = receiver.func_code
|
|
||||||
acceptable = fc.co_varnames[0:fc.co_argcount]
|
|
||||||
else:
|
|
||||||
raise DispatcherError, 'Unknown receiver %s of type %s' % (receiver, type(receiver))
|
|
||||||
if not (fc.co_flags & 8):
|
|
||||||
# fc does not have a **kwds type parameter, therefore
|
|
||||||
# remove unacceptable arguments.
|
|
||||||
for arg in kwds.keys():
|
|
||||||
if arg not in acceptable:
|
|
||||||
del kwds[arg]
|
|
||||||
return receiver(**kwds)
|
|
||||||
|
|
||||||
|
|
||||||
def safeRef(object):
|
|
||||||
"""Return a *safe* weak reference to a callable object."""
|
|
||||||
if hasattr(object, 'im_self'):
|
|
||||||
if object.im_self is not None:
|
|
||||||
# Turn a bound method into a BoundMethodWeakref instance.
|
|
||||||
# Keep track of these instances for lookup by disconnect().
|
|
||||||
selfkey = object.im_self
|
|
||||||
funckey = object.im_func
|
|
||||||
if not _boundMethods.has_key(selfkey):
|
|
||||||
_boundMethods[selfkey] = weakref.WeakKeyDictionary()
|
|
||||||
if not _boundMethods[selfkey].has_key(funckey):
|
|
||||||
_boundMethods[selfkey][funckey] = \
|
|
||||||
BoundMethodWeakref(boundMethod=object)
|
|
||||||
return _boundMethods[selfkey][funckey]
|
|
||||||
return weakref.ref(object, _removeReceiver)
|
|
||||||
|
|
||||||
|
|
||||||
class BoundMethodWeakref:
|
|
||||||
"""BoundMethodWeakref class."""
|
|
||||||
|
|
||||||
def __init__(self, boundMethod):
|
|
||||||
"""Return a weak-reference-like instance for a bound method."""
|
|
||||||
self.isDead = 0
|
|
||||||
def remove(object, self=self):
|
|
||||||
"""Set self.isDead to true when method or instance is destroyed."""
|
|
||||||
self.isDead = 1
|
|
||||||
_removeReceiver(receiver=self)
|
|
||||||
self.weakSelf = weakref.ref(boundMethod.im_self, remove)
|
|
||||||
self.weakFunc = weakref.ref(boundMethod.im_func, remove)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
"""Return the closest representation."""
|
|
||||||
return '<bound method weakref for %s.%s>' % (self.weakSelf, self.weakFunc)
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
"""Return a strong reference to the bound method."""
|
|
||||||
if self.isDead:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
object = self.weakSelf()
|
|
||||||
method = self.weakFunc().__name__
|
|
||||||
try: # wxPython hack to handle wxDead objects.
|
|
||||||
return getattr(object, method)
|
|
||||||
except AttributeError:
|
|
||||||
## _removeReceiver(receiver=self)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _removeReceiver(receiver):
|
|
||||||
"""Remove receiver from connections."""
|
|
||||||
for senderkey in connections.keys():
|
|
||||||
for signal in connections[senderkey].keys():
|
|
||||||
receivers = connections[senderkey][signal]
|
|
||||||
try:
|
|
||||||
receivers.remove(receiver)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
_cleanupConnections(senderkey, signal)
|
|
||||||
|
|
||||||
def _cleanupConnections(senderkey, signal):
|
|
||||||
"""Delete any empty signals for senderkey. Delete senderkey if empty."""
|
|
||||||
receivers = connections[senderkey][signal]
|
|
||||||
if not receivers:
|
|
||||||
# No more connected receivers. Therefore, remove the signal.
|
|
||||||
signals = connections[senderkey]
|
|
||||||
del signals[signal]
|
|
||||||
if not signals:
|
|
||||||
# No more signal connections. Therefore, remove the sender.
|
|
||||||
_removeSender(senderkey)
|
|
||||||
|
|
||||||
def _removeSender(senderkey):
|
|
||||||
"""Remove senderkey from connections."""
|
|
||||||
del connections[senderkey]
|
|
||||||
# Senderkey will only be in senders dictionary if sender
|
|
||||||
# could be weakly referenced.
|
|
||||||
try:
|
|
||||||
del senders[senderkey]
|
|
||||||
except:
|
|
||||||
pass
|
|
@@ -1,43 +0,0 @@
|
|||||||
"""Document class."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class Document:
|
|
||||||
"""Document class."""
|
|
||||||
|
|
||||||
def __init__(self, filename=None):
|
|
||||||
"""Create a Document instance."""
|
|
||||||
self.filename = filename
|
|
||||||
self.filepath = None
|
|
||||||
self.filedir = None
|
|
||||||
self.filebase = None
|
|
||||||
self.fileext = None
|
|
||||||
if self.filename:
|
|
||||||
self.filepath = os.path.realpath(self.filename)
|
|
||||||
self.filedir, self.filename = os.path.split(self.filepath)
|
|
||||||
self.filebase, self.fileext = os.path.splitext(self.filename)
|
|
||||||
|
|
||||||
def read(self):
|
|
||||||
"""Return contents of file."""
|
|
||||||
if self.filepath and os.path.exists(self.filepath):
|
|
||||||
f = file(self.filepath, 'rb')
|
|
||||||
try:
|
|
||||||
return f.read()
|
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
else:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def write(self, text):
|
|
||||||
"""Write text to file."""
|
|
||||||
try:
|
|
||||||
f = file(self.filepath, 'wb')
|
|
||||||
f.write(text)
|
|
||||||
finally:
|
|
||||||
if f:
|
|
||||||
f.close()
|
|
@@ -1,843 +0,0 @@
|
|||||||
"""PyAlaCarte and PyAlaMode editors."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
|
|
||||||
from buffer import Buffer
|
|
||||||
import crust
|
|
||||||
import dispatcher
|
|
||||||
import editwindow
|
|
||||||
import frame
|
|
||||||
from shell import Shell
|
|
||||||
import version
|
|
||||||
|
|
||||||
|
|
||||||
class EditorFrame(frame.Frame):
|
|
||||||
"""Frame containing one editor."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyAlaCarte',
|
|
||||||
pos=wx.DefaultPosition, size=(800, 600),
|
|
||||||
style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE,
|
|
||||||
filename=None):
|
|
||||||
"""Create EditorFrame instance."""
|
|
||||||
frame.Frame.__init__(self, parent, id, title, pos, size, style)
|
|
||||||
self.buffers = {}
|
|
||||||
self.buffer = None # Current buffer.
|
|
||||||
self.editor = None
|
|
||||||
self._defaultText = title + ' - the tastiest Python editor.'
|
|
||||||
self._statusText = self._defaultText
|
|
||||||
self.SetStatusText(self._statusText)
|
|
||||||
wx.EVT_IDLE(self, self.OnIdle)
|
|
||||||
self._setup()
|
|
||||||
if filename:
|
|
||||||
self.bufferCreate(filename)
|
|
||||||
|
|
||||||
def _setup(self):
|
|
||||||
"""Setup prior to first buffer creation.
|
|
||||||
|
|
||||||
Useful for subclasses."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setEditor(self, editor):
|
|
||||||
self.editor = editor
|
|
||||||
self.buffer = self.editor.buffer
|
|
||||||
self.buffers[self.buffer.id] = self.buffer
|
|
||||||
|
|
||||||
def OnAbout(self, event):
|
|
||||||
"""Display an About window."""
|
|
||||||
title = 'About PyAlaCarte'
|
|
||||||
text = 'Another fine, flaky program.'
|
|
||||||
dialog = wx.MessageDialog(self, text, title,
|
|
||||||
wx.OK | wx.ICON_INFORMATION)
|
|
||||||
dialog.ShowModal()
|
|
||||||
dialog.Destroy()
|
|
||||||
|
|
||||||
def OnClose(self, event):
|
|
||||||
"""Event handler for closing."""
|
|
||||||
for buffer in self.buffers.values():
|
|
||||||
self.buffer = buffer
|
|
||||||
if buffer.hasChanged():
|
|
||||||
cancel = self.bufferSuggestSave()
|
|
||||||
if cancel and event.CanVeto():
|
|
||||||
event.Veto()
|
|
||||||
return
|
|
||||||
self.Destroy()
|
|
||||||
|
|
||||||
def OnIdle(self, event):
|
|
||||||
"""Event handler for idle time."""
|
|
||||||
self._updateStatus()
|
|
||||||
if hasattr(self, 'notebook'):
|
|
||||||
self._updateTabText()
|
|
||||||
self._updateTitle()
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
def _updateStatus(self):
|
|
||||||
"""Show current status information."""
|
|
||||||
if self.editor and hasattr(self.editor, 'getStatus'):
|
|
||||||
status = self.editor.getStatus()
|
|
||||||
text = 'File: %s | Line: %d | Column: %d' % status
|
|
||||||
else:
|
|
||||||
text = self._defaultText
|
|
||||||
if text != self._statusText:
|
|
||||||
self.SetStatusText(text)
|
|
||||||
self._statusText = text
|
|
||||||
|
|
||||||
def _updateTabText(self):
|
|
||||||
"""Show current buffer information on notebook tab."""
|
|
||||||
## suffix = ' **'
|
|
||||||
## notebook = self.notebook
|
|
||||||
## selection = notebook.GetSelection()
|
|
||||||
## if selection == -1:
|
|
||||||
## return
|
|
||||||
## text = notebook.GetPageText(selection)
|
|
||||||
## window = notebook.GetPage(selection)
|
|
||||||
## if window.editor and window.editor.buffer.hasChanged():
|
|
||||||
## if text.endswith(suffix):
|
|
||||||
## pass
|
|
||||||
## else:
|
|
||||||
## notebook.SetPageText(selection, text + suffix)
|
|
||||||
## else:
|
|
||||||
## if text.endswith(suffix):
|
|
||||||
## notebook.SetPageText(selection, text[:len(suffix)])
|
|
||||||
|
|
||||||
def _updateTitle(self):
|
|
||||||
"""Show current title information."""
|
|
||||||
title = self.GetTitle()
|
|
||||||
if self.bufferHasChanged():
|
|
||||||
if title.startswith('* '):
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.SetTitle('* ' + title)
|
|
||||||
else:
|
|
||||||
if title.startswith('* '):
|
|
||||||
self.SetTitle(title[2:])
|
|
||||||
|
|
||||||
def hasBuffer(self):
|
|
||||||
"""Return True if there is a current buffer."""
|
|
||||||
if self.buffer:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def bufferClose(self):
|
|
||||||
"""Close buffer."""
|
|
||||||
if self.bufferHasChanged():
|
|
||||||
cancel = self.bufferSuggestSave()
|
|
||||||
if cancel:
|
|
||||||
return cancel
|
|
||||||
self.bufferDestroy()
|
|
||||||
cancel = False
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
def bufferCreate(self, filename=None):
|
|
||||||
"""Create new buffer."""
|
|
||||||
self.bufferDestroy()
|
|
||||||
buffer = Buffer()
|
|
||||||
self.panel = panel = wx.Panel(parent=self, id=-1)
|
|
||||||
wx.EVT_ERASE_BACKGROUND(panel, lambda x: x)
|
|
||||||
editor = Editor(parent=panel)
|
|
||||||
panel.editor = editor
|
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
||||||
sizer.Add(editor.window, 1, wx.EXPAND)
|
|
||||||
panel.SetSizer(sizer)
|
|
||||||
panel.SetAutoLayout(True)
|
|
||||||
sizer.Layout()
|
|
||||||
buffer.addEditor(editor)
|
|
||||||
buffer.open(filename)
|
|
||||||
self.setEditor(editor)
|
|
||||||
self.editor.setFocus()
|
|
||||||
self.SendSizeEvent()
|
|
||||||
|
|
||||||
|
|
||||||
def bufferDestroy(self):
|
|
||||||
"""Destroy the current buffer."""
|
|
||||||
if self.buffer:
|
|
||||||
for editor in self.buffer.editors.values():
|
|
||||||
editor.destroy()
|
|
||||||
self.editor = None
|
|
||||||
del self.buffers[self.buffer.id]
|
|
||||||
self.buffer = None
|
|
||||||
self.panel.Destroy()
|
|
||||||
|
|
||||||
|
|
||||||
def bufferHasChanged(self):
|
|
||||||
"""Return True if buffer has changed since last save."""
|
|
||||||
if self.buffer:
|
|
||||||
return self.buffer.hasChanged()
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def bufferNew(self):
|
|
||||||
"""Create new buffer."""
|
|
||||||
if self.bufferHasChanged():
|
|
||||||
cancel = self.bufferSuggestSave()
|
|
||||||
if cancel:
|
|
||||||
return cancel
|
|
||||||
self.bufferCreate()
|
|
||||||
cancel = False
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
def bufferOpen(self):
|
|
||||||
"""Open file in buffer."""
|
|
||||||
if self.bufferHasChanged():
|
|
||||||
cancel = self.bufferSuggestSave()
|
|
||||||
if cancel:
|
|
||||||
return cancel
|
|
||||||
filedir = ''
|
|
||||||
if self.buffer and self.buffer.doc.filedir:
|
|
||||||
filedir = self.buffer.doc.filedir
|
|
||||||
result = openSingle(directory=filedir)
|
|
||||||
if result.path:
|
|
||||||
self.bufferCreate(result.path)
|
|
||||||
cancel = False
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
## def bufferPrint(self):
|
|
||||||
## """Print buffer."""
|
|
||||||
## pass
|
|
||||||
|
|
||||||
## def bufferRevert(self):
|
|
||||||
## """Revert buffer to version of file on disk."""
|
|
||||||
## pass
|
|
||||||
|
|
||||||
def bufferSave(self):
|
|
||||||
"""Save buffer to its file."""
|
|
||||||
if self.buffer.doc.filepath:
|
|
||||||
self.buffer.save()
|
|
||||||
cancel = False
|
|
||||||
else:
|
|
||||||
cancel = self.bufferSaveAs()
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
def bufferSaveAs(self):
|
|
||||||
"""Save buffer to a new filename."""
|
|
||||||
if self.bufferHasChanged() and self.buffer.doc.filepath:
|
|
||||||
cancel = self.bufferSuggestSave()
|
|
||||||
if cancel:
|
|
||||||
return cancel
|
|
||||||
filedir = ''
|
|
||||||
if self.buffer and self.buffer.doc.filedir:
|
|
||||||
filedir = self.buffer.doc.filedir
|
|
||||||
result = saveSingle(directory=filedir)
|
|
||||||
if result.path:
|
|
||||||
self.buffer.saveAs(result.path)
|
|
||||||
cancel = False
|
|
||||||
else:
|
|
||||||
cancel = True
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
def bufferSuggestSave(self):
|
|
||||||
"""Suggest saving changes. Return True if user selected Cancel."""
|
|
||||||
result = messageDialog(parent=None,
|
|
||||||
message='%s has changed.\n'
|
|
||||||
'Would you like to save it first'
|
|
||||||
'?' % self.buffer.name,
|
|
||||||
title='Save current file?')
|
|
||||||
if result.positive:
|
|
||||||
cancel = self.bufferSave()
|
|
||||||
else:
|
|
||||||
cancel = result.text == 'Cancel'
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
def updateNamespace(self):
|
|
||||||
"""Update the buffer namespace for autocompletion and calltips."""
|
|
||||||
if self.buffer.updateNamespace():
|
|
||||||
self.SetStatusText('Namespace updated')
|
|
||||||
else:
|
|
||||||
self.SetStatusText('Error executing, unable to update namespace')
|
|
||||||
|
|
||||||
|
|
||||||
class EditorNotebookFrame(EditorFrame):
|
|
||||||
"""Frame containing one or more editors in a notebook."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyAlaMode',
|
|
||||||
pos=wx.DefaultPosition, size=(800, 600),
|
|
||||||
style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE,
|
|
||||||
filename=None):
|
|
||||||
"""Create EditorNotebookFrame instance."""
|
|
||||||
self.notebook = None
|
|
||||||
EditorFrame.__init__(self, parent, id, title, pos,
|
|
||||||
size, style, filename)
|
|
||||||
if self.notebook:
|
|
||||||
dispatcher.connect(receiver=self._editorChange,
|
|
||||||
signal='EditorChange', sender=self.notebook)
|
|
||||||
|
|
||||||
def _setup(self):
|
|
||||||
"""Setup prior to first buffer creation.
|
|
||||||
|
|
||||||
Called automatically by base class during init."""
|
|
||||||
self.notebook = EditorNotebook(parent=self)
|
|
||||||
intro = 'Py %s' % version.VERSION
|
|
||||||
import imp
|
|
||||||
module = imp.new_module('__main__')
|
|
||||||
import __builtin__
|
|
||||||
module.__dict__['__builtins__'] = __builtin__
|
|
||||||
namespace = module.__dict__.copy()
|
|
||||||
self.crust = crust.Crust(parent=self.notebook, intro=intro, locals=namespace)
|
|
||||||
self.shell = self.crust.shell
|
|
||||||
# Override the filling so that status messages go to the status bar.
|
|
||||||
self.crust.filling.tree.setStatusText = self.SetStatusText
|
|
||||||
# Override the shell so that status messages go to the status bar.
|
|
||||||
self.shell.setStatusText = self.SetStatusText
|
|
||||||
# Fix a problem with the sash shrinking to nothing.
|
|
||||||
self.crust.filling.SetSashPosition(200)
|
|
||||||
self.notebook.AddPage(page=self.crust, text='*Shell*', select=True)
|
|
||||||
self.setEditor(self.crust.editor)
|
|
||||||
self.crust.editor.SetFocus()
|
|
||||||
|
|
||||||
def _editorChange(self, editor):
|
|
||||||
"""Editor change signal receiver."""
|
|
||||||
self.setEditor(editor)
|
|
||||||
|
|
||||||
def OnAbout(self, event):
|
|
||||||
"""Display an About window."""
|
|
||||||
title = 'About PyAlaMode'
|
|
||||||
text = 'Another fine, flaky program.'
|
|
||||||
dialog = wx.MessageDialog(self, text, title,
|
|
||||||
wx.OK | wx.ICON_INFORMATION)
|
|
||||||
dialog.ShowModal()
|
|
||||||
dialog.Destroy()
|
|
||||||
|
|
||||||
def _updateTitle(self):
|
|
||||||
"""Show current title information."""
|
|
||||||
pass
|
|
||||||
## title = self.GetTitle()
|
|
||||||
## if self.bufferHasChanged():
|
|
||||||
## if title.startswith('* '):
|
|
||||||
## pass
|
|
||||||
## else:
|
|
||||||
## self.SetTitle('* ' + title)
|
|
||||||
## else:
|
|
||||||
## if title.startswith('* '):
|
|
||||||
## self.SetTitle(title[2:])
|
|
||||||
|
|
||||||
def bufferCreate(self, filename=None):
|
|
||||||
"""Create new buffer."""
|
|
||||||
buffer = Buffer()
|
|
||||||
panel = wx.Panel(parent=self.notebook, id=-1)
|
|
||||||
wx.EVT_ERASE_BACKGROUND(panel, lambda x: x)
|
|
||||||
editor = Editor(parent=panel)
|
|
||||||
panel.editor = editor
|
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
||||||
sizer.Add(editor.window, 1, wx.EXPAND)
|
|
||||||
panel.SetSizer(sizer)
|
|
||||||
panel.SetAutoLayout(True)
|
|
||||||
sizer.Layout()
|
|
||||||
buffer.addEditor(editor)
|
|
||||||
buffer.open(filename)
|
|
||||||
self.setEditor(editor)
|
|
||||||
self.notebook.AddPage(page=panel, text=self.buffer.name, select=True)
|
|
||||||
self.editor.setFocus()
|
|
||||||
|
|
||||||
def bufferDestroy(self):
|
|
||||||
"""Destroy the current buffer."""
|
|
||||||
selection = self.notebook.GetSelection()
|
|
||||||
## print "Destroy Selection:", selection
|
|
||||||
if selection > 0: # Don't destroy the PyCrust tab.
|
|
||||||
if self.buffer:
|
|
||||||
del self.buffers[self.buffer.id]
|
|
||||||
self.buffer = None # Do this before DeletePage().
|
|
||||||
self.notebook.DeletePage(selection)
|
|
||||||
|
|
||||||
def bufferNew(self):
|
|
||||||
"""Create new buffer."""
|
|
||||||
self.bufferCreate()
|
|
||||||
cancel = False
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
def bufferOpen(self):
|
|
||||||
"""Open file in buffer."""
|
|
||||||
filedir = ''
|
|
||||||
if self.buffer and self.buffer.doc.filedir:
|
|
||||||
filedir = self.buffer.doc.filedir
|
|
||||||
result = openMultiple(directory=filedir)
|
|
||||||
for path in result.paths:
|
|
||||||
self.bufferCreate(path)
|
|
||||||
cancel = False
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
|
|
||||||
class EditorNotebook(wx.Notebook):
|
|
||||||
"""A notebook containing a page for each editor."""
|
|
||||||
|
|
||||||
def __init__(self, parent):
|
|
||||||
"""Create EditorNotebook instance."""
|
|
||||||
wx.Notebook.__init__(self, parent, id=-1, style=wx.CLIP_CHILDREN)
|
|
||||||
wx.EVT_NOTEBOOK_PAGE_CHANGING(self, self.GetId(),
|
|
||||||
self.OnPageChanging)
|
|
||||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(),
|
|
||||||
self.OnPageChanged)
|
|
||||||
wx.EVT_IDLE(self, self.OnIdle)
|
|
||||||
|
|
||||||
def OnIdle(self, event):
|
|
||||||
"""Event handler for idle time."""
|
|
||||||
self._updateTabText()
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
def _updateTabText(self):
|
|
||||||
"""Show current buffer display name on all but first tab."""
|
|
||||||
size = 3
|
|
||||||
changed = ' **'
|
|
||||||
unchanged = ' --'
|
|
||||||
selection = self.GetSelection()
|
|
||||||
if selection < 1:
|
|
||||||
return
|
|
||||||
text = self.GetPageText(selection)
|
|
||||||
window = self.GetPage(selection)
|
|
||||||
if not window.editor:
|
|
||||||
return
|
|
||||||
if text.endswith(changed) or text.endswith(unchanged):
|
|
||||||
name = text[:-size]
|
|
||||||
else:
|
|
||||||
name = text
|
|
||||||
if name != window.editor.buffer.name:
|
|
||||||
text = window.editor.buffer.name
|
|
||||||
if window.editor.buffer.hasChanged():
|
|
||||||
if text.endswith(changed):
|
|
||||||
text = None
|
|
||||||
elif text.endswith(unchanged):
|
|
||||||
text = text[:-size] + changed
|
|
||||||
else:
|
|
||||||
text += changed
|
|
||||||
else:
|
|
||||||
if text.endswith(changed):
|
|
||||||
text = text[:-size] + unchanged
|
|
||||||
elif text.endswith(unchanged):
|
|
||||||
text = None
|
|
||||||
else:
|
|
||||||
text += unchanged
|
|
||||||
if text is not None:
|
|
||||||
self.SetPageText(selection, text)
|
|
||||||
self.Refresh() # Needed on Win98.
|
|
||||||
|
|
||||||
def OnPageChanging(self, event):
|
|
||||||
"""Page changing event handler."""
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
def OnPageChanged(self, event):
|
|
||||||
"""Page changed event handler."""
|
|
||||||
new = event.GetSelection()
|
|
||||||
window = self.GetPage(new)
|
|
||||||
dispatcher.send(signal='EditorChange', sender=self,
|
|
||||||
editor=window.editor)
|
|
||||||
window.SetFocus()
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
|
|
||||||
class EditorShellNotebookFrame(EditorNotebookFrame):
|
|
||||||
"""Frame containing a notebook containing EditorShellNotebooks."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyAlaModeTest',
|
|
||||||
pos=wx.DefaultPosition, size=(600, 400),
|
|
||||||
style=wx.DEFAULT_FRAME_STYLE,
|
|
||||||
filename=None, singlefile=False):
|
|
||||||
"""Create EditorShellNotebookFrame instance."""
|
|
||||||
self._singlefile = singlefile
|
|
||||||
EditorNotebookFrame.__init__(self, parent, id, title, pos,
|
|
||||||
size, style, filename)
|
|
||||||
|
|
||||||
def _setup(self):
|
|
||||||
"""Setup prior to first buffer creation.
|
|
||||||
|
|
||||||
Called automatically by base class during init."""
|
|
||||||
if not self._singlefile:
|
|
||||||
self.notebook = EditorNotebook(parent=self)
|
|
||||||
|
|
||||||
def OnAbout(self, event):
|
|
||||||
"""Display an About window."""
|
|
||||||
title = 'About PyAlaModePlus'
|
|
||||||
text = 'Another fine, flaky program.'
|
|
||||||
dialog = wx.MessageDialog(self, text, title,
|
|
||||||
wx.OK | wx.ICON_INFORMATION)
|
|
||||||
dialog.ShowModal()
|
|
||||||
dialog.Destroy()
|
|
||||||
|
|
||||||
def bufferCreate(self, filename=None):
|
|
||||||
"""Create new buffer."""
|
|
||||||
if self._singlefile:
|
|
||||||
self.bufferDestroy()
|
|
||||||
notebook = EditorShellNotebook(parent=self,
|
|
||||||
filename=filename)
|
|
||||||
self.notebook = notebook
|
|
||||||
else:
|
|
||||||
notebook = EditorShellNotebook(parent=self.notebook,
|
|
||||||
filename=filename)
|
|
||||||
self.setEditor(notebook.editor)
|
|
||||||
if not self._singlefile:
|
|
||||||
self.notebook.AddPage(page=notebook, text=self.buffer.name,
|
|
||||||
select=True)
|
|
||||||
self.editor.setFocus()
|
|
||||||
|
|
||||||
def bufferDestroy(self):
|
|
||||||
"""Destroy the current buffer."""
|
|
||||||
if self.buffer:
|
|
||||||
self.editor = None
|
|
||||||
del self.buffers[self.buffer.id]
|
|
||||||
self.buffer = None # Do this before DeletePage().
|
|
||||||
if self._singlefile:
|
|
||||||
self.notebook.Destroy()
|
|
||||||
self.notebook = None
|
|
||||||
else:
|
|
||||||
selection = self.notebook.GetSelection()
|
|
||||||
## print "Destroy Selection:", selection
|
|
||||||
self.notebook.DeletePage(selection)
|
|
||||||
|
|
||||||
def bufferNew(self):
|
|
||||||
"""Create new buffer."""
|
|
||||||
if self._singlefile and self.bufferHasChanged():
|
|
||||||
cancel = self.bufferSuggestSave()
|
|
||||||
if cancel:
|
|
||||||
return cancel
|
|
||||||
self.bufferCreate()
|
|
||||||
cancel = False
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
def bufferOpen(self):
|
|
||||||
"""Open file in buffer."""
|
|
||||||
if self._singlefile and self.bufferHasChanged():
|
|
||||||
cancel = self.bufferSuggestSave()
|
|
||||||
if cancel:
|
|
||||||
return cancel
|
|
||||||
filedir = ''
|
|
||||||
if self.buffer and self.buffer.doc.filedir:
|
|
||||||
filedir = self.buffer.doc.filedir
|
|
||||||
if self._singlefile:
|
|
||||||
result = openSingle(directory=filedir)
|
|
||||||
if result.path:
|
|
||||||
self.bufferCreate(result.path)
|
|
||||||
else:
|
|
||||||
result = openMultiple(directory=filedir)
|
|
||||||
for path in result.paths:
|
|
||||||
self.bufferCreate(path)
|
|
||||||
cancel = False
|
|
||||||
return cancel
|
|
||||||
|
|
||||||
|
|
||||||
class EditorShellNotebook(wx.Notebook):
|
|
||||||
"""A notebook containing an editor page and a shell page."""
|
|
||||||
|
|
||||||
def __init__(self, parent, filename=None):
|
|
||||||
"""Create EditorShellNotebook instance."""
|
|
||||||
wx.Notebook.__init__(self, parent, id=-1)
|
|
||||||
usePanels = True
|
|
||||||
if usePanels:
|
|
||||||
editorparent = editorpanel = wx.Panel(self, -1)
|
|
||||||
shellparent = shellpanel = wx.Panel(self, -1)
|
|
||||||
else:
|
|
||||||
editorparent = self
|
|
||||||
shellparent = self
|
|
||||||
self.buffer = Buffer()
|
|
||||||
self.editor = Editor(parent=editorparent)
|
|
||||||
self.buffer.addEditor(self.editor)
|
|
||||||
self.buffer.open(filename)
|
|
||||||
self.shell = Shell(parent=shellparent, locals=self.buffer.interp.locals,
|
|
||||||
style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER)
|
|
||||||
self.buffer.interp.locals.clear()
|
|
||||||
if usePanels:
|
|
||||||
self.AddPage(page=editorpanel, text='Editor', select=True)
|
|
||||||
self.AddPage(page=shellpanel, text='Shell')
|
|
||||||
# Setup sizers
|
|
||||||
editorsizer = wx.BoxSizer(wx.VERTICAL)
|
|
||||||
editorsizer.Add(self.editor.window, 1, wx.EXPAND)
|
|
||||||
editorpanel.SetSizer(editorsizer)
|
|
||||||
editorpanel.SetAutoLayout(True)
|
|
||||||
shellsizer = wx.BoxSizer(wx.VERTICAL)
|
|
||||||
shellsizer.Add(self.shell, 1, wx.EXPAND)
|
|
||||||
shellpanel.SetSizer(shellsizer)
|
|
||||||
shellpanel.SetAutoLayout(True)
|
|
||||||
else:
|
|
||||||
self.AddPage(page=self.editor.window, text='Editor', select=True)
|
|
||||||
self.AddPage(page=self.shell, text='Shell')
|
|
||||||
self.editor.setFocus()
|
|
||||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
|
|
||||||
|
|
||||||
def OnPageChanged(self, event):
|
|
||||||
"""Page changed event handler."""
|
|
||||||
selection = event.GetSelection()
|
|
||||||
if selection == 0:
|
|
||||||
self.editor.setFocus()
|
|
||||||
else:
|
|
||||||
self.shell.SetFocus()
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
def SetFocus(self):
|
|
||||||
wx.Notebook.SetFocus(self)
|
|
||||||
selection = self.GetSelection()
|
|
||||||
if selection == 0:
|
|
||||||
self.editor.setFocus()
|
|
||||||
else:
|
|
||||||
self.shell.SetFocus()
|
|
||||||
|
|
||||||
|
|
||||||
class Editor:
|
|
||||||
"""Editor having an EditWindow."""
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
|
||||||
size=wx.DefaultSize,
|
|
||||||
style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
|
|
||||||
"""Create Editor instance."""
|
|
||||||
self.window = EditWindow(self, parent, id, pos, size, style)
|
|
||||||
self.id = self.window.GetId()
|
|
||||||
self.buffer = None
|
|
||||||
# Assign handlers for keyboard events.
|
|
||||||
wx.EVT_CHAR(self.window, self.OnChar)
|
|
||||||
wx.EVT_KEY_DOWN(self.window, self.OnKeyDown)
|
|
||||||
|
|
||||||
def _setBuffer(self, buffer, text):
|
|
||||||
"""Set the editor to a buffer. Private callback called by buffer."""
|
|
||||||
self.buffer = buffer
|
|
||||||
self.autoCompleteKeys = buffer.interp.getAutoCompleteKeys()
|
|
||||||
self.clearAll()
|
|
||||||
self.setText(text)
|
|
||||||
self.emptyUndoBuffer()
|
|
||||||
self.setSavePoint()
|
|
||||||
|
|
||||||
def destroy(self):
|
|
||||||
"""Destroy all editor objects."""
|
|
||||||
self.window.Destroy()
|
|
||||||
|
|
||||||
def clearAll(self):
|
|
||||||
self.window.ClearAll()
|
|
||||||
|
|
||||||
def emptyUndoBuffer(self):
|
|
||||||
self.window.EmptyUndoBuffer()
|
|
||||||
|
|
||||||
def getStatus(self):
|
|
||||||
"""Return (filepath, line, column) status tuple."""
|
|
||||||
if self.window:
|
|
||||||
pos = self.window.GetCurrentPos()
|
|
||||||
line = self.window.LineFromPosition(pos) + 1
|
|
||||||
col = self.window.GetColumn(pos)
|
|
||||||
if self.buffer:
|
|
||||||
name = self.buffer.doc.filepath or self.buffer.name
|
|
||||||
else:
|
|
||||||
name = ''
|
|
||||||
status = (name, line, col)
|
|
||||||
return status
|
|
||||||
else:
|
|
||||||
return ('', 0, 0)
|
|
||||||
|
|
||||||
def getText(self):
|
|
||||||
"""Return contents of editor."""
|
|
||||||
return self.window.GetText()
|
|
||||||
|
|
||||||
def hasChanged(self):
|
|
||||||
"""Return True if contents have changed."""
|
|
||||||
return self.window.GetModify()
|
|
||||||
|
|
||||||
def setFocus(self):
|
|
||||||
"""Set the input focus to the editor window."""
|
|
||||||
self.window.SetFocus()
|
|
||||||
|
|
||||||
def setSavePoint(self):
|
|
||||||
self.window.SetSavePoint()
|
|
||||||
|
|
||||||
def setText(self, text):
|
|
||||||
"""Set contents of editor."""
|
|
||||||
self.window.SetText(text)
|
|
||||||
|
|
||||||
def OnChar(self, event):
|
|
||||||
"""Keypress event handler.
|
|
||||||
|
|
||||||
Only receives an event if OnKeyDown calls event.Skip() for the
|
|
||||||
corresponding event."""
|
|
||||||
|
|
||||||
key = event.KeyCode()
|
|
||||||
if key in self.autoCompleteKeys:
|
|
||||||
# Usually the dot (period) key activates auto completion.
|
|
||||||
if self.window.AutoCompActive():
|
|
||||||
self.window.AutoCompCancel()
|
|
||||||
self.window.ReplaceSelection('')
|
|
||||||
self.window.AddText(chr(key))
|
|
||||||
text, pos = self.window.GetCurLine()
|
|
||||||
text = text[:pos]
|
|
||||||
if self.window.autoComplete:
|
|
||||||
self.autoCompleteShow(text)
|
|
||||||
elif key == ord('('):
|
|
||||||
# The left paren activates a call tip and cancels an
|
|
||||||
# active auto completion.
|
|
||||||
if self.window.AutoCompActive():
|
|
||||||
self.window.AutoCompCancel()
|
|
||||||
self.window.ReplaceSelection('')
|
|
||||||
self.window.AddText('(')
|
|
||||||
text, pos = self.window.GetCurLine()
|
|
||||||
text = text[:pos]
|
|
||||||
self.autoCallTipShow(text)
|
|
||||||
else:
|
|
||||||
# Allow the normal event handling to take place.
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
def OnKeyDown(self, event):
|
|
||||||
"""Key down event handler."""
|
|
||||||
|
|
||||||
key = event.KeyCode()
|
|
||||||
# If the auto-complete window is up let it do its thing.
|
|
||||||
if self.window.AutoCompActive():
|
|
||||||
event.Skip()
|
|
||||||
return
|
|
||||||
controlDown = event.ControlDown()
|
|
||||||
altDown = event.AltDown()
|
|
||||||
shiftDown = event.ShiftDown()
|
|
||||||
# Let Ctrl-Alt-* get handled normally.
|
|
||||||
if controlDown and altDown:
|
|
||||||
event.Skip()
|
|
||||||
# Increase font size.
|
|
||||||
elif controlDown and key in (ord(']'),):
|
|
||||||
dispatcher.send(signal='FontIncrease')
|
|
||||||
# Decrease font size.
|
|
||||||
elif controlDown and key in (ord('['),):
|
|
||||||
dispatcher.send(signal='FontDecrease')
|
|
||||||
# Default font size.
|
|
||||||
elif controlDown and key in (ord('='),):
|
|
||||||
dispatcher.send(signal='FontDefault')
|
|
||||||
else:
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
def autoCompleteShow(self, command):
|
|
||||||
"""Display auto-completion popup list."""
|
|
||||||
list = self.buffer.interp.getAutoCompleteList(command,
|
|
||||||
includeMagic=self.window.autoCompleteIncludeMagic,
|
|
||||||
includeSingle=self.window.autoCompleteIncludeSingle,
|
|
||||||
includeDouble=self.window.autoCompleteIncludeDouble)
|
|
||||||
if list:
|
|
||||||
options = ' '.join(list)
|
|
||||||
offset = 0
|
|
||||||
self.window.AutoCompShow(offset, options)
|
|
||||||
|
|
||||||
def autoCallTipShow(self, command):
|
|
||||||
"""Display argument spec and docstring in a popup window."""
|
|
||||||
if self.window.CallTipActive():
|
|
||||||
self.window.CallTipCancel()
|
|
||||||
(name, argspec, tip) = self.buffer.interp.getCallTip(command)
|
|
||||||
if tip:
|
|
||||||
dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip)
|
|
||||||
if not self.window.autoCallTip:
|
|
||||||
return
|
|
||||||
if argspec:
|
|
||||||
startpos = self.window.GetCurrentPos()
|
|
||||||
self.window.AddText(argspec + ')')
|
|
||||||
endpos = self.window.GetCurrentPos()
|
|
||||||
self.window.SetSelection(endpos, startpos)
|
|
||||||
if tip:
|
|
||||||
curpos = self.window.GetCurrentPos()
|
|
||||||
size = len(name)
|
|
||||||
tippos = curpos - (size + 1)
|
|
||||||
fallback = curpos - self.window.GetColumn(curpos)
|
|
||||||
# In case there isn't enough room, only go back to the
|
|
||||||
# fallback.
|
|
||||||
tippos = max(tippos, fallback)
|
|
||||||
self.window.CallTipShow(tippos, tip)
|
|
||||||
self.window.CallTipSetHighlight(0, size)
|
|
||||||
|
|
||||||
|
|
||||||
class EditWindow(editwindow.EditWindow):
|
|
||||||
"""EditWindow based on StyledTextCtrl."""
|
|
||||||
|
|
||||||
def __init__(self, editor, parent, id=-1, pos=wx.DefaultPosition,
|
|
||||||
size=wx.DefaultSize,
|
|
||||||
style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
|
|
||||||
"""Create EditWindow instance."""
|
|
||||||
editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
|
|
||||||
self.editor = editor
|
|
||||||
|
|
||||||
|
|
||||||
class DialogResults:
|
|
||||||
"""DialogResults class."""
|
|
||||||
|
|
||||||
def __init__(self, returned):
|
|
||||||
"""Create wrapper for results returned by dialog."""
|
|
||||||
self.returned = returned
|
|
||||||
self.positive = returned in (wx.ID_OK, wx.ID_YES)
|
|
||||||
self.text = self._asString()
|
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return str(self.__dict__)
|
|
||||||
|
|
||||||
def _asString(self):
|
|
||||||
returned = self.returned
|
|
||||||
if returned == wx.ID_OK:
|
|
||||||
return "Ok"
|
|
||||||
elif returned == wx.ID_CANCEL:
|
|
||||||
return "Cancel"
|
|
||||||
elif returned == wx.ID_YES:
|
|
||||||
return "Yes"
|
|
||||||
elif returned == wx.ID_NO:
|
|
||||||
return "No"
|
|
||||||
|
|
||||||
|
|
||||||
def fileDialog(parent=None, title='Open', directory='', filename='',
|
|
||||||
wildcard='All Files (*.*)|*.*',
|
|
||||||
style=wx.OPEN | wx.MULTIPLE):
|
|
||||||
"""File dialog wrapper function."""
|
|
||||||
dialog = wx.FileDialog(parent, title, directory, filename,
|
|
||||||
wildcard, style)
|
|
||||||
result = DialogResults(dialog.ShowModal())
|
|
||||||
if result.positive:
|
|
||||||
result.paths = dialog.GetPaths()
|
|
||||||
else:
|
|
||||||
result.paths = []
|
|
||||||
dialog.Destroy()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def openSingle(parent=None, title='Open', directory='', filename='',
|
|
||||||
wildcard='All Files (*.*)|*.*', style=wx.OPEN):
|
|
||||||
"""File dialog wrapper function."""
|
|
||||||
dialog = wx.FileDialog(parent, title, directory, filename,
|
|
||||||
wildcard, style)
|
|
||||||
result = DialogResults(dialog.ShowModal())
|
|
||||||
if result.positive:
|
|
||||||
result.path = dialog.GetPath()
|
|
||||||
else:
|
|
||||||
result.path = None
|
|
||||||
dialog.Destroy()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def openMultiple(parent=None, title='Open', directory='', filename='',
|
|
||||||
wildcard='All Files (*.*)|*.*',
|
|
||||||
style=wx.OPEN | wx.MULTIPLE):
|
|
||||||
"""File dialog wrapper function."""
|
|
||||||
return fileDialog(parent, title, directory, filename, wildcard, style)
|
|
||||||
|
|
||||||
|
|
||||||
def saveSingle(parent=None, title='Save', directory='', filename='',
|
|
||||||
wildcard='All Files (*.*)|*.*',
|
|
||||||
style=wx.SAVE | wx.HIDE_READONLY | wx.OVERWRITE_PROMPT):
|
|
||||||
"""File dialog wrapper function."""
|
|
||||||
dialog = wx.FileDialog(parent, title, directory, filename,
|
|
||||||
wildcard, style)
|
|
||||||
result = DialogResults(dialog.ShowModal())
|
|
||||||
if result.positive:
|
|
||||||
result.path = dialog.GetPath()
|
|
||||||
else:
|
|
||||||
result.path = None
|
|
||||||
dialog.Destroy()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def directory(parent=None, message='Choose a directory', path='', style=0,
|
|
||||||
pos=wx.DefaultPosition, size=wx.DefaultSize):
|
|
||||||
"""Dir dialog wrapper function."""
|
|
||||||
dialog = wx.DirDialog(parent, message, path, style, pos, size)
|
|
||||||
result = DialogResults(dialog.ShowModal())
|
|
||||||
if result.positive:
|
|
||||||
result.path = dialog.GetPath()
|
|
||||||
else:
|
|
||||||
result.path = None
|
|
||||||
dialog.Destroy()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def messageDialog(parent=None, message='', title='Message box',
|
|
||||||
style=wx.YES_NO | wx.CANCEL | wx.CENTRE | wx.ICON_QUESTION,
|
|
||||||
pos=wx.DefaultPosition):
|
|
||||||
"""Message dialog wrapper function."""
|
|
||||||
dialog = wx.MessageDialog(parent, message, title, style, pos)
|
|
||||||
result = DialogResults(dialog.ShowModal())
|
|
||||||
dialog.Destroy()
|
|
||||||
return result
|
|
@@ -1,225 +0,0 @@
|
|||||||
"""EditWindow class."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
from wx import stc
|
|
||||||
|
|
||||||
import keyword
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
import dispatcher
|
|
||||||
from version import VERSION
|
|
||||||
|
|
||||||
|
|
||||||
if 'wxMSW' in wx.PlatformInfo:
|
|
||||||
FACES = { 'times' : 'Times New Roman',
|
|
||||||
'mono' : 'Courier New',
|
|
||||||
'helv' : 'Arial',
|
|
||||||
'lucida' : 'Lucida Console',
|
|
||||||
'other' : 'Comic Sans MS',
|
|
||||||
'size' : 10,
|
|
||||||
'lnsize' : 8,
|
|
||||||
'backcol' : '#FFFFFF',
|
|
||||||
'calltipbg' : '#FFFFB8',
|
|
||||||
'calltipfg' : '#404040',
|
|
||||||
}
|
|
||||||
|
|
||||||
elif 'wxGTK' in wx.PlatformInfo and 'gtk2' in wx.PlatformInfo:
|
|
||||||
FACES = { 'times' : 'Serif',
|
|
||||||
'mono' : 'Monospace',
|
|
||||||
'helv' : 'Sans',
|
|
||||||
'other' : 'new century schoolbook',
|
|
||||||
'size' : 10,
|
|
||||||
'lnsize' : 9,
|
|
||||||
'backcol' : '#FFFFFF',
|
|
||||||
'calltipbg' : '#FFFFB8',
|
|
||||||
'calltipfg' : '#404040',
|
|
||||||
}
|
|
||||||
|
|
||||||
elif 'wxMac' in wx.PlatformInfo:
|
|
||||||
FACES = { 'times' : 'Lucida Grande',
|
|
||||||
'mono' : 'Courier New',
|
|
||||||
'helv' : 'Geneva',
|
|
||||||
'other' : 'new century schoolbook',
|
|
||||||
'size' : 13,
|
|
||||||
'lnsize' : 10,
|
|
||||||
'backcol' : '#FFFFFF',
|
|
||||||
'calltipbg' : '#FFFFB8',
|
|
||||||
'calltipfg' : '#404040',
|
|
||||||
}
|
|
||||||
|
|
||||||
else: # GTK1, etc.
|
|
||||||
FACES = { 'times' : 'Times',
|
|
||||||
'mono' : 'Courier',
|
|
||||||
'helv' : 'Helvetica',
|
|
||||||
'other' : 'new century schoolbook',
|
|
||||||
'size' : 12,
|
|
||||||
'lnsize' : 10,
|
|
||||||
'backcol' : '#FFFFFF',
|
|
||||||
'calltipbg' : '#FFFFB8',
|
|
||||||
'calltipfg' : '#404040',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class EditWindow(stc.StyledTextCtrl):
|
|
||||||
"""EditWindow based on StyledTextCtrl."""
|
|
||||||
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
|
||||||
size=wx.DefaultSize, style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
|
|
||||||
"""Create EditWindow instance."""
|
|
||||||
stc.StyledTextCtrl.__init__(self, parent, id, pos, size, style)
|
|
||||||
self.__config()
|
|
||||||
stc.EVT_STC_UPDATEUI(self, id, self.OnUpdateUI)
|
|
||||||
dispatcher.connect(receiver=self._fontsizer, signal='FontIncrease')
|
|
||||||
dispatcher.connect(receiver=self._fontsizer, signal='FontDecrease')
|
|
||||||
dispatcher.connect(receiver=self._fontsizer, signal='FontDefault')
|
|
||||||
|
|
||||||
def _fontsizer(self, signal):
|
|
||||||
"""Receiver for Font* signals."""
|
|
||||||
size = self.GetZoom()
|
|
||||||
if signal == 'FontIncrease':
|
|
||||||
size += 1
|
|
||||||
elif signal == 'FontDecrease':
|
|
||||||
size -= 1
|
|
||||||
elif signal == 'FontDefault':
|
|
||||||
size = 0
|
|
||||||
self.SetZoom(size)
|
|
||||||
|
|
||||||
def __config(self):
|
|
||||||
"""Configure shell based on user preferences."""
|
|
||||||
self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
|
|
||||||
self.SetMarginWidth(1, 40)
|
|
||||||
|
|
||||||
self.SetLexer(stc.STC_LEX_PYTHON)
|
|
||||||
self.SetKeyWords(0, ' '.join(keyword.kwlist))
|
|
||||||
|
|
||||||
self.setStyles(FACES)
|
|
||||||
self.SetViewWhiteSpace(False)
|
|
||||||
self.SetTabWidth(4)
|
|
||||||
self.SetUseTabs(False)
|
|
||||||
# Do we want to automatically pop up command completion options?
|
|
||||||
self.autoComplete = True
|
|
||||||
self.autoCompleteIncludeMagic = True
|
|
||||||
self.autoCompleteIncludeSingle = True
|
|
||||||
self.autoCompleteIncludeDouble = True
|
|
||||||
self.autoCompleteCaseInsensitive = True
|
|
||||||
self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
|
|
||||||
self.autoCompleteAutoHide = False
|
|
||||||
self.AutoCompSetAutoHide(self.autoCompleteAutoHide)
|
|
||||||
self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`')
|
|
||||||
# Do we want to automatically pop up command argument help?
|
|
||||||
self.autoCallTip = True
|
|
||||||
self.CallTipSetBackground(FACES['calltipbg'])
|
|
||||||
self.CallTipSetForeground(FACES['calltipfg'])
|
|
||||||
self.SetWrapMode(False)
|
|
||||||
try:
|
|
||||||
self.SetEndAtLastLine(False)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setStyles(self, faces):
|
|
||||||
"""Configure font size, typeface and color for lexer."""
|
|
||||||
|
|
||||||
# Default style
|
|
||||||
self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
|
|
||||||
"face:%(mono)s,size:%(size)d,back:%(backcol)s" % \
|
|
||||||
faces)
|
|
||||||
|
|
||||||
self.StyleClearAll()
|
|
||||||
|
|
||||||
# Built in styles
|
|
||||||
self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,
|
|
||||||
"back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
|
|
||||||
self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR,
|
|
||||||
"face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
|
|
||||||
"fore:#0000FF,back:#FFFF88")
|
|
||||||
self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
|
|
||||||
"fore:#FF0000,back:#FFFF88")
|
|
||||||
|
|
||||||
# Python styles
|
|
||||||
self.StyleSetSpec(stc.STC_P_DEFAULT,
|
|
||||||
"face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.STC_P_COMMENTLINE,
|
|
||||||
"fore:#007F00,face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.STC_P_NUMBER,
|
|
||||||
"")
|
|
||||||
self.StyleSetSpec(stc.STC_P_STRING,
|
|
||||||
"fore:#7F007F,face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.STC_P_CHARACTER,
|
|
||||||
"fore:#7F007F,face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.STC_P_WORD,
|
|
||||||
"fore:#00007F,bold")
|
|
||||||
self.StyleSetSpec(stc.STC_P_TRIPLE,
|
|
||||||
"fore:#7F0000")
|
|
||||||
self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE,
|
|
||||||
"fore:#000033,back:#FFFFE8")
|
|
||||||
self.StyleSetSpec(stc.STC_P_CLASSNAME,
|
|
||||||
"fore:#0000FF,bold")
|
|
||||||
self.StyleSetSpec(stc.STC_P_DEFNAME,
|
|
||||||
"fore:#007F7F,bold")
|
|
||||||
self.StyleSetSpec(stc.STC_P_OPERATOR,
|
|
||||||
"")
|
|
||||||
self.StyleSetSpec(stc.STC_P_IDENTIFIER,
|
|
||||||
"")
|
|
||||||
self.StyleSetSpec(stc.STC_P_COMMENTBLOCK,
|
|
||||||
"fore:#7F7F7F")
|
|
||||||
self.StyleSetSpec(stc.STC_P_STRINGEOL,
|
|
||||||
"fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
|
|
||||||
|
|
||||||
def OnUpdateUI(self, event):
|
|
||||||
"""Check for matching braces."""
|
|
||||||
# If the auto-complete window is up let it do its thing.
|
|
||||||
if self.AutoCompActive() or self.CallTipActive():
|
|
||||||
return
|
|
||||||
braceAtCaret = -1
|
|
||||||
braceOpposite = -1
|
|
||||||
charBefore = None
|
|
||||||
caretPos = self.GetCurrentPos()
|
|
||||||
if caretPos > 0:
|
|
||||||
charBefore = self.GetCharAt(caretPos - 1)
|
|
||||||
styleBefore = self.GetStyleAt(caretPos - 1)
|
|
||||||
|
|
||||||
# Check before.
|
|
||||||
if charBefore and chr(charBefore) in '[]{}()' \
|
|
||||||
and styleBefore == stc.STC_P_OPERATOR:
|
|
||||||
braceAtCaret = caretPos - 1
|
|
||||||
|
|
||||||
# Check after.
|
|
||||||
if braceAtCaret < 0:
|
|
||||||
charAfter = self.GetCharAt(caretPos)
|
|
||||||
styleAfter = self.GetStyleAt(caretPos)
|
|
||||||
if charAfter and chr(charAfter) in '[]{}()' \
|
|
||||||
and styleAfter == stc.STC_P_OPERATOR:
|
|
||||||
braceAtCaret = caretPos
|
|
||||||
|
|
||||||
if braceAtCaret >= 0:
|
|
||||||
braceOpposite = self.BraceMatch(braceAtCaret)
|
|
||||||
|
|
||||||
if braceAtCaret != -1 and braceOpposite == -1:
|
|
||||||
self.BraceBadLight(braceAtCaret)
|
|
||||||
else:
|
|
||||||
self.BraceHighlight(braceAtCaret, braceOpposite)
|
|
||||||
|
|
||||||
def CanCopy(self):
|
|
||||||
"""Return True if text is selected and can be copied."""
|
|
||||||
return self.GetSelectionStart() != self.GetSelectionEnd()
|
|
||||||
|
|
||||||
def CanCut(self):
|
|
||||||
"""Return True if text is selected and can be cut."""
|
|
||||||
return self.CanCopy() and self.CanEdit()
|
|
||||||
|
|
||||||
def CanEdit(self):
|
|
||||||
"""Return True if editing should succeed."""
|
|
||||||
return not self.GetReadOnly()
|
|
||||||
|
|
||||||
def CanPaste(self):
|
|
||||||
"""Return True if pasting should succeed."""
|
|
||||||
return stc.StyledTextCtrl.CanPaste(self) and self.CanEdit()
|
|
@@ -1,332 +0,0 @@
|
|||||||
"""Filling is the gui tree control through which a user can navigate
|
|
||||||
the local namespace or any object."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
|
|
||||||
import dispatcher
|
|
||||||
import editwindow
|
|
||||||
import inspect
|
|
||||||
import introspect
|
|
||||||
import keyword
|
|
||||||
import sys
|
|
||||||
import types
|
|
||||||
from version import VERSION
|
|
||||||
|
|
||||||
|
|
||||||
COMMONTYPES = [getattr(types, t) for t in dir(types) \
|
|
||||||
if not t.startswith('_') \
|
|
||||||
and t not in ('ClassType', 'InstanceType', 'ModuleType')]
|
|
||||||
|
|
||||||
DOCTYPES = ('BuiltinFunctionType', 'BuiltinMethodType', 'ClassType',
|
|
||||||
'FunctionType', 'GeneratorType', 'InstanceType',
|
|
||||||
'LambdaType', 'MethodType', 'ModuleType',
|
|
||||||
'UnboundMethodType', 'method-wrapper')
|
|
||||||
|
|
||||||
SIMPLETYPES = [getattr(types, t) for t in dir(types) \
|
|
||||||
if not t.startswith('_') and t not in DOCTYPES]
|
|
||||||
|
|
||||||
del t
|
|
||||||
|
|
||||||
try:
|
|
||||||
COMMONTYPES.append(type(''.__repr__)) # Method-wrapper in version 2.2.x.
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class FillingTree(wx.TreeCtrl):
|
|
||||||
"""FillingTree based on TreeCtrl."""
|
|
||||||
|
|
||||||
name = 'Filling Tree'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
|
||||||
size=wx.DefaultSize, style=wx.TR_DEFAULT_STYLE,
|
|
||||||
rootObject=None, rootLabel=None, rootIsNamespace=False,
|
|
||||||
static=False):
|
|
||||||
"""Create FillingTree instance."""
|
|
||||||
wx.TreeCtrl.__init__(self, parent, id, pos, size, style)
|
|
||||||
self.rootIsNamespace = rootIsNamespace
|
|
||||||
import __main__
|
|
||||||
if rootObject is None:
|
|
||||||
rootObject = __main__.__dict__
|
|
||||||
self.rootIsNamespace = True
|
|
||||||
if rootObject is __main__.__dict__ and rootLabel is None:
|
|
||||||
rootLabel = 'locals()'
|
|
||||||
if not rootLabel:
|
|
||||||
rootLabel = 'Ingredients'
|
|
||||||
rootData = wx.TreeItemData(rootObject)
|
|
||||||
self.item = self.root = self.AddRoot(rootLabel, -1, -1, rootData)
|
|
||||||
self.SetItemHasChildren(self.root, self.objHasChildren(rootObject))
|
|
||||||
wx.EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding)
|
|
||||||
wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed)
|
|
||||||
wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
|
|
||||||
wx.EVT_TREE_ITEM_ACTIVATED(self, self.GetId(), self.OnItemActivated)
|
|
||||||
if not static:
|
|
||||||
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
|
||||||
|
|
||||||
def push(self, command, more):
|
|
||||||
"""Receiver for Interpreter.push signal."""
|
|
||||||
self.display()
|
|
||||||
|
|
||||||
def OnItemExpanding(self, event):
|
|
||||||
"""Add children to the item."""
|
|
||||||
busy = wx.BusyCursor()
|
|
||||||
item = event.GetItem()
|
|
||||||
if self.IsExpanded(item):
|
|
||||||
return
|
|
||||||
self.addChildren(item)
|
|
||||||
# self.SelectItem(item)
|
|
||||||
|
|
||||||
def OnItemCollapsed(self, event):
|
|
||||||
"""Remove all children from the item."""
|
|
||||||
busy = wx.BusyCursor()
|
|
||||||
item = event.GetItem()
|
|
||||||
# self.CollapseAndReset(item)
|
|
||||||
# self.DeleteChildren(item)
|
|
||||||
# self.SelectItem(item)
|
|
||||||
|
|
||||||
def OnSelChanged(self, event):
|
|
||||||
"""Display information about the item."""
|
|
||||||
busy = wx.BusyCursor()
|
|
||||||
self.item = event.GetItem()
|
|
||||||
self.display()
|
|
||||||
|
|
||||||
def OnItemActivated(self, event):
|
|
||||||
"""Launch a DirFrame."""
|
|
||||||
item = event.GetItem()
|
|
||||||
text = self.getFullName(item)
|
|
||||||
obj = self.GetPyData(item)
|
|
||||||
frame = FillingFrame(parent=self, size=(600, 100), rootObject=obj,
|
|
||||||
rootLabel=text, rootIsNamespace=False)
|
|
||||||
frame.Show()
|
|
||||||
|
|
||||||
def objHasChildren(self, obj):
|
|
||||||
"""Return true if object has children."""
|
|
||||||
if self.objGetChildren(obj):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def objGetChildren(self, obj):
|
|
||||||
"""Return dictionary with attributes or contents of object."""
|
|
||||||
busy = wx.BusyCursor()
|
|
||||||
otype = type(obj)
|
|
||||||
if otype is types.DictType \
|
|
||||||
or str(otype)[17:23] == 'BTrees' and hasattr(obj, 'keys'):
|
|
||||||
return obj
|
|
||||||
d = {}
|
|
||||||
if otype is types.ListType or otype is types.TupleType:
|
|
||||||
for n in range(len(obj)):
|
|
||||||
key = '[' + str(n) + ']'
|
|
||||||
d[key] = obj[n]
|
|
||||||
if otype not in COMMONTYPES:
|
|
||||||
for key in introspect.getAttributeNames(obj):
|
|
||||||
# Believe it or not, some attributes can disappear,
|
|
||||||
# such as the exc_traceback attribute of the sys
|
|
||||||
# module. So this is nested in a try block.
|
|
||||||
try:
|
|
||||||
d[key] = getattr(obj, key)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return d
|
|
||||||
|
|
||||||
def addChildren(self, item):
|
|
||||||
self.DeleteChildren(item)
|
|
||||||
obj = self.GetPyData(item)
|
|
||||||
children = self.objGetChildren(obj)
|
|
||||||
if not children:
|
|
||||||
return
|
|
||||||
keys = children.keys()
|
|
||||||
keys.sort(lambda x, y: cmp(str(x).lower(), str(y).lower()))
|
|
||||||
for key in keys:
|
|
||||||
itemtext = str(key)
|
|
||||||
# Show string dictionary items with single quotes, except
|
|
||||||
# for the first level of items, if they represent a
|
|
||||||
# namespace.
|
|
||||||
if type(obj) is types.DictType \
|
|
||||||
and type(key) is types.StringType \
|
|
||||||
and (item != self.root \
|
|
||||||
or (item == self.root and not self.rootIsNamespace)):
|
|
||||||
itemtext = repr(key)
|
|
||||||
child = children[key]
|
|
||||||
data = wx.TreeItemData(child)
|
|
||||||
branch = self.AppendItem(parent=item, text=itemtext, data=data)
|
|
||||||
self.SetItemHasChildren(branch, self.objHasChildren(child))
|
|
||||||
|
|
||||||
def display(self):
|
|
||||||
item = self.item
|
|
||||||
if self.IsExpanded(item):
|
|
||||||
self.addChildren(item)
|
|
||||||
self.setText('')
|
|
||||||
obj = self.GetPyData(item)
|
|
||||||
if wx.Platform == '__WXMSW__':
|
|
||||||
if obj is None: # Windows bug fix.
|
|
||||||
return
|
|
||||||
self.SetItemHasChildren(item, self.objHasChildren(obj))
|
|
||||||
otype = type(obj)
|
|
||||||
text = ''
|
|
||||||
text += self.getFullName(item)
|
|
||||||
text += '\n\nType: ' + str(otype)
|
|
||||||
try:
|
|
||||||
value = str(obj)
|
|
||||||
except:
|
|
||||||
value = ''
|
|
||||||
if otype is types.StringType or otype is types.UnicodeType:
|
|
||||||
value = repr(obj)
|
|
||||||
text += '\n\nValue: ' + value
|
|
||||||
if otype not in SIMPLETYPES:
|
|
||||||
try:
|
|
||||||
text += '\n\nDocstring:\n\n"""' + \
|
|
||||||
inspect.getdoc(obj).strip() + '"""'
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if otype is types.InstanceType:
|
|
||||||
try:
|
|
||||||
text += '\n\nClass Definition:\n\n' + \
|
|
||||||
inspect.getsource(obj.__class__)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
text += '\n\nSource Code:\n\n' + \
|
|
||||||
inspect.getsource(obj)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
self.setText(text)
|
|
||||||
|
|
||||||
def getFullName(self, item, partial=''):
|
|
||||||
"""Return a syntactically proper name for item."""
|
|
||||||
name = self.GetItemText(item)
|
|
||||||
parent = None
|
|
||||||
obj = None
|
|
||||||
if item != self.root:
|
|
||||||
parent = self.GetItemParent(item)
|
|
||||||
obj = self.GetPyData(parent)
|
|
||||||
# Apply dictionary syntax to dictionary items, except the root
|
|
||||||
# and first level children of a namepace.
|
|
||||||
if (type(obj) is types.DictType \
|
|
||||||
or str(type(obj))[17:23] == 'BTrees' \
|
|
||||||
and hasattr(obj, 'keys')) \
|
|
||||||
and ((item != self.root and parent != self.root) \
|
|
||||||
or (parent == self.root and not self.rootIsNamespace)):
|
|
||||||
name = '[' + name + ']'
|
|
||||||
# Apply dot syntax to multipart names.
|
|
||||||
if partial:
|
|
||||||
if partial[0] == '[':
|
|
||||||
name += partial
|
|
||||||
else:
|
|
||||||
name += '.' + partial
|
|
||||||
# Repeat for everything but the root item
|
|
||||||
# and first level children of a namespace.
|
|
||||||
if (item != self.root and parent != self.root) \
|
|
||||||
or (parent == self.root and not self.rootIsNamespace):
|
|
||||||
name = self.getFullName(parent, partial=name)
|
|
||||||
return name
|
|
||||||
|
|
||||||
def setText(self, text):
|
|
||||||
"""Display information about the current selection."""
|
|
||||||
|
|
||||||
# This method will likely be replaced by the enclosing app to
|
|
||||||
# do something more interesting, like write to a text control.
|
|
||||||
print text
|
|
||||||
|
|
||||||
def setStatusText(self, text):
|
|
||||||
"""Display status information."""
|
|
||||||
|
|
||||||
# This method will likely be replaced by the enclosing app to
|
|
||||||
# do something more interesting, like write to a status bar.
|
|
||||||
print text
|
|
||||||
|
|
||||||
|
|
||||||
class FillingText(editwindow.EditWindow):
|
|
||||||
"""FillingText based on StyledTextCtrl."""
|
|
||||||
|
|
||||||
name = 'Filling Text'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
|
||||||
size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
|
|
||||||
static=False):
|
|
||||||
"""Create FillingText instance."""
|
|
||||||
editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
|
|
||||||
# Configure various defaults and user preferences.
|
|
||||||
self.SetReadOnly(True)
|
|
||||||
self.SetWrapMode(True)
|
|
||||||
self.SetMarginWidth(1, 0)
|
|
||||||
if not static:
|
|
||||||
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
|
||||||
|
|
||||||
def push(self, command, more):
|
|
||||||
"""Receiver for Interpreter.push signal."""
|
|
||||||
self.Refresh()
|
|
||||||
|
|
||||||
def SetText(self, *args, **kwds):
|
|
||||||
self.SetReadOnly(False)
|
|
||||||
editwindow.EditWindow.SetText(self, *args, **kwds)
|
|
||||||
self.SetReadOnly(True)
|
|
||||||
|
|
||||||
|
|
||||||
class Filling(wx.SplitterWindow):
|
|
||||||
"""Filling based on wxSplitterWindow."""
|
|
||||||
|
|
||||||
name = 'Filling'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
|
||||||
size=wx.DefaultSize, style=wx.SP_3D,
|
|
||||||
name='Filling Window', rootObject=None,
|
|
||||||
rootLabel=None, rootIsNamespace=False, static=False):
|
|
||||||
"""Create a Filling instance."""
|
|
||||||
wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
|
||||||
self.tree = FillingTree(parent=self, rootObject=rootObject,
|
|
||||||
rootLabel=rootLabel,
|
|
||||||
rootIsNamespace=rootIsNamespace,
|
|
||||||
static=static)
|
|
||||||
self.text = FillingText(parent=self, static=static)
|
|
||||||
self.SplitVertically(self.tree, self.text, 130)
|
|
||||||
self.SetMinimumPaneSize(1)
|
|
||||||
# Override the filling so that descriptions go to FillingText.
|
|
||||||
self.tree.setText = self.text.SetText
|
|
||||||
# Display the root item.
|
|
||||||
## self.tree.SelectItem(self.tree.root)
|
|
||||||
self.tree.display()
|
|
||||||
|
|
||||||
|
|
||||||
class FillingFrame(wx.Frame):
|
|
||||||
"""Frame containing the namespace tree component."""
|
|
||||||
|
|
||||||
name = 'Filling Frame'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyFilling',
|
|
||||||
pos=wx.DefaultPosition, size=(600, 400),
|
|
||||||
style=wx.DEFAULT_FRAME_STYLE, rootObject=None,
|
|
||||||
rootLabel=None, rootIsNamespace=False, static=False):
|
|
||||||
"""Create FillingFrame instance."""
|
|
||||||
wx.Frame.__init__(self, parent, id, title, pos, size, style)
|
|
||||||
intro = 'PyFilling - The Tastiest Namespace Inspector'
|
|
||||||
self.CreateStatusBar()
|
|
||||||
self.SetStatusText(intro)
|
|
||||||
import images
|
|
||||||
self.SetIcon(images.getPyIcon())
|
|
||||||
self.filling = Filling(parent=self, rootObject=rootObject,
|
|
||||||
rootLabel=rootLabel,
|
|
||||||
rootIsNamespace=rootIsNamespace,
|
|
||||||
static=static)
|
|
||||||
# Override so that status messages go to the status bar.
|
|
||||||
self.filling.tree.setStatusText = self.SetStatusText
|
|
||||||
|
|
||||||
|
|
||||||
class App(wx.App):
|
|
||||||
"""PyFilling standalone application."""
|
|
||||||
|
|
||||||
def OnInit(self):
|
|
||||||
wx.InitAllImageHandlers()
|
|
||||||
self.fillingFrame = FillingFrame()
|
|
||||||
self.fillingFrame.Show(True)
|
|
||||||
self.SetTopWindow(self.fillingFrame)
|
|
||||||
return True
|
|
@@ -1,362 +0,0 @@
|
|||||||
"""Base frame with menu."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
from version import VERSION
|
|
||||||
|
|
||||||
|
|
||||||
ID_NEW = wx.ID_NEW
|
|
||||||
ID_OPEN = wx.ID_OPEN
|
|
||||||
ID_REVERT = wx.ID_REVERT
|
|
||||||
ID_CLOSE = wx.ID_CLOSE
|
|
||||||
ID_SAVE = wx.ID_SAVE
|
|
||||||
ID_SAVEAS = wx.ID_SAVEAS
|
|
||||||
ID_PRINT = wx.ID_PRINT
|
|
||||||
ID_EXIT = wx.ID_EXIT
|
|
||||||
ID_UNDO = wx.ID_UNDO
|
|
||||||
ID_REDO = wx.ID_REDO
|
|
||||||
ID_CUT = wx.ID_CUT
|
|
||||||
ID_COPY = wx.ID_COPY
|
|
||||||
ID_PASTE = wx.ID_PASTE
|
|
||||||
ID_CLEAR = wx.ID_CLEAR
|
|
||||||
ID_SELECTALL = wx.ID_SELECTALL
|
|
||||||
ID_ABOUT = wx.ID_ABOUT
|
|
||||||
ID_AUTOCOMP = wx.NewId()
|
|
||||||
ID_AUTOCOMP_SHOW = wx.NewId()
|
|
||||||
ID_AUTOCOMP_MAGIC = wx.NewId()
|
|
||||||
ID_AUTOCOMP_SINGLE = wx.NewId()
|
|
||||||
ID_AUTOCOMP_DOUBLE = wx.NewId()
|
|
||||||
ID_CALLTIPS = wx.NewId()
|
|
||||||
ID_CALLTIPS_SHOW = wx.NewId()
|
|
||||||
ID_COPY_PLUS = wx.NewId()
|
|
||||||
ID_NAMESPACE = wx.NewId()
|
|
||||||
ID_PASTE_PLUS = wx.NewId()
|
|
||||||
ID_WRAP = wx.NewId()
|
|
||||||
ID_USEAA = wx.NewId()
|
|
||||||
|
|
||||||
|
|
||||||
class Frame(wx.Frame):
|
|
||||||
"""Frame with standard menu items."""
|
|
||||||
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='Editor',
|
|
||||||
pos=wx.DefaultPosition, size=wx.DefaultSize,
|
|
||||||
style=wx.DEFAULT_FRAME_STYLE):
|
|
||||||
"""Create a Frame instance."""
|
|
||||||
wx.Frame.__init__(self, parent, id, title, pos, size, style)
|
|
||||||
self.CreateStatusBar()
|
|
||||||
self.SetStatusText('Frame')
|
|
||||||
import images
|
|
||||||
self.SetIcon(images.getPyIcon())
|
|
||||||
self.__createMenus()
|
|
||||||
wx.EVT_CLOSE(self, self.OnClose)
|
|
||||||
|
|
||||||
def OnClose(self, event):
|
|
||||||
"""Event handler for closing."""
|
|
||||||
self.Destroy()
|
|
||||||
|
|
||||||
def __createMenus(self):
|
|
||||||
m = self.fileMenu = wx.Menu()
|
|
||||||
m.Append(ID_NEW, '&New \tCtrl+N',
|
|
||||||
'New file')
|
|
||||||
m.Append(ID_OPEN, '&Open... \tCtrl+O',
|
|
||||||
'Open file')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(ID_REVERT, '&Revert \tCtrl+R',
|
|
||||||
'Revert to last saved version')
|
|
||||||
m.Append(ID_CLOSE, '&Close \tCtrl+W',
|
|
||||||
'Close file')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(ID_SAVE, '&Save... \tCtrl+S',
|
|
||||||
'Save file')
|
|
||||||
m.Append(ID_SAVEAS, 'Save &As \tShift+Ctrl+S',
|
|
||||||
'Save file with new name')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(ID_PRINT, '&Print... \tCtrl+P',
|
|
||||||
'Print file')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(ID_NAMESPACE, '&Update Namespace \tShift+Ctrl+N',
|
|
||||||
'Update namespace for autocompletion and calltips')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(ID_EXIT, 'E&xit', 'Exit Program')
|
|
||||||
|
|
||||||
m = self.editMenu = wx.Menu()
|
|
||||||
m.Append(ID_UNDO, '&Undo \tCtrl+Z',
|
|
||||||
'Undo the last action')
|
|
||||||
m.Append(ID_REDO, '&Redo \tCtrl+Y',
|
|
||||||
'Redo the last undone action')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(ID_CUT, 'Cu&t \tCtrl+X',
|
|
||||||
'Cut the selection')
|
|
||||||
m.Append(ID_COPY, '&Copy \tCtrl+C',
|
|
||||||
'Copy the selection')
|
|
||||||
m.Append(ID_COPY_PLUS, 'Cop&y Plus \tShift+Ctrl+C',
|
|
||||||
'Copy the selection - retaining prompts')
|
|
||||||
m.Append(ID_PASTE, '&Paste \tCtrl+V', 'Paste from clipboard')
|
|
||||||
m.Append(ID_PASTE_PLUS, 'Past&e Plus \tShift+Ctrl+V',
|
|
||||||
'Paste and run commands')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(ID_CLEAR, 'Cle&ar',
|
|
||||||
'Delete the selection')
|
|
||||||
m.Append(ID_SELECTALL, 'Select A&ll \tCtrl+A',
|
|
||||||
'Select all text')
|
|
||||||
|
|
||||||
m = self.autocompMenu = wx.Menu()
|
|
||||||
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion',
|
|
||||||
'Show auto completion list', wx.ITEM_CHECK)
|
|
||||||
m.Append(ID_AUTOCOMP_MAGIC, 'Include Magic Attributes',
|
|
||||||
'Include attributes visible to __getattr__ and __setattr__',
|
|
||||||
wx.ITEM_CHECK)
|
|
||||||
m.Append(ID_AUTOCOMP_SINGLE, 'Include Single Underscores',
|
|
||||||
'Include attibutes prefixed by a single underscore', wx.ITEM_CHECK)
|
|
||||||
m.Append(ID_AUTOCOMP_DOUBLE, 'Include Double Underscores',
|
|
||||||
'Include attibutes prefixed by a double underscore', wx.ITEM_CHECK)
|
|
||||||
|
|
||||||
m = self.calltipsMenu = wx.Menu()
|
|
||||||
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips',
|
|
||||||
'Show call tips with argument signature and docstring', wx.ITEM_CHECK)
|
|
||||||
|
|
||||||
m = self.optionsMenu = wx.Menu()
|
|
||||||
m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu,
|
|
||||||
'Auto Completion Options')
|
|
||||||
m.AppendMenu(ID_CALLTIPS, '&Call Tips', self.calltipsMenu,
|
|
||||||
'Call Tip Options')
|
|
||||||
m.Append(ID_WRAP, '&Wrap Lines',
|
|
||||||
'Wrap lines at right edge', wx.ITEM_CHECK)
|
|
||||||
if wx.Platform == "__WXMAC__":
|
|
||||||
m.Append(ID_USEAA, '&Use AntiAliasing',
|
|
||||||
'Use anti-aliased fonts', wx.ITEM_CHECK)
|
|
||||||
|
|
||||||
m = self.helpMenu = wx.Menu()
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(ID_ABOUT, '&About...', 'About this program')
|
|
||||||
|
|
||||||
b = self.menuBar = wx.MenuBar()
|
|
||||||
b.Append(self.fileMenu, '&File')
|
|
||||||
b.Append(self.editMenu, '&Edit')
|
|
||||||
b.Append(self.optionsMenu, '&Options')
|
|
||||||
b.Append(self.helpMenu, '&Help')
|
|
||||||
self.SetMenuBar(b)
|
|
||||||
|
|
||||||
wx.EVT_MENU(self, ID_NEW, self.OnFileNew)
|
|
||||||
wx.EVT_MENU(self, ID_OPEN, self.OnFileOpen)
|
|
||||||
wx.EVT_MENU(self, ID_REVERT, self.OnFileRevert)
|
|
||||||
wx.EVT_MENU(self, ID_CLOSE, self.OnFileClose)
|
|
||||||
wx.EVT_MENU(self, ID_SAVE, self.OnFileSave)
|
|
||||||
wx.EVT_MENU(self, ID_SAVEAS, self.OnFileSaveAs)
|
|
||||||
wx.EVT_MENU(self, ID_NAMESPACE, self.OnFileUpdateNamespace)
|
|
||||||
wx.EVT_MENU(self, ID_PRINT, self.OnFilePrint)
|
|
||||||
wx.EVT_MENU(self, ID_EXIT, self.OnExit)
|
|
||||||
wx.EVT_MENU(self, ID_UNDO, self.OnUndo)
|
|
||||||
wx.EVT_MENU(self, ID_REDO, self.OnRedo)
|
|
||||||
wx.EVT_MENU(self, ID_CUT, self.OnCut)
|
|
||||||
wx.EVT_MENU(self, ID_COPY, self.OnCopy)
|
|
||||||
wx.EVT_MENU(self, ID_COPY_PLUS, self.OnCopyPlus)
|
|
||||||
wx.EVT_MENU(self, ID_PASTE, self.OnPaste)
|
|
||||||
wx.EVT_MENU(self, ID_PASTE_PLUS, self.OnPastePlus)
|
|
||||||
wx.EVT_MENU(self, ID_CLEAR, self.OnClear)
|
|
||||||
wx.EVT_MENU(self, ID_SELECTALL, self.OnSelectAll)
|
|
||||||
wx.EVT_MENU(self, ID_ABOUT, self.OnAbout)
|
|
||||||
wx.EVT_MENU(self, ID_AUTOCOMP_SHOW, self.OnAutoCompleteShow)
|
|
||||||
wx.EVT_MENU(self, ID_AUTOCOMP_MAGIC, self.OnAutoCompleteMagic)
|
|
||||||
wx.EVT_MENU(self, ID_AUTOCOMP_SINGLE, self.OnAutoCompleteSingle)
|
|
||||||
wx.EVT_MENU(self, ID_AUTOCOMP_DOUBLE, self.OnAutoCompleteDouble)
|
|
||||||
wx.EVT_MENU(self, ID_CALLTIPS_SHOW, self.OnCallTipsShow)
|
|
||||||
wx.EVT_MENU(self, ID_WRAP, self.OnWrap)
|
|
||||||
wx.EVT_MENU(self, ID_USEAA, self.OnUseAA)
|
|
||||||
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_NEW, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_OPEN, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_REVERT, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_CLOSE, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_SAVE, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_SAVEAS, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_NAMESPACE, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_PRINT, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_UNDO, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_REDO, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_CUT, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_COPY, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_COPY_PLUS, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_PASTE, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_PASTE_PLUS, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_CLEAR, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_SELECTALL, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SHOW, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_MAGIC, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SINGLE, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_DOUBLE, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_CALLTIPS_SHOW, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_WRAP, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_USEAA, self.OnUpdateMenu)
|
|
||||||
|
|
||||||
def OnFileNew(self, event):
|
|
||||||
self.bufferNew()
|
|
||||||
|
|
||||||
def OnFileOpen(self, event):
|
|
||||||
self.bufferOpen()
|
|
||||||
|
|
||||||
def OnFileRevert(self, event):
|
|
||||||
self.bufferRevert()
|
|
||||||
|
|
||||||
def OnFileClose(self, event):
|
|
||||||
self.bufferClose()
|
|
||||||
|
|
||||||
def OnFileSave(self, event):
|
|
||||||
self.bufferSave()
|
|
||||||
|
|
||||||
def OnFileSaveAs(self, event):
|
|
||||||
self.bufferSaveAs()
|
|
||||||
|
|
||||||
def OnFileUpdateNamespace(self, event):
|
|
||||||
self.updateNamespace()
|
|
||||||
|
|
||||||
def OnFilePrint(self, event):
|
|
||||||
self.bufferPrint()
|
|
||||||
|
|
||||||
def OnExit(self, event):
|
|
||||||
self.Close(False)
|
|
||||||
|
|
||||||
def OnUndo(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.Undo()
|
|
||||||
|
|
||||||
def OnRedo(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.Redo()
|
|
||||||
|
|
||||||
def OnCut(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.Cut()
|
|
||||||
|
|
||||||
def OnCopy(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.Copy()
|
|
||||||
|
|
||||||
def OnCopyPlus(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.CopyWithPrompts()
|
|
||||||
|
|
||||||
def OnPaste(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.Paste()
|
|
||||||
|
|
||||||
def OnPastePlus(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.PasteAndRun()
|
|
||||||
|
|
||||||
def OnClear(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.Clear()
|
|
||||||
|
|
||||||
def OnSelectAll(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.SelectAll()
|
|
||||||
|
|
||||||
def OnAbout(self, event):
|
|
||||||
"""Display an About window."""
|
|
||||||
title = 'About'
|
|
||||||
text = 'Your message here.'
|
|
||||||
dialog = wx.MessageDialog(self, text, title,
|
|
||||||
wx.OK | wx.ICON_INFORMATION)
|
|
||||||
dialog.ShowModal()
|
|
||||||
dialog.Destroy()
|
|
||||||
|
|
||||||
def OnAutoCompleteShow(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.autoComplete = event.IsChecked()
|
|
||||||
|
|
||||||
def OnAutoCompleteMagic(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.autoCompleteIncludeMagic = event.IsChecked()
|
|
||||||
|
|
||||||
def OnAutoCompleteSingle(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.autoCompleteIncludeSingle = event.IsChecked()
|
|
||||||
|
|
||||||
def OnAutoCompleteDouble(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.autoCompleteIncludeDouble = event.IsChecked()
|
|
||||||
|
|
||||||
def OnCallTipsShow(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.autoCallTip = event.IsChecked()
|
|
||||||
|
|
||||||
def OnWrap(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.SetWrapMode(event.IsChecked())
|
|
||||||
|
|
||||||
def OnUseAA(self, event):
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
win.SetUseAntiAliasing(event.IsChecked())
|
|
||||||
|
|
||||||
|
|
||||||
def OnUpdateMenu(self, event):
|
|
||||||
"""Update menu items based on current status and context."""
|
|
||||||
win = wx.Window_FindFocus()
|
|
||||||
id = event.GetId()
|
|
||||||
event.Enable(True)
|
|
||||||
try:
|
|
||||||
if id == ID_NEW:
|
|
||||||
event.Enable(hasattr(self, 'bufferNew'))
|
|
||||||
elif id == ID_OPEN:
|
|
||||||
event.Enable(hasattr(self, 'bufferOpen'))
|
|
||||||
elif id == ID_REVERT:
|
|
||||||
event.Enable(hasattr(self, 'bufferRevert')
|
|
||||||
and self.hasBuffer())
|
|
||||||
elif id == ID_CLOSE:
|
|
||||||
event.Enable(hasattr(self, 'bufferClose')
|
|
||||||
and self.hasBuffer())
|
|
||||||
elif id == ID_SAVE:
|
|
||||||
event.Enable(hasattr(self, 'bufferSave')
|
|
||||||
and self.bufferHasChanged())
|
|
||||||
elif id == ID_SAVEAS:
|
|
||||||
event.Enable(hasattr(self, 'bufferSaveAs')
|
|
||||||
and self.hasBuffer())
|
|
||||||
elif id == ID_NAMESPACE:
|
|
||||||
event.Enable(hasattr(self, 'updateNamespace')
|
|
||||||
and self.hasBuffer())
|
|
||||||
elif id == ID_PRINT:
|
|
||||||
event.Enable(hasattr(self, 'bufferPrint')
|
|
||||||
and self.hasBuffer())
|
|
||||||
elif id == ID_UNDO:
|
|
||||||
event.Enable(win.CanUndo())
|
|
||||||
elif id == ID_REDO:
|
|
||||||
event.Enable(win.CanRedo())
|
|
||||||
elif id == ID_CUT:
|
|
||||||
event.Enable(win.CanCut())
|
|
||||||
elif id == ID_COPY:
|
|
||||||
event.Enable(win.CanCopy())
|
|
||||||
elif id == ID_COPY_PLUS:
|
|
||||||
event.Enable(win.CanCopy() and hasattr(win, 'CopyWithPrompts'))
|
|
||||||
elif id == ID_PASTE:
|
|
||||||
event.Enable(win.CanPaste())
|
|
||||||
elif id == ID_PASTE_PLUS:
|
|
||||||
event.Enable(win.CanPaste() and hasattr(win, 'PasteAndRun'))
|
|
||||||
elif id == ID_CLEAR:
|
|
||||||
event.Enable(win.CanCut())
|
|
||||||
elif id == ID_SELECTALL:
|
|
||||||
event.Enable(hasattr(win, 'SelectAll'))
|
|
||||||
elif id == ID_AUTOCOMP_SHOW:
|
|
||||||
event.Check(win.autoComplete)
|
|
||||||
elif id == ID_AUTOCOMP_MAGIC:
|
|
||||||
event.Check(win.autoCompleteIncludeMagic)
|
|
||||||
elif id == ID_AUTOCOMP_SINGLE:
|
|
||||||
event.Check(win.autoCompleteIncludeSingle)
|
|
||||||
elif id == ID_AUTOCOMP_DOUBLE:
|
|
||||||
event.Check(win.autoCompleteIncludeDouble)
|
|
||||||
elif id == ID_CALLTIPS_SHOW:
|
|
||||||
event.Check(win.autoCallTip)
|
|
||||||
elif id == ID_WRAP:
|
|
||||||
event.Check(win.GetWrapMode())
|
|
||||||
elif id == ID_USEAA:
|
|
||||||
event.Check(win.GetUseAntiAliasing())
|
|
||||||
else:
|
|
||||||
event.Enable(False)
|
|
||||||
except AttributeError:
|
|
||||||
# This menu option is not supported in the current context.
|
|
||||||
event.Enable(False)
|
|
@@ -1,72 +0,0 @@
|
|||||||
"""Support for icons."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import wx
|
|
||||||
import cStringIO
|
|
||||||
|
|
||||||
|
|
||||||
def getPyIcon():
|
|
||||||
icon = wx.EmptyIcon()
|
|
||||||
icon.CopyFromBitmap(getPyBitmap())
|
|
||||||
return icon
|
|
||||||
|
|
||||||
def getPyBitmap():
|
|
||||||
return wx.BitmapFromImage(getPyImage())
|
|
||||||
|
|
||||||
def getPyImage():
|
|
||||||
stream = cStringIO.StringIO(getPyData())
|
|
||||||
return wx.ImageFromStream(stream)
|
|
||||||
|
|
||||||
def getPyData():
|
|
||||||
return \
|
|
||||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
|
|
||||||
\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x04\
|
|
||||||
\x95IDATx\x9c\xed\x97?lSG\x1c\xc7?\x97\x98\xd8Q\xa3\xdeY\xa2j\x06\xa4\xf7"QJ\
|
|
||||||
\xbb<3@\x01\xa9\xc2\x0c\xa8!\x1d\x1c6\xcaB\xa8D[uI2\xf4\x8f\xe8\x103\xb4\xa2\
|
|
||||||
,5\x0b\x03\x032C\xab\xc0\x92dh:t\xc0)*E\xcd@<Q\x01Rl\t\xd4D\xaa\xe4{R\xd0{&\
|
|
||||||
\xa5\xd7\xe1\xfc\xec\xe7\xfciR\x08e\xe9O\xb2\xee|\xfe\xbd\xfb}~\xdf\xdf\xbd\
|
|
||||||
\xbb\xb3PJ\xf1"\xad\xe3\x85F\xff\x1f\xe0y\x03h\xad\xcdA\xc7~\xb4\xd6f-\x9f\
|
|
||||||
\xc4\xf3\x0c>Y\x1c#\x97\xddCUk\xf4B\x8d3\x9f\x8d\x9a\x9bU%\xe2~b\xab\xdf\x82\
|
|
||||||
\x83N+\xd3\xe92\\\x1f\xcf\x93\xdd\x9f\xa1\xaa5\x95\xf9\n\xe7\xf3y\xe2\x10[V\
|
|
||||||
\x82H\xe6\xd3G\x1dN\xf7\xc3\xa7\xc7a\xc0\x83\xc3\xc7\xf3\xcc\xcc\xcd\xe3(\
|
|
||||||
\x85\xdb\xe7\xf2\xc9\xe8X\x1b\xe43+\x10\xd5\xb6\x94\x87Z\xe8\x90NU\x91I@\x00\
|
|
||||||
\x06\xbe\x18\xb7J\x98\xca$`\x98\xb9]&{,\x8fRV\x85\xa7V@k\x9bq)o\x83+\t\xe9T\
|
|
||||||
\xd5f\x95\x02\x91\xb4~_\r\xd9\xb6\xbaP\x03\x04n\x9f\xcbDa\xb8\t\xfe\xaf\x17a\
|
|
||||||
<\xe3\xc8\x94lo\x9b\xd6\xa8\xf4\x80\x07\xb7o\xcd\xe0\x0c\x0e\xa2R\x8a\xb4\
|
|
||||||
\x93n\xbal\x1a`e\xe0U\xc1\xd6\xb0\xb8\n\x99\x91"\x93\xaf\xba\xe4\x0ed\xda|6,\
|
|
||||||
\x81\xd6\xda\x9c|\xab]\xea\xcd\x04\x8f\x9b\t\xad\nz\xa1\x02\x80\xdb\xe7R\x1a\
|
|
||||||
\xcf\xa3\xb56\xeb\x02D5\x9e\xf8\xdc\xe1T\xff\xd3\x05\x8e\x82\x83U\xe1Z\xb1\
|
|
||||||
\x18\x9b\xbf\x06\xacQ\x82H\xea\x01/Z@Ut\x08R\xb4$}\x16\xd3\x81A&%\xde\xee\
|
|
||||||
\xbev\x80x\xe0]{\xb2\x1cR\xa5\xe6C*\xb5\xf1\xc4Q\xa6"e\xfbQ\x1b\x8dE\xe6\x87\
|
|
||||||
>\xaa[Q\xadi\x0b\xb0r\x8f\x9e.\xc3t\xb9\xc4]\xaf5\xf6\xfe\xdb\xddt&\x02\xfa\
|
|
||||||
\x9c\xf5\x01\xe2A\xa2\xbeX\x01>]ntR\x12\xe3[\x00\x01\x98\x89\x11[_\xed\xafn\
|
|
||||||
\xab\x81U\xa0\xe7I7\x00\x97o\x04\xcd\x89\x06<;\xe9\x80\x07]i\x97\xc17\x1f\
|
|
||||||
\xd2\xd3\x91`\xe9\xaf?\x01p^Y\x06Z\n\xfau8?a\xfb]i\x97\xec\xa1\x8c\x05(|\xd8\
|
|
||||||
N\xba\xb3\xab\x87\xfb\x8f\x97\xd8\xd9\xd5\x03\xc0\xfd\xc7K\xec\xd8\xd6\xdd\
|
|
||||||
\xfc\xfd\xc1r\xd0\xf4\x01\xda~\x03H\xf4\x04\xd4j :\xb75\xc7\xae\xfd\xbcLW\
|
|
||||||
\xda\xa5\xf0M\x1e\t\xcc\xcc\xcdq\xa9P@\x8c\xf5fL\xdaHF\x16g\x9a\x19\xad\xcc\
|
|
||||||
\xee\xcb\xa3\n\xad\xa1\xda\xf1\x08\xef\xe5\x97x\xf8\xc8f\xf8\xc7\x93:\xdb;\
|
|
||||||
\x93M\xc8\x08j\xc7\xb6n\x1e,\x07m`\x97o\x04|;>\xd1T\xc4\x17\x8a\x13\xb9\xc3\
|
|
||||||
\x88\x01\x0fs\xa4\x9cc}\xf3A\x190\x82\x1f\xddR{-\x1bV\xfc\xd8f\xba\xbd3\xd9\
|
|
||||||
\x06\x15\x07\xbb\xf8\xd3\x12\xdf]-"\x93\xb2\xb1C*\xde\xcd\x1d\xde\xccN(\xc1\
|
|
||||||
\xae\x17"\xd0#+<j\x17m{\xcd\x9bj\x00.\xaf\xf0Xb\xb8\xdfA\xa6\x14\x18\x03\x06\
|
|
||||||
\xb4o\xcf\x8d\xc4\xbervc\x86M\xdaz\x80\x00\x95T\x19?\xd0 @&%~c\xbc\xe3W\xaf\
|
|
||||||
\xb4e\x00\xffh\xc6@\xbd\x11\xbc\xde\x1a\xfe\xef.\xa5\xa2q4\n0\x81\xad\xe9\
|
|
||||||
\xae7<\x12\xaf\xf5\xc2hy\xaa\xe97\x9cS\\\x98\xb2\x0e\x03\xb1\xcdhW\xdaC\x1a\
|
|
||||||
\xa0\xa2\xa0\x0e"\x14`\xb0Y\x85\x1b\x1f\x12\xaa7\x03)\xd9\x84\xa8\xccW\xb8{\
|
|
||||||
\xa7L\xe2\xde\x02\x94\xc6Gp_\xcf\x80\x90\x98\xd0g\xf4\xac\x82Pc\x82\x1a\xd5\
|
|
||||||
\x10\x08}&\xa7J\xcc\xde.1]m\x80\xf6+\xee\xfd\xae\x9bo\xc4\xf0;\x80\xef\x90\
|
|
||||||
\x0e\x04\x06`Q!\x02\x05\xc2 \xb5\xc2\x95\x15d\xb4C&[\xf7\xd2\x04\x80\xbb\xdb\
|
|
||||||
\x9e\xd1\x8e\x02\x90\xd8\xd4$ I\x87\x80\xf1\xf1\xdc!4\xc3\x88\x94}\xd8,TH\
|
|
||||||
\xbb.5m\xf0C\x9f3\x1f\r\x01\x96.\x82\x1a9\xe9Q\xb8\xd2\xf8\xf25\x0c\xbe\xe7#\
|
|
||||||
\x92\x12\x1d[\x03\t\x00E\xf4\xa6\t\xaaZ7`$\x18\x90\xf8\xf8\x80JK\x94\xa1\x01\
|
|
||||||
\x07\xb8\x0e~X\xc3\xed\x16\xf8)\xf8~j\x12B\rI\x89_\xf7!0 \x04\xf9Q\xc0\x18\
|
|
||||||
\x0c\xd1i\xea\x13\xb7\x04\xc0\x89\x93C\xabj\xb6\xf7@\x96\xd9_J|0:\x86R\n\xb7\
|
|
||||||
\xd7@\xaa%\x9d\xa3$\xba.\x90RA]\xe3\x87\x1a\x89\xdd\xefeR\xc2\x1a\'\xa8\x1f\
|
|
||||||
\x82\x0e-@m\xd1\xde\x076\xbc\x15\x97~(\x9a\x89b\x9e\xd9[s\xab!\xf7g\xd6\x1c\
|
|
||||||
\x8f\xdb\xbel\x8e\xa1S\xc7\xda\xc6\xe6\xee\xccs\xe9\xdcYnV\x95\xd8\xf2?&q+\
|
|
||||||
\x9c\x1b1\xf3\xbf\xcd3{\xfdJ\xdb\xf8\xde\xfd\x19.\\\xad\x08\x80\xbf\x01\xd1\
|
|
||||||
\x86\xfa\x8b\xc7\xc0\xc8\xb7\x00\x00\x00\x00IEND\xaeB`\x82'
|
|
@@ -1,126 +0,0 @@
|
|||||||
"""Interpreter executes Python commands."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from code import InteractiveInterpreter
|
|
||||||
import dispatcher
|
|
||||||
import introspect
|
|
||||||
import wx
|
|
||||||
|
|
||||||
class Interpreter(InteractiveInterpreter):
|
|
||||||
"""Interpreter based on code.InteractiveInterpreter."""
|
|
||||||
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, locals=None, rawin=None,
|
|
||||||
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr):
|
|
||||||
"""Create an interactive interpreter object."""
|
|
||||||
InteractiveInterpreter.__init__(self, locals=locals)
|
|
||||||
self.stdin = stdin
|
|
||||||
self.stdout = stdout
|
|
||||||
self.stderr = stderr
|
|
||||||
if rawin:
|
|
||||||
import __builtin__
|
|
||||||
__builtin__.raw_input = rawin
|
|
||||||
del __builtin__
|
|
||||||
copyright = 'Type "help", "copyright", "credits" or "license"'
|
|
||||||
copyright += ' for more information.'
|
|
||||||
self.introText = 'Python %s on %s%s%s' % \
|
|
||||||
(sys.version, sys.platform, os.linesep, copyright)
|
|
||||||
try:
|
|
||||||
sys.ps1
|
|
||||||
except AttributeError:
|
|
||||||
sys.ps1 = '>>> '
|
|
||||||
try:
|
|
||||||
sys.ps2
|
|
||||||
except AttributeError:
|
|
||||||
sys.ps2 = '... '
|
|
||||||
self.more = 0
|
|
||||||
# List of lists to support recursive push().
|
|
||||||
self.commandBuffer = []
|
|
||||||
self.startupScript = os.environ.get('PYTHONSTARTUP')
|
|
||||||
|
|
||||||
def push(self, command):
|
|
||||||
"""Send command to the interpreter to be executed.
|
|
||||||
|
|
||||||
Because this may be called recursively, we append a new list
|
|
||||||
onto the commandBuffer list and then append commands into
|
|
||||||
that. If the passed in command is part of a multi-line
|
|
||||||
command we keep appending the pieces to the last list in
|
|
||||||
commandBuffer until we have a complete command. If not, we
|
|
||||||
delete that last list."""
|
|
||||||
|
|
||||||
# In case the command is unicode try encoding it
|
|
||||||
if type(command) == unicode:
|
|
||||||
try:
|
|
||||||
command = command.encode(wx.GetDefaultPyEncoding())
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
pass # otherwise leave it alone
|
|
||||||
|
|
||||||
if not self.more:
|
|
||||||
try: del self.commandBuffer[-1]
|
|
||||||
except IndexError: pass
|
|
||||||
if not self.more: self.commandBuffer.append([])
|
|
||||||
self.commandBuffer[-1].append(command)
|
|
||||||
source = '\n'.join(self.commandBuffer[-1])
|
|
||||||
more = self.more = self.runsource(source)
|
|
||||||
dispatcher.send(signal='Interpreter.push', sender=self,
|
|
||||||
command=command, more=more, source=source)
|
|
||||||
return more
|
|
||||||
|
|
||||||
def runsource(self, source):
|
|
||||||
"""Compile and run source code in the interpreter."""
|
|
||||||
stdin, stdout, stderr = sys.stdin, sys.stdout, sys.stderr
|
|
||||||
sys.stdin, sys.stdout, sys.stderr = \
|
|
||||||
self.stdin, self.stdout, self.stderr
|
|
||||||
more = InteractiveInterpreter.runsource(self, source)
|
|
||||||
# If sys.std* is still what we set it to, then restore it.
|
|
||||||
# But, if the executed source changed sys.std*, assume it was
|
|
||||||
# meant to be changed and leave it. Power to the people.
|
|
||||||
if sys.stdin == self.stdin:
|
|
||||||
sys.stdin = stdin
|
|
||||||
if sys.stdout == self.stdout:
|
|
||||||
sys.stdout = stdout
|
|
||||||
if sys.stderr == self.stderr:
|
|
||||||
sys.stderr = stderr
|
|
||||||
return more
|
|
||||||
|
|
||||||
def getAutoCompleteKeys(self):
|
|
||||||
"""Return list of auto-completion keycodes."""
|
|
||||||
return [ord('.')]
|
|
||||||
|
|
||||||
def getAutoCompleteList(self, command='', *args, **kwds):
|
|
||||||
"""Return list of auto-completion options for a command.
|
|
||||||
|
|
||||||
The list of options will be based on the locals namespace."""
|
|
||||||
stdin, stdout, stderr = sys.stdin, sys.stdout, sys.stderr
|
|
||||||
sys.stdin, sys.stdout, sys.stderr = \
|
|
||||||
self.stdin, self.stdout, self.stderr
|
|
||||||
l = introspect.getAutoCompleteList(command, self.locals,
|
|
||||||
*args, **kwds)
|
|
||||||
sys.stdin, sys.stdout, sys.stderr = stdin, stdout, stderr
|
|
||||||
return l
|
|
||||||
|
|
||||||
def getCallTip(self, command='', *args, **kwds):
|
|
||||||
"""Return call tip text for a command.
|
|
||||||
|
|
||||||
Call tip information will be based on the locals namespace."""
|
|
||||||
return introspect.getCallTip(command, self.locals, *args, **kwds)
|
|
||||||
|
|
||||||
|
|
||||||
class InterpreterAlaCarte(Interpreter):
|
|
||||||
"""Demo Interpreter."""
|
|
||||||
|
|
||||||
def __init__(self, locals, rawin, stdin, stdout, stderr,
|
|
||||||
ps1='main prompt', ps2='continuation prompt'):
|
|
||||||
"""Create an interactive interpreter object."""
|
|
||||||
Interpreter.__init__(self, locals=locals, rawin=rawin,
|
|
||||||
stdin=stdin, stdout=stdout, stderr=stderr)
|
|
||||||
sys.ps1 = ps1
|
|
||||||
sys.ps2 = ps2
|
|
||||||
|
|
||||||
|
|
@@ -1,382 +0,0 @@
|
|||||||
"""Provides a variety of introspective-type support functions for
|
|
||||||
things like call tips and command auto completion."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
from __future__ import nested_scopes
|
|
||||||
|
|
||||||
import cStringIO
|
|
||||||
import inspect
|
|
||||||
import sys
|
|
||||||
import tokenize
|
|
||||||
import types
|
|
||||||
import wx
|
|
||||||
|
|
||||||
def getAutoCompleteList(command='', locals=None, includeMagic=1,
|
|
||||||
includeSingle=1, includeDouble=1):
|
|
||||||
"""Return list of auto-completion options for command.
|
|
||||||
|
|
||||||
The list of options will be based on the locals namespace."""
|
|
||||||
attributes = []
|
|
||||||
# Get the proper chunk of code from the command.
|
|
||||||
root = getRoot(command, terminator='.')
|
|
||||||
try:
|
|
||||||
if locals is not None:
|
|
||||||
object = eval(root, locals)
|
|
||||||
else:
|
|
||||||
object = eval(root)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
attributes = getAttributeNames(object, includeMagic,
|
|
||||||
includeSingle, includeDouble)
|
|
||||||
return attributes
|
|
||||||
|
|
||||||
def getAttributeNames(object, includeMagic=1, includeSingle=1,
|
|
||||||
includeDouble=1):
|
|
||||||
"""Return list of unique attributes, including inherited, for object."""
|
|
||||||
attributes = []
|
|
||||||
dict = {}
|
|
||||||
if not hasattrAlwaysReturnsTrue(object):
|
|
||||||
# Add some attributes that don't always get picked up.
|
|
||||||
special_attrs = ['__bases__', '__class__', '__dict__', '__name__',
|
|
||||||
'func_closure', 'func_code', 'func_defaults',
|
|
||||||
'func_dict', 'func_doc', 'func_globals', 'func_name']
|
|
||||||
attributes += [attr for attr in special_attrs \
|
|
||||||
if hasattr(object, attr)]
|
|
||||||
if includeMagic:
|
|
||||||
try: attributes += object._getAttributeNames()
|
|
||||||
except: pass
|
|
||||||
# Get all attribute names.
|
|
||||||
str_type = str(type(object))
|
|
||||||
if str_type == "<type 'array'>":
|
|
||||||
attributes += dir(object)
|
|
||||||
else:
|
|
||||||
attrdict = getAllAttributeNames(object)
|
|
||||||
# Store the object's dir.
|
|
||||||
object_dir = dir(object)
|
|
||||||
for (obj_type_name, technique, count), attrlist in attrdict.items():
|
|
||||||
# This complexity is necessary to avoid accessing all the
|
|
||||||
# attributes of the object. This is very handy for objects
|
|
||||||
# whose attributes are lazily evaluated.
|
|
||||||
if type(object).__name__ == obj_type_name and technique == 'dir':
|
|
||||||
attributes += attrlist
|
|
||||||
else:
|
|
||||||
attributes += [attr for attr in attrlist \
|
|
||||||
if attr not in object_dir and hasattr(object, attr)]
|
|
||||||
|
|
||||||
# Remove duplicates from the attribute list.
|
|
||||||
for item in attributes:
|
|
||||||
dict[item] = None
|
|
||||||
attributes = dict.keys()
|
|
||||||
# new-style swig wrappings can result in non-string attributes
|
|
||||||
# e.g. ITK http://www.itk.org/
|
|
||||||
attributes = [attribute for attribute in attributes \
|
|
||||||
if type(attribute) == str]
|
|
||||||
attributes.sort(lambda x, y: cmp(x.upper(), y.upper()))
|
|
||||||
if not includeSingle:
|
|
||||||
attributes = filter(lambda item: item[0]!='_' \
|
|
||||||
or item[1]=='_', attributes)
|
|
||||||
if not includeDouble:
|
|
||||||
attributes = filter(lambda item: item[:2]!='__', attributes)
|
|
||||||
return attributes
|
|
||||||
|
|
||||||
def hasattrAlwaysReturnsTrue(object):
|
|
||||||
return hasattr(object, 'bogu5_123_aTTri8ute')
|
|
||||||
|
|
||||||
def getAllAttributeNames(object):
|
|
||||||
"""Return dict of all attributes, including inherited, for an object.
|
|
||||||
|
|
||||||
Recursively walk through a class and all base classes.
|
|
||||||
"""
|
|
||||||
attrdict = {} # (object, technique, count): [list of attributes]
|
|
||||||
# !!!
|
|
||||||
# Do Not use hasattr() as a test anywhere in this function,
|
|
||||||
# because it is unreliable with remote objects: xmlrpc, soap, etc.
|
|
||||||
# They always return true for hasattr().
|
|
||||||
# !!!
|
|
||||||
try:
|
|
||||||
# This could(?) fail if the type is poorly defined without
|
|
||||||
# even a name.
|
|
||||||
key = type(object).__name__
|
|
||||||
except:
|
|
||||||
key = 'anonymous'
|
|
||||||
# Wake up sleepy objects - a hack for ZODB objects in "ghost" state.
|
|
||||||
wakeupcall = dir(object)
|
|
||||||
del wakeupcall
|
|
||||||
# Get attributes available through the normal convention.
|
|
||||||
attributes = dir(object)
|
|
||||||
attrdict[(key, 'dir', len(attributes))] = attributes
|
|
||||||
# Get attributes from the object's dictionary, if it has one.
|
|
||||||
try:
|
|
||||||
attributes = object.__dict__.keys()
|
|
||||||
attributes.sort()
|
|
||||||
except: # Must catch all because object might have __getattr__.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
attrdict[(key, '__dict__', len(attributes))] = attributes
|
|
||||||
# For a class instance, get the attributes for the class.
|
|
||||||
try:
|
|
||||||
klass = object.__class__
|
|
||||||
except: # Must catch all because object might have __getattr__.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if klass is object:
|
|
||||||
# Break a circular reference. This happens with extension
|
|
||||||
# classes.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
attrdict.update(getAllAttributeNames(klass))
|
|
||||||
# Also get attributes from any and all parent classes.
|
|
||||||
try:
|
|
||||||
bases = object.__bases__
|
|
||||||
except: # Must catch all because object might have __getattr__.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if isinstance(bases, types.TupleType):
|
|
||||||
for base in bases:
|
|
||||||
if type(base) is types.TypeType:
|
|
||||||
# Break a circular reference. Happens in Python 2.2.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
attrdict.update(getAllAttributeNames(base))
|
|
||||||
return attrdict
|
|
||||||
|
|
||||||
def getCallTip(command='', locals=None):
|
|
||||||
"""For a command, return a tuple of object name, argspec, tip text.
|
|
||||||
|
|
||||||
The call tip information will be based on the locals namespace."""
|
|
||||||
calltip = ('', '', '') # object name, argspec, tip text.
|
|
||||||
# Get the proper chunk of code from the command.
|
|
||||||
root = getRoot(command, terminator='(')
|
|
||||||
try:
|
|
||||||
if locals is not None:
|
|
||||||
object = eval(root, locals)
|
|
||||||
else:
|
|
||||||
object = eval(root)
|
|
||||||
except:
|
|
||||||
return calltip
|
|
||||||
name = ''
|
|
||||||
object, dropSelf = getBaseObject(object)
|
|
||||||
try:
|
|
||||||
name = object.__name__
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
tip1 = ''
|
|
||||||
argspec = ''
|
|
||||||
if inspect.isbuiltin(object):
|
|
||||||
# Builtin functions don't have an argspec that we can get.
|
|
||||||
pass
|
|
||||||
elif inspect.isfunction(object):
|
|
||||||
# tip1 is a string like: "getCallTip(command='', locals=None)"
|
|
||||||
argspec = apply(inspect.formatargspec, inspect.getargspec(object))
|
|
||||||
if dropSelf:
|
|
||||||
# The first parameter to a method is a reference to an
|
|
||||||
# instance, usually coded as "self", and is usually passed
|
|
||||||
# automatically by Python; therefore we want to drop it.
|
|
||||||
temp = argspec.split(',')
|
|
||||||
if len(temp) == 1: # No other arguments.
|
|
||||||
argspec = '()'
|
|
||||||
elif temp[0][:2] == '(*': # first param is like *args, not self
|
|
||||||
pass
|
|
||||||
else: # Drop the first argument.
|
|
||||||
argspec = '(' + ','.join(temp[1:]).lstrip()
|
|
||||||
tip1 = name + argspec
|
|
||||||
doc = ''
|
|
||||||
if callable(object):
|
|
||||||
try:
|
|
||||||
doc = inspect.getdoc(object)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if doc:
|
|
||||||
# tip2 is the first separated line of the docstring, like:
|
|
||||||
# "Return call tip text for a command."
|
|
||||||
# tip3 is the rest of the docstring, like:
|
|
||||||
# "The call tip information will be based on ... <snip>
|
|
||||||
firstline = doc.split('\n')[0].lstrip()
|
|
||||||
if tip1 == firstline or firstline[:len(name)+1] == name+'(':
|
|
||||||
tip1 = ''
|
|
||||||
else:
|
|
||||||
tip1 += '\n\n'
|
|
||||||
docpieces = doc.split('\n\n')
|
|
||||||
tip2 = docpieces[0]
|
|
||||||
tip3 = '\n\n'.join(docpieces[1:])
|
|
||||||
tip = '%s%s\n\n%s' % (tip1, tip2, tip3)
|
|
||||||
else:
|
|
||||||
tip = tip1
|
|
||||||
calltip = (name, argspec[1:-1], tip.strip())
|
|
||||||
return calltip
|
|
||||||
|
|
||||||
def getRoot(command, terminator=None):
|
|
||||||
"""Return the rightmost root portion of an arbitrary Python command.
|
|
||||||
|
|
||||||
Return only the root portion that can be eval()'d without side
|
|
||||||
effects. The command would normally terminate with a '(' or
|
|
||||||
'.'. The terminator and anything after the terminator will be
|
|
||||||
dropped."""
|
|
||||||
command = command.split('\n')[-1]
|
|
||||||
if command.startswith(sys.ps2):
|
|
||||||
command = command[len(sys.ps2):]
|
|
||||||
command = command.lstrip()
|
|
||||||
command = rtrimTerminus(command, terminator)
|
|
||||||
tokens = getTokens(command)
|
|
||||||
if not tokens:
|
|
||||||
return ''
|
|
||||||
if tokens[-1][0] is tokenize.ENDMARKER:
|
|
||||||
# Remove the end marker.
|
|
||||||
del tokens[-1]
|
|
||||||
if not tokens:
|
|
||||||
return ''
|
|
||||||
if terminator == '.' and \
|
|
||||||
(tokens[-1][1] <> '.' or tokens[-1][0] is not tokenize.OP):
|
|
||||||
# Trap decimals in numbers, versus the dot operator.
|
|
||||||
return ''
|
|
||||||
else:
|
|
||||||
# Strip off the terminator.
|
|
||||||
if terminator and command.endswith(terminator):
|
|
||||||
size = 0 - len(terminator)
|
|
||||||
command = command[:size]
|
|
||||||
command = command.rstrip()
|
|
||||||
tokens = getTokens(command)
|
|
||||||
tokens.reverse()
|
|
||||||
line = ''
|
|
||||||
start = None
|
|
||||||
prefix = ''
|
|
||||||
laststring = '.'
|
|
||||||
emptyTypes = ('[]', '()', '{}')
|
|
||||||
for token in tokens:
|
|
||||||
tokentype = token[0]
|
|
||||||
tokenstring = token[1]
|
|
||||||
line = token[4]
|
|
||||||
if tokentype is tokenize.ENDMARKER:
|
|
||||||
continue
|
|
||||||
if tokentype in (tokenize.NAME, tokenize.STRING, tokenize.NUMBER) \
|
|
||||||
and laststring != '.':
|
|
||||||
# We've reached something that's not part of the root.
|
|
||||||
if prefix and line[token[3][1]] != ' ':
|
|
||||||
# If it doesn't have a space after it, remove the prefix.
|
|
||||||
prefix = ''
|
|
||||||
break
|
|
||||||
if tokentype in (tokenize.NAME, tokenize.STRING, tokenize.NUMBER) \
|
|
||||||
or (tokentype is tokenize.OP and tokenstring == '.'):
|
|
||||||
if prefix:
|
|
||||||
# The prefix isn't valid because it comes after a dot.
|
|
||||||
prefix = ''
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# start represents the last known good point in the line.
|
|
||||||
start = token[2][1]
|
|
||||||
elif len(tokenstring) == 1 and tokenstring in ('[({])}'):
|
|
||||||
# Remember, we're working backwords.
|
|
||||||
# So prefix += tokenstring would be wrong.
|
|
||||||
if prefix in emptyTypes and tokenstring in ('[({'):
|
|
||||||
# We've already got an empty type identified so now we
|
|
||||||
# are in a nested situation and we can break out with
|
|
||||||
# what we've got.
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
prefix = tokenstring + prefix
|
|
||||||
else:
|
|
||||||
# We've reached something that's not part of the root.
|
|
||||||
break
|
|
||||||
laststring = tokenstring
|
|
||||||
if start is None:
|
|
||||||
start = len(line)
|
|
||||||
root = line[start:]
|
|
||||||
if prefix in emptyTypes:
|
|
||||||
# Empty types are safe to be eval()'d and introspected.
|
|
||||||
root = prefix + root
|
|
||||||
return root
|
|
||||||
|
|
||||||
def getTokens(command):
|
|
||||||
"""Return list of token tuples for command."""
|
|
||||||
|
|
||||||
# In case the command is unicode try encoding it
|
|
||||||
if type(command) == unicode:
|
|
||||||
try:
|
|
||||||
command = command.encode(wx.GetDefaultPyEncoding())
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
pass # otherwise leave it alone
|
|
||||||
|
|
||||||
f = cStringIO.StringIO(command)
|
|
||||||
# tokens is a list of token tuples, each looking like:
|
|
||||||
# (type, string, (srow, scol), (erow, ecol), line)
|
|
||||||
tokens = []
|
|
||||||
# Can't use list comprehension:
|
|
||||||
# tokens = [token for token in tokenize.generate_tokens(f.readline)]
|
|
||||||
# because of need to append as much as possible before TokenError.
|
|
||||||
try:
|
|
||||||
## This code wasn't backward compatible with Python 2.1.3.
|
|
||||||
##
|
|
||||||
## for token in tokenize.generate_tokens(f.readline):
|
|
||||||
## tokens.append(token)
|
|
||||||
|
|
||||||
# This works with Python 2.1.3 (with nested_scopes).
|
|
||||||
def eater(*args):
|
|
||||||
tokens.append(args)
|
|
||||||
tokenize.tokenize_loop(f.readline, eater)
|
|
||||||
except tokenize.TokenError:
|
|
||||||
# This is due to a premature EOF, which we expect since we are
|
|
||||||
# feeding in fragments of Python code.
|
|
||||||
pass
|
|
||||||
return tokens
|
|
||||||
|
|
||||||
def rtrimTerminus(command, terminator=None):
|
|
||||||
"""Return command minus anything that follows the final terminator."""
|
|
||||||
if terminator:
|
|
||||||
pieces = command.split(terminator)
|
|
||||||
if len(pieces) > 1:
|
|
||||||
command = terminator.join(pieces[:-1]) + terminator
|
|
||||||
return command
|
|
||||||
|
|
||||||
def getBaseObject(object):
|
|
||||||
"""Return base object and dropSelf indicator for an object."""
|
|
||||||
if inspect.isbuiltin(object):
|
|
||||||
# Builtin functions don't have an argspec that we can get.
|
|
||||||
dropSelf = 0
|
|
||||||
elif inspect.ismethod(object):
|
|
||||||
# Get the function from the object otherwise
|
|
||||||
# inspect.getargspec() complains that the object isn't a
|
|
||||||
# Python function.
|
|
||||||
try:
|
|
||||||
if object.im_self is None:
|
|
||||||
# This is an unbound method so we do not drop self
|
|
||||||
# from the argspec, since an instance must be passed
|
|
||||||
# as the first arg.
|
|
||||||
dropSelf = 0
|
|
||||||
else:
|
|
||||||
dropSelf = 1
|
|
||||||
object = object.im_func
|
|
||||||
except AttributeError:
|
|
||||||
dropSelf = 0
|
|
||||||
elif inspect.isclass(object):
|
|
||||||
# Get the __init__ method function for the class.
|
|
||||||
constructor = getConstructor(object)
|
|
||||||
if constructor is not None:
|
|
||||||
object = constructor
|
|
||||||
dropSelf = 1
|
|
||||||
else:
|
|
||||||
dropSelf = 0
|
|
||||||
elif callable(object):
|
|
||||||
# Get the __call__ method instead.
|
|
||||||
try:
|
|
||||||
object = object.__call__.im_func
|
|
||||||
dropSelf = 1
|
|
||||||
except AttributeError:
|
|
||||||
dropSelf = 0
|
|
||||||
else:
|
|
||||||
dropSelf = 0
|
|
||||||
return object, dropSelf
|
|
||||||
|
|
||||||
def getConstructor(object):
|
|
||||||
"""Return constructor for class object, or None if there isn't one."""
|
|
||||||
try:
|
|
||||||
return object.__init__.im_func
|
|
||||||
except AttributeError:
|
|
||||||
for base in object.__bases__:
|
|
||||||
constructor = getConstructor(base)
|
|
||||||
if constructor is not None:
|
|
||||||
return constructor
|
|
||||||
return None
|
|
@@ -1,101 +0,0 @@
|
|||||||
"""Provides a variety of classes to create pseudo keywords and pseudo files."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
|
|
||||||
class PseudoKeyword:
|
|
||||||
"""A callable class that calls a method passed as a parameter.
|
|
||||||
|
|
||||||
Good for creating a pseudo keyword in the python runtime
|
|
||||||
environment. The keyword is really an object that has a repr()
|
|
||||||
that calls itself which calls the method that was passed in the
|
|
||||||
init of the object. All this just to avoid having to type in the
|
|
||||||
closing parens on a method. So, for example:
|
|
||||||
|
|
||||||
>>> quit = PseudoKeyword(SomeObject.someMethod)
|
|
||||||
>>> quit
|
|
||||||
|
|
||||||
SomeObject.someMethod gets executed as if it had been called
|
|
||||||
directly and the user didn't have to type the parens, like
|
|
||||||
'quit()'. This technique is most applicable for pseudo keywords
|
|
||||||
like quit, exit and help.
|
|
||||||
|
|
||||||
If SomeObject.someMethod can take parameters, they can still be
|
|
||||||
passed by using the keyword in the traditional way with parens."""
|
|
||||||
|
|
||||||
def __init__(self, method):
|
|
||||||
"""Create a callable object that executes method when called."""
|
|
||||||
|
|
||||||
if callable(method):
|
|
||||||
self.method = method
|
|
||||||
else:
|
|
||||||
raise ValueError, 'method must be callable'
|
|
||||||
|
|
||||||
def __call__(self, *args, **kwds):
|
|
||||||
self.method(*args, **kwds)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
self()
|
|
||||||
return ''
|
|
||||||
|
|
||||||
|
|
||||||
class PseudoFile:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Create a file-like object."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def readline(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def write(self, s):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def writelines(self, l):
|
|
||||||
map(self.write, l)
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def isatty(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class PseudoFileIn(PseudoFile):
|
|
||||||
|
|
||||||
def __init__(self, readline, readlines=None):
|
|
||||||
if callable(readline):
|
|
||||||
self.readline = readline
|
|
||||||
else:
|
|
||||||
raise ValueError, 'readline must be callable'
|
|
||||||
if callable(readlines):
|
|
||||||
self.readlines = readlines
|
|
||||||
|
|
||||||
def isatty(self):
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
class PseudoFileOut(PseudoFile):
|
|
||||||
|
|
||||||
def __init__(self, write):
|
|
||||||
if callable(write):
|
|
||||||
self.write = write
|
|
||||||
else:
|
|
||||||
raise ValueError, 'write must be callable'
|
|
||||||
|
|
||||||
def isatty(self):
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
class PseudoFileErr(PseudoFile):
|
|
||||||
|
|
||||||
def __init__(self, write):
|
|
||||||
if callable(write):
|
|
||||||
self.write = write
|
|
||||||
else:
|
|
||||||
raise ValueError, 'write must be callable'
|
|
||||||
|
|
||||||
def isatty(self):
|
|
||||||
return 1
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,82 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
# Import from this module's parent directory.
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
sys.path.insert(0, os.pardir)
|
|
||||||
import interpreter
|
|
||||||
del sys.path[0]
|
|
||||||
del sys
|
|
||||||
del os
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
These unittest methods are preferred:
|
|
||||||
-------------------------------------
|
|
||||||
self.assert_(expr, msg=None)
|
|
||||||
self.assertEqual(first, second, msg=None)
|
|
||||||
self.assertRaises(excClass, callableObj, *args, **kwargs)
|
|
||||||
self.fail(msg=None)
|
|
||||||
self.failIf(expr, msg=None)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_module(self):
|
|
||||||
module = interpreter
|
|
||||||
self.assert_(module.__author__)
|
|
||||||
self.assert_(module.__cvsid__)
|
|
||||||
self.assert_(module.__revision__)
|
|
||||||
self.assert_(module.Interpreter)
|
|
||||||
self.assert_(module.Interpreter.push)
|
|
||||||
self.assert_(module.Interpreter.runsource)
|
|
||||||
self.assert_(module.Interpreter.getAutoCompleteList)
|
|
||||||
self.assert_(module.Interpreter.getCallTip)
|
|
||||||
self.assert_(module.InterpreterAlaCarte)
|
|
||||||
|
|
||||||
|
|
||||||
class InterpreterTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.output = ''
|
|
||||||
self.i = interpreter.Interpreter(stdout=self)
|
|
||||||
|
|
||||||
def write(self, text):
|
|
||||||
"""Capture output from self.i.push()."""
|
|
||||||
self.output += text
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.output = ''
|
|
||||||
self.i = None
|
|
||||||
del self.i
|
|
||||||
|
|
||||||
def test_more(self):
|
|
||||||
self.assertEqual(self.i.push('dir()'), 0)
|
|
||||||
self.assertEqual(self.i.push('for n in range(3):'), 1)
|
|
||||||
|
|
||||||
def test_push(self):
|
|
||||||
values = (
|
|
||||||
('dir', '<built-in function dir>'),
|
|
||||||
('dir()', "['__builtins__', '__doc__', '__name__']"),
|
|
||||||
('2 + 2', '4'),
|
|
||||||
('d = {}', ''),
|
|
||||||
('d', '{}'),
|
|
||||||
('del d', ''),
|
|
||||||
('len([4,5,6])', '3'),
|
|
||||||
)
|
|
||||||
for input, output in values:
|
|
||||||
if output: output += '\n'
|
|
||||||
self.i.push(input)
|
|
||||||
self.assertEqual(self.output, output)
|
|
||||||
self.output = ''
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
@@ -1,862 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
# Import from this module's parent directory.
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
sys.path.insert(0, os.pardir)
|
|
||||||
import introspect
|
|
||||||
del sys.path[0]
|
|
||||||
del sys
|
|
||||||
del os
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
These unittest methods are preferred:
|
|
||||||
-------------------------------------
|
|
||||||
self.assert_(expr, msg=None)
|
|
||||||
self.assertEqual(first, second, msg=None)
|
|
||||||
self.assertRaises(excClass, callableObj, *args, **kwargs)
|
|
||||||
self.fail(msg=None)
|
|
||||||
self.failIf(expr, msg=None)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_module(self):
|
|
||||||
module = introspect
|
|
||||||
self.assert_(module.__author__)
|
|
||||||
self.assert_(module.__cvsid__)
|
|
||||||
self.assert_(module.__revision__)
|
|
||||||
self.assert_(module.getAllAttributeNames)
|
|
||||||
self.assert_(module.getAttributeNames)
|
|
||||||
self.assert_(module.getAutoCompleteList)
|
|
||||||
self.assert_(module.getBaseObject)
|
|
||||||
self.assert_(module.getCallTip)
|
|
||||||
self.assert_(module.getConstructor)
|
|
||||||
self.assert_(module.getRoot)
|
|
||||||
self.assert_(module.rtrimTerminus)
|
|
||||||
|
|
||||||
|
|
||||||
class RtrimTerminusTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_rtrimTerminus(self):
|
|
||||||
values = (
|
|
||||||
('', '', ''),
|
|
||||||
('', None, ''),
|
|
||||||
('', '.', ''),
|
|
||||||
('', '(', ''),
|
|
||||||
|
|
||||||
('.', '', '.'),
|
|
||||||
('.', None, '.'),
|
|
||||||
('.', '.', '.'),
|
|
||||||
('.', '(', '.'),
|
|
||||||
|
|
||||||
('(', '', '('),
|
|
||||||
('(', None, '('),
|
|
||||||
('(', '.', '('),
|
|
||||||
('(', '(', '('),
|
|
||||||
|
|
||||||
('spam', '', 'spam'),
|
|
||||||
('spam', None, 'spam'),
|
|
||||||
('spam', '.', 'spam'),
|
|
||||||
('spam', '(', 'spam'),
|
|
||||||
|
|
||||||
('spam.', '', 'spam.'),
|
|
||||||
('spam.', None, 'spam.'),
|
|
||||||
('spam.', '.', 'spam.'),
|
|
||||||
('spam.', '(', 'spam.'),
|
|
||||||
|
|
||||||
('spam(', '', 'spam('),
|
|
||||||
('spam(', None, 'spam('),
|
|
||||||
('spam(', '.', 'spam('),
|
|
||||||
('spam(', '(', 'spam('),
|
|
||||||
|
|
||||||
('spam.eggs', '.', 'spam.'),
|
|
||||||
('spam.eggs.', '.', 'spam.eggs.'),
|
|
||||||
('spam.eggs(', '(', 'spam.eggs('),
|
|
||||||
('spam.eggs.', '(', 'spam.eggs.'),
|
|
||||||
('spam.eggs(', '.', 'spam.'),
|
|
||||||
|
|
||||||
('x = spam.', '.', 'x = spam.'),
|
|
||||||
('x = spam.eggs', '.', 'x = spam.'),
|
|
||||||
('x = spam.eggs.', '.', 'x = spam.eggs.'),
|
|
||||||
('x = spam.eggs(', '(', 'x = spam.eggs('),
|
|
||||||
)
|
|
||||||
for input, terminator, output in values:
|
|
||||||
result = introspect.rtrimTerminus(input, terminator)
|
|
||||||
self.assertEqual(result, output,
|
|
||||||
':in: %r :t: %r :out: %r :result: %r' %
|
|
||||||
(input, terminator, output, result))
|
|
||||||
|
|
||||||
|
|
||||||
class GetRootTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def _checkRoot(self, input, terminator, output):
|
|
||||||
root = introspect.getRoot(command=input, terminator=terminator)
|
|
||||||
self.assertEqual(root, output,
|
|
||||||
':in: %r :t: %r :out: %r :root: %r' %
|
|
||||||
(input, terminator, output, root))
|
|
||||||
|
|
||||||
def test_getRoot(self):
|
|
||||||
values = (
|
|
||||||
('', '', ''),
|
|
||||||
('', None, ''),
|
|
||||||
('', '.', ''),
|
|
||||||
('', '(', ''),
|
|
||||||
|
|
||||||
('.', '', '.'),
|
|
||||||
('.', None, '.'),
|
|
||||||
('.', '.', ''),
|
|
||||||
('.', '(', '.'),
|
|
||||||
|
|
||||||
('(', '', ''),
|
|
||||||
('(', None, ''),
|
|
||||||
('(', '.', ''),
|
|
||||||
('(', '(', ''),
|
|
||||||
|
|
||||||
('spam', '', 'spam'),
|
|
||||||
('spam', None, 'spam'),
|
|
||||||
('spam', '.', ''),
|
|
||||||
('spam', '(', 'spam'),
|
|
||||||
|
|
||||||
('spam.', '', 'spam.'),
|
|
||||||
('spam.', None, 'spam.'),
|
|
||||||
('spam.', '.', 'spam'),
|
|
||||||
('spam.', '(', 'spam.'),
|
|
||||||
|
|
||||||
('spam(', '', ''),
|
|
||||||
('spam(', None, ''),
|
|
||||||
('spam(', '.', ''),
|
|
||||||
('spam(', '(', 'spam'),
|
|
||||||
|
|
||||||
('spam.eggs', '.', 'spam'),
|
|
||||||
('spam.eggs.', '.', 'spam.eggs'),
|
|
||||||
('spam.eggs(', '(', 'spam.eggs'),
|
|
||||||
('spam.eggs.', '(', 'spam.eggs.'),
|
|
||||||
('spam.eggs(', '.', 'spam'),
|
|
||||||
|
|
||||||
('x = spam.', '.', 'spam'),
|
|
||||||
('x = spam.eggs', '.', 'spam'),
|
|
||||||
('x = spam.eggs.', '.', 'spam.eggs'),
|
|
||||||
('x = spam.eggs(', '(', 'spam.eggs'),
|
|
||||||
|
|
||||||
('for n in range(3):\n d.', '.', 'd'),
|
|
||||||
('for n in range(3):\n... d.', '.', 'd'),
|
|
||||||
)
|
|
||||||
for input, terminator, output in values:
|
|
||||||
self._checkRoot(input, terminator, output)
|
|
||||||
|
|
||||||
def test_getRoot_Advanced(self):
|
|
||||||
values = (
|
|
||||||
('spam_', '', 'spam_'),
|
|
||||||
('spam_', None, 'spam_'),
|
|
||||||
('spam_', '.', ''),
|
|
||||||
('spam_', '(', 'spam_'),
|
|
||||||
|
|
||||||
('_spam', '', '_spam'),
|
|
||||||
('_spam', None, '_spam'),
|
|
||||||
('_spam', '.', ''),
|
|
||||||
('_spam', '(', '_spam'),
|
|
||||||
|
|
||||||
('spam_eggs', '', 'spam_eggs'),
|
|
||||||
('spam_eggs', None, 'spam_eggs'),
|
|
||||||
('spam_eggs', '.', ''),
|
|
||||||
('spam_eggs', '(', 'spam_eggs'),
|
|
||||||
|
|
||||||
('spam123', '', 'spam123'),
|
|
||||||
('spam123', None, 'spam123'),
|
|
||||||
('spam123', '.', ''),
|
|
||||||
('spam123', '(', 'spam123'),
|
|
||||||
|
|
||||||
('spam_123', '', 'spam_123'),
|
|
||||||
('spam_123', None, 'spam_123'),
|
|
||||||
('spam_123', '.', ''),
|
|
||||||
('spam_123', '(', 'spam_123'),
|
|
||||||
)
|
|
||||||
for input, terminator, output in values:
|
|
||||||
self._checkRoot(input, terminator, output)
|
|
||||||
|
|
||||||
## The original intent was to detect when we were inside a string.
|
|
||||||
## That has proven to be very difficult, for little benefit.
|
|
||||||
## The fact that autocomplete or calltips might be triggered inside
|
|
||||||
## a string is not a big deal. Sometimes it is even helpful.
|
|
||||||
|
|
||||||
## def test_getRoot_InsideStrings(self):
|
|
||||||
## values = (
|
|
||||||
## ('x = ".', '.', ''),
|
|
||||||
## ("x = '.", '.', ''),
|
|
||||||
## ('x = """.', '.', ''),
|
|
||||||
## ("x = '''.", '.', ''),
|
|
||||||
##
|
|
||||||
## ('x = "(', '(', ''),
|
|
||||||
## ("x = '(", '(', ''),
|
|
||||||
## ('x = """(', '(', ''),
|
|
||||||
## ("x = '''(", '(', ''),
|
|
||||||
##
|
|
||||||
## ('x = "spam', '.', ''),
|
|
||||||
## ('x = "spam.', '.', ''),
|
|
||||||
## ("x = 'spam.", '.', ''),
|
|
||||||
## ('x = """spam.', '.', ''),
|
|
||||||
## ("x = '''spam.", '.', ''),
|
|
||||||
##
|
|
||||||
## ('x = "spam', '(', ''),
|
|
||||||
## ('x = "spam(', '(', ''),
|
|
||||||
## ("x = 'spam(", '(', ''),
|
|
||||||
## ('x = """spam(', '(', ''),
|
|
||||||
## ("x = '''spam(", '(', ''),
|
|
||||||
##
|
|
||||||
## ('x = "spam.eggs.', '.', ''),
|
|
||||||
## ("x = 'spam.eggs.", '.', ''),
|
|
||||||
## ('x = """spam.eggs.', '.', ''),
|
|
||||||
## ("x = '''spam.eggs.", '.', ''),
|
|
||||||
##
|
|
||||||
## ('x = "spam.eggs(', '(', ''),
|
|
||||||
## ("x = 'spam.eggs(", '(', ''),
|
|
||||||
## ('x = """spam.eggs(', '(', ''),
|
|
||||||
## ("x = '''spam.eggs(", '(', ''),
|
|
||||||
## )
|
|
||||||
## for input, terminator, output in values:
|
|
||||||
## self._checkRoot(input, terminator, output)
|
|
||||||
|
|
||||||
def test_getRoot_EmptyTypes(self):
|
|
||||||
values = (
|
|
||||||
("''.", '.', "''"),
|
|
||||||
('"".', '.', '""'),
|
|
||||||
('"""""".', '.', '""""""'),
|
|
||||||
("''''''.", '.', "''''''"),
|
|
||||||
|
|
||||||
('[].', '.', '[]'),
|
|
||||||
('().', '.', '()'),
|
|
||||||
('{}.', '.', '{}'),
|
|
||||||
|
|
||||||
('[](', '(', '[]'),
|
|
||||||
('()(', '(', '()'),
|
|
||||||
('{}(', '(', '{}'),
|
|
||||||
|
|
||||||
("x = ''.", '.', "''"),
|
|
||||||
('x = "".', '.', '""'),
|
|
||||||
('x = """""".', '.', '""""""'),
|
|
||||||
("x = ''''''.", '.', "''''''"),
|
|
||||||
|
|
||||||
('x = [].', '.', '[]'),
|
|
||||||
('x = ().', '.', '()'),
|
|
||||||
('x = {}.', '.', '{}'),
|
|
||||||
|
|
||||||
('x = [](', '(', '[]'),
|
|
||||||
('x = ()(', '(', '()'),
|
|
||||||
('x = {}(', '(', '{}'),
|
|
||||||
|
|
||||||
('print [].', '.', '[]'),
|
|
||||||
('print ().', '.', '()'),
|
|
||||||
('print {}.', '.', '{}'),
|
|
||||||
|
|
||||||
('print [](', '(', '[]'),
|
|
||||||
('print ()(', '(', '()'),
|
|
||||||
('print {}(', '(', '{}'),
|
|
||||||
|
|
||||||
("''.attr.", '.', "''.attr"),
|
|
||||||
('"".attr.', '.', '"".attr'),
|
|
||||||
('"""""".attr.', '.', '"""""".attr'),
|
|
||||||
("''''''.attr.", '.', "''''''.attr"),
|
|
||||||
|
|
||||||
('[].attr.', '.', '[].attr'),
|
|
||||||
('().attr.', '.', '().attr'),
|
|
||||||
('{}.attr.', '.', '{}.attr'),
|
|
||||||
|
|
||||||
('[].attr(', '(', '[].attr'),
|
|
||||||
('().attr(', '(', '().attr'),
|
|
||||||
('{}.attr(', '(', '{}.attr'),
|
|
||||||
|
|
||||||
('spam().', '.', ''),
|
|
||||||
('spam_().', '.', ''),
|
|
||||||
('spam5().', '.', ''),
|
|
||||||
('spam[]().', '.', ''),
|
|
||||||
('spam()[].', '.', ''),
|
|
||||||
('spam[]{}.', '.', ''),
|
|
||||||
|
|
||||||
("spam(''.", '.', "''"),
|
|
||||||
('spam("".', '.', '""'),
|
|
||||||
('spam("""""".', '.', '""""""'),
|
|
||||||
("spam(''''''.", '.', "''''''"),
|
|
||||||
|
|
||||||
('spam([].', '.', '[]'),
|
|
||||||
('spam(().', '.', '()'),
|
|
||||||
('spam({}.', '.', '{}'),
|
|
||||||
('spam[[].', '.', '[]'),
|
|
||||||
('spam[().', '.', '()'),
|
|
||||||
('spam[{}.', '.', '{}'),
|
|
||||||
('x = {[].', '.', '[]'),
|
|
||||||
('x = {().', '.', '()'),
|
|
||||||
('x = {{}.', '.', '{}'),
|
|
||||||
|
|
||||||
('spam,[].', '.', '[]'),
|
|
||||||
('spam+[].', '.', '[]'),
|
|
||||||
('spam-[].', '.', '[]'),
|
|
||||||
('spam*[].', '.', '[]'),
|
|
||||||
('spam/[].', '.', '[]'),
|
|
||||||
('spam=[].', '.', '[]'),
|
|
||||||
('spam%[].', '.', '[]'),
|
|
||||||
('spam<[].', '.', '[]'),
|
|
||||||
('spam>[].', '.', '[]'),
|
|
||||||
('spam&[].', '.', '[]'),
|
|
||||||
('spam|[].', '.', '[]'),
|
|
||||||
('spam^[].', '.', '[]'),
|
|
||||||
('spam~[].', '.', '[]'),
|
|
||||||
('spam:[].', '.', '[]'),
|
|
||||||
|
|
||||||
('spam,().', '.', '()'),
|
|
||||||
('spam+().', '.', '()'),
|
|
||||||
('spam-().', '.', '()'),
|
|
||||||
('spam*().', '.', '()'),
|
|
||||||
('spam/().', '.', '()'),
|
|
||||||
('spam=().', '.', '()'),
|
|
||||||
('spam%().', '.', '()'),
|
|
||||||
('spam<().', '.', '()'),
|
|
||||||
('spam>().', '.', '()'),
|
|
||||||
('spam&().', '.', '()'),
|
|
||||||
('spam|().', '.', '()'),
|
|
||||||
('spam^().', '.', '()'),
|
|
||||||
('spam~().', '.', '()'),
|
|
||||||
('spam:().', '.', '()'),
|
|
||||||
|
|
||||||
('spam,{}.', '.', '{}'),
|
|
||||||
('spam+{}.', '.', '{}'),
|
|
||||||
('spam-{}.', '.', '{}'),
|
|
||||||
('spam*{}.', '.', '{}'),
|
|
||||||
('spam/{}.', '.', '{}'),
|
|
||||||
('spam={}.', '.', '{}'),
|
|
||||||
('spam%{}.', '.', '{}'),
|
|
||||||
('spam<{}.', '.', '{}'),
|
|
||||||
('spam>{}.', '.', '{}'),
|
|
||||||
('spam&{}.', '.', '{}'),
|
|
||||||
('spam|{}.', '.', '{}'),
|
|
||||||
('spam^{}.', '.', '{}'),
|
|
||||||
('spam~{}.', '.', '{}'),
|
|
||||||
('spam:{}.', '.', '{}'),
|
|
||||||
)
|
|
||||||
for input, terminator, output in values:
|
|
||||||
self._checkRoot(input, terminator, output)
|
|
||||||
|
|
||||||
|
|
||||||
# Support for GetBaseObjectTestCase and GetAttributeNamesTestCase.
|
|
||||||
|
|
||||||
class Foo:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _private(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Bar:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Spam:
|
|
||||||
def __call__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def foo(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def bar(spam):
|
|
||||||
# It shouldn't matter what we call "self".
|
|
||||||
pass
|
|
||||||
|
|
||||||
def eggs(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def ham(eggs):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class GetBaseObjectTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_getBaseObject(self):
|
|
||||||
spam = Spam()
|
|
||||||
eggs = Spam.eggs
|
|
||||||
listappend = [].append
|
|
||||||
spamda = lambda: None
|
|
||||||
values = (
|
|
||||||
('spam', 'spam', 0),
|
|
||||||
(123, 123, 0),
|
|
||||||
(12.3, 12.3, 0),
|
|
||||||
([], [], 0),
|
|
||||||
((), (), 0),
|
|
||||||
({}, {}, 0),
|
|
||||||
# Builtin function.
|
|
||||||
(len, len, 0),
|
|
||||||
# Builtin method.
|
|
||||||
(listappend, listappend, 0),
|
|
||||||
# User function.
|
|
||||||
(ham, ham, 0),
|
|
||||||
# Byte-compiled code.
|
|
||||||
(ham.func_code, ham.func_code, 0),
|
|
||||||
# Lambda.
|
|
||||||
(spamda, spamda, 0),
|
|
||||||
# Class with init.
|
|
||||||
(Foo, Foo.__init__.im_func, 1),
|
|
||||||
# Class with no init.
|
|
||||||
(Bar, Bar, 0),
|
|
||||||
# Bound method.
|
|
||||||
(spam.foo, spam.foo.im_func, 1),
|
|
||||||
# Bound method with self named something else (spam).
|
|
||||||
(spam.bar, spam.bar.im_func, 1),
|
|
||||||
# Unbound method. (Do not drop the self argument.)
|
|
||||||
(eggs, eggs.im_func, 0),
|
|
||||||
# Callable instance.
|
|
||||||
(spam, spam.__call__.im_func, 1),
|
|
||||||
)
|
|
||||||
for object, baseObject, dropSelf in values:
|
|
||||||
result = introspect.getBaseObject(object)
|
|
||||||
self.assertEqual(result, (baseObject, dropSelf))
|
|
||||||
|
|
||||||
|
|
||||||
class GetAttributeTestCase(unittest.TestCase):
|
|
||||||
"""Base class for other test case classes."""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.values = (
|
|
||||||
'__abs__',
|
|
||||||
'__add__',
|
|
||||||
'__and__',
|
|
||||||
'__base__',
|
|
||||||
'__bases__',
|
|
||||||
'__basicsize__',
|
|
||||||
'__builtins__',
|
|
||||||
'__call__',
|
|
||||||
'__class__',
|
|
||||||
'__cmp__',
|
|
||||||
'__coerce__',
|
|
||||||
'__contains__',
|
|
||||||
'__del__',
|
|
||||||
'__delattr__',
|
|
||||||
'__delitem__',
|
|
||||||
'__delslice__',
|
|
||||||
'__dict__',
|
|
||||||
'__dictoffset__',
|
|
||||||
'__div__',
|
|
||||||
'__divmod__',
|
|
||||||
'__doc__',
|
|
||||||
'__eq__',
|
|
||||||
'__file__',
|
|
||||||
'__flags__',
|
|
||||||
'__float__',
|
|
||||||
'__floordiv__',
|
|
||||||
'__ge__',
|
|
||||||
'__get__',
|
|
||||||
'__getattr__',
|
|
||||||
'__getattribute__',
|
|
||||||
'__getitem__',
|
|
||||||
'__getslice__',
|
|
||||||
'__gt__',
|
|
||||||
'__hash__',
|
|
||||||
'__hex__',
|
|
||||||
'__iadd__',
|
|
||||||
'__imul__',
|
|
||||||
'__init__',
|
|
||||||
'__int__',
|
|
||||||
'__invert__',
|
|
||||||
'__itemsize__',
|
|
||||||
'__iter__',
|
|
||||||
'__le__',
|
|
||||||
'__len__',
|
|
||||||
'__long__',
|
|
||||||
'__lshift__',
|
|
||||||
'__lt__',
|
|
||||||
'__mod__',
|
|
||||||
'__module__',
|
|
||||||
'__mro__',
|
|
||||||
'__mul__',
|
|
||||||
'__name__',
|
|
||||||
'__ne__',
|
|
||||||
'__neg__',
|
|
||||||
'__new__',
|
|
||||||
'__nonzero__',
|
|
||||||
'__oct__',
|
|
||||||
'__or__',
|
|
||||||
'__path__',
|
|
||||||
'__pos__',
|
|
||||||
'__pow__',
|
|
||||||
'__radd__',
|
|
||||||
'__rand__',
|
|
||||||
'__rdiv__',
|
|
||||||
'__rdivmod__',
|
|
||||||
'__reduce__',
|
|
||||||
'__repr__',
|
|
||||||
'__rfloordiv__',
|
|
||||||
'__rlshift__',
|
|
||||||
'__rmod__',
|
|
||||||
'__rmul__',
|
|
||||||
'__ror__',
|
|
||||||
'__rpow__',
|
|
||||||
'__rrshift__',
|
|
||||||
'__rshift__',
|
|
||||||
'__rsub__',
|
|
||||||
'__rtruediv__',
|
|
||||||
'__rxor__',
|
|
||||||
'__self__',
|
|
||||||
'__setattr__',
|
|
||||||
'__setitem__',
|
|
||||||
'__setslice__',
|
|
||||||
'__str__',
|
|
||||||
'__sub__',
|
|
||||||
'__subclasses__',
|
|
||||||
'__truediv__',
|
|
||||||
'__warningregistry__',
|
|
||||||
'__weakrefoffset__',
|
|
||||||
'__xor__',
|
|
||||||
'append',
|
|
||||||
'capitalize',
|
|
||||||
'center',
|
|
||||||
'clear',
|
|
||||||
'close',
|
|
||||||
'closed',
|
|
||||||
'co_argcount',
|
|
||||||
'co_cellvars',
|
|
||||||
'co_code',
|
|
||||||
'co_consts',
|
|
||||||
'co_filename',
|
|
||||||
'co_firstlineno',
|
|
||||||
'co_flags',
|
|
||||||
'co_freevars',
|
|
||||||
'co_lnotab',
|
|
||||||
'co_name',
|
|
||||||
'co_names',
|
|
||||||
'co_nlocals',
|
|
||||||
'co_stacksize',
|
|
||||||
'co_varnames',
|
|
||||||
'conjugate',
|
|
||||||
'copy',
|
|
||||||
'count',
|
|
||||||
'decode',
|
|
||||||
'encode',
|
|
||||||
'endswith',
|
|
||||||
'expandtabs',
|
|
||||||
'extend',
|
|
||||||
'fileno',
|
|
||||||
'find',
|
|
||||||
'flush',
|
|
||||||
'func_closure',
|
|
||||||
'func_code',
|
|
||||||
'func_defaults',
|
|
||||||
'func_dict',
|
|
||||||
'func_doc',
|
|
||||||
'func_globals',
|
|
||||||
'func_name',
|
|
||||||
'get',
|
|
||||||
'has_key',
|
|
||||||
'im_class',
|
|
||||||
'im_func',
|
|
||||||
'im_self',
|
|
||||||
'imag',
|
|
||||||
'index',
|
|
||||||
'insert',
|
|
||||||
'isalnum',
|
|
||||||
'isalpha',
|
|
||||||
'isatty',
|
|
||||||
'isdigit',
|
|
||||||
'islower',
|
|
||||||
'isspace',
|
|
||||||
'istitle',
|
|
||||||
'isupper',
|
|
||||||
'items',
|
|
||||||
'iteritems',
|
|
||||||
'iterkeys',
|
|
||||||
'itervalues',
|
|
||||||
'join',
|
|
||||||
'keys',
|
|
||||||
'ljust',
|
|
||||||
'lower',
|
|
||||||
'lstrip',
|
|
||||||
'mode',
|
|
||||||
'mro',
|
|
||||||
'name',
|
|
||||||
'pop',
|
|
||||||
'popitem',
|
|
||||||
'real',
|
|
||||||
'read',
|
|
||||||
'readinto',
|
|
||||||
'readline',
|
|
||||||
'readlines',
|
|
||||||
'remove',
|
|
||||||
'replace',
|
|
||||||
'reverse',
|
|
||||||
'rfind',
|
|
||||||
'rindex',
|
|
||||||
'rjust',
|
|
||||||
'rstrip',
|
|
||||||
'seek',
|
|
||||||
'setdefault',
|
|
||||||
'softspace',
|
|
||||||
'sort',
|
|
||||||
'split',
|
|
||||||
'splitlines',
|
|
||||||
'start',
|
|
||||||
'startswith',
|
|
||||||
'step',
|
|
||||||
'stop',
|
|
||||||
'strip',
|
|
||||||
'swapcase',
|
|
||||||
'tell',
|
|
||||||
'title',
|
|
||||||
'tolist',
|
|
||||||
'translate',
|
|
||||||
'truncate',
|
|
||||||
'update',
|
|
||||||
'upper',
|
|
||||||
'values',
|
|
||||||
'write',
|
|
||||||
'writelines',
|
|
||||||
'xreadlines',
|
|
||||||
)
|
|
||||||
|
|
||||||
# Since getAllAttributeNames() calls str(object),
|
|
||||||
# we need to test for a broken __str__ method.
|
|
||||||
class BrokenStr:
|
|
||||||
def __str__(self):
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
brokenStr = BrokenStr()
|
|
||||||
|
|
||||||
class GetAttributeNamesTestCase(GetAttributeTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
GetAttributeTestCase.setUp(self)
|
|
||||||
from wx import py
|
|
||||||
spam = Spam()
|
|
||||||
self.f = open('test_introspect.py')
|
|
||||||
self.items = (
|
|
||||||
None,
|
|
||||||
int(123),
|
|
||||||
long(123),
|
|
||||||
float(123),
|
|
||||||
complex(123),
|
|
||||||
"",
|
|
||||||
unicode(""),
|
|
||||||
[],
|
|
||||||
(),
|
|
||||||
xrange(0),
|
|
||||||
{},
|
|
||||||
# Builtin function.
|
|
||||||
len,
|
|
||||||
# Builtin method.
|
|
||||||
[].append,
|
|
||||||
# User function.
|
|
||||||
ham,
|
|
||||||
# Byte-compiled code.
|
|
||||||
ham.func_code,
|
|
||||||
# Lambda.
|
|
||||||
lambda: None,
|
|
||||||
# Class with no init.
|
|
||||||
Bar,
|
|
||||||
# Instance with no init.
|
|
||||||
Bar(),
|
|
||||||
# Class with init and del.
|
|
||||||
Foo,
|
|
||||||
# Instance with init and del.
|
|
||||||
Foo(),
|
|
||||||
# Bound method.
|
|
||||||
spam.foo,
|
|
||||||
# Unbound method.
|
|
||||||
Spam.eggs,
|
|
||||||
# Callable instance.
|
|
||||||
spam,
|
|
||||||
# Module.
|
|
||||||
introspect,
|
|
||||||
# Package.
|
|
||||||
py,
|
|
||||||
# Buffer.
|
|
||||||
buffer(''),
|
|
||||||
# File.
|
|
||||||
self.f,
|
|
||||||
# Slice.
|
|
||||||
slice(0),
|
|
||||||
# Ellipsis.
|
|
||||||
Ellipsis,
|
|
||||||
# BrokenStr class.
|
|
||||||
BrokenStr,
|
|
||||||
# BrokenStr instance.
|
|
||||||
brokenStr,
|
|
||||||
)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.items = None
|
|
||||||
self.f.close()
|
|
||||||
|
|
||||||
def test_getAttributeNames(self):
|
|
||||||
for item in self.items:
|
|
||||||
self._checkAttributeNames(item)
|
|
||||||
if __builtins__.has_key('object'):
|
|
||||||
self._checkAttributeNames(object)
|
|
||||||
|
|
||||||
def test_getAttributeNames_NoSingle(self):
|
|
||||||
for item in self.items:
|
|
||||||
result = introspect.getAttributeNames(item, includeSingle=0)
|
|
||||||
attributes = [attribute for attribute in result \
|
|
||||||
if attribute[0] != '_' or attribute[:2] == '__']
|
|
||||||
self.assertEqual(result, attributes,
|
|
||||||
':item: %r' % (item,))
|
|
||||||
|
|
||||||
def test_getAttributeNames_NoDouble(self):
|
|
||||||
for item in self.items:
|
|
||||||
result = introspect.getAttributeNames(item, includeDouble=0)
|
|
||||||
attributes = [attribute for attribute in result \
|
|
||||||
if attribute[:2] != '__']
|
|
||||||
self.assertEqual(result, attributes,
|
|
||||||
':item: %r' % (item,))
|
|
||||||
|
|
||||||
def test_getAttributeNames_NoSingleOrDouble(self):
|
|
||||||
for item in self.items:
|
|
||||||
result = introspect.getAttributeNames(item, includeSingle=0,
|
|
||||||
includeDouble=0)
|
|
||||||
attributes = [attribute for attribute in result \
|
|
||||||
if attribute[0] != '_']
|
|
||||||
self.assertEqual(result, attributes,
|
|
||||||
':item: %r' % (item,))
|
|
||||||
|
|
||||||
def _checkAttributeNames(self, item):
|
|
||||||
result = introspect.getAttributeNames(item)
|
|
||||||
attributes = [attribute for attribute in self.values \
|
|
||||||
if hasattr(item, attribute)]
|
|
||||||
for attribute in attributes:
|
|
||||||
self.assert_(attribute in result,
|
|
||||||
':item: %r :attribute: %r' % (item, attribute))
|
|
||||||
|
|
||||||
|
|
||||||
class GetAutoCompleteListTestCase(GetAttributeTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
GetAttributeTestCase.setUp(self)
|
|
||||||
self.items = (
|
|
||||||
'None.',
|
|
||||||
'123 .',
|
|
||||||
'"".',
|
|
||||||
'[].',
|
|
||||||
'().',
|
|
||||||
'{}.',
|
|
||||||
# Builtin function.
|
|
||||||
'len.',
|
|
||||||
# Builtin method.
|
|
||||||
'[].append.',
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_getAutoCompleteList(self):
|
|
||||||
for item in self.items:
|
|
||||||
result = introspect.getAutoCompleteList(item)
|
|
||||||
object = eval(item[:-1])
|
|
||||||
attributes = [attribute for attribute in self.values \
|
|
||||||
if hasattr(object, attribute)]
|
|
||||||
for attribute in attributes:
|
|
||||||
self.assert_(attribute in result,
|
|
||||||
':item: %r :attribute: %r' % (item, attribute))
|
|
||||||
|
|
||||||
def test_getAutoCompleteList_NoSingle(self):
|
|
||||||
for item in self.items:
|
|
||||||
result = introspect.getAutoCompleteList(item, includeSingle=0)
|
|
||||||
attributes = [attribute for attribute in result \
|
|
||||||
if attribute[0] != '_' or attribute[:2] == '__']
|
|
||||||
self.assertEqual(result, attributes,
|
|
||||||
':item: %r' % (item,))
|
|
||||||
|
|
||||||
def test_getAutoCompleteList_NoDouble(self):
|
|
||||||
for item in self.items:
|
|
||||||
result = introspect.getAutoCompleteList(item, includeDouble=0)
|
|
||||||
attributes = [attribute for attribute in result \
|
|
||||||
if attribute[:2] != '__']
|
|
||||||
self.assertEqual(result, attributes,
|
|
||||||
':item: %r' % (item,))
|
|
||||||
|
|
||||||
def test_getAutoCompleteList_NoSingleOrDouble(self):
|
|
||||||
for item in self.items:
|
|
||||||
result = introspect.getAutoCompleteList(item, includeSingle=0,
|
|
||||||
includeDouble=0)
|
|
||||||
attributes = [attribute for attribute in result \
|
|
||||||
if attribute[0] != '_']
|
|
||||||
self.assertEqual(result, attributes,
|
|
||||||
':item: %r' % (item,))
|
|
||||||
|
|
||||||
|
|
||||||
# Support for GetConstructorTestCase.
|
|
||||||
|
|
||||||
class A1:
|
|
||||||
def __init__(self, a):
|
|
||||||
self.a = a
|
|
||||||
|
|
||||||
class B1(A1):
|
|
||||||
def __init__(self, b):
|
|
||||||
self.b = b
|
|
||||||
|
|
||||||
class C1(A1):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class D1(C1, B1):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if __builtins__.has_key('object'):
|
|
||||||
class A2(object):
|
|
||||||
def __init__(self, a):
|
|
||||||
self.a = a
|
|
||||||
|
|
||||||
class B2(A2):
|
|
||||||
def __init__(self, b):
|
|
||||||
self.b = b
|
|
||||||
|
|
||||||
class C2(A2):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class D2(C2, B2):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class N:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class O:
|
|
||||||
def __init__(self, a, b=2, *args, **kwargs):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class P(O):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Q(P):
|
|
||||||
def __init__(self, c, d=4):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class GetConstructorTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_getConstructor(self):
|
|
||||||
args = ('self', 'a', 'b', 'args', 'kwargs')
|
|
||||||
varnames = introspect.getConstructor(O).func_code.co_varnames
|
|
||||||
self.assertEqual(varnames, args)
|
|
||||||
varnames = introspect.getConstructor(P).func_code.co_varnames
|
|
||||||
self.assertEqual(varnames, args)
|
|
||||||
args = ('self', 'c', 'd')
|
|
||||||
varnames = introspect.getConstructor(Q).func_code.co_varnames
|
|
||||||
self.assertEqual(varnames, args)
|
|
||||||
|
|
||||||
def test_getConstructor_None(self):
|
|
||||||
values = (N, 1, 'spam', {}, [], (), dir)
|
|
||||||
for value in values:
|
|
||||||
self.assertEqual(introspect.getConstructor(N), None)
|
|
||||||
|
|
||||||
def test_getConstructor_MultipleInheritance(self):
|
|
||||||
# Test old style inheritance rules.
|
|
||||||
args = ('self', 'a')
|
|
||||||
varnames = introspect.getConstructor(D1).func_code.co_varnames
|
|
||||||
self.assertEqual(varnames, args)
|
|
||||||
if __builtins__.has_key('object'):
|
|
||||||
# Test new style inheritance rules as well.
|
|
||||||
args = ('self', 'b')
|
|
||||||
varnames = introspect.getConstructor(D2).func_code.co_varnames
|
|
||||||
self.assertEqual(varnames, args)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
@@ -1,81 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
# Import from this module's parent directory.
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
sys.path.insert(0, os.pardir)
|
|
||||||
import pseudo
|
|
||||||
del sys.path[0]
|
|
||||||
del sys
|
|
||||||
del os
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
These unittest methods are preferred:
|
|
||||||
-------------------------------------
|
|
||||||
self.assert_(expr, msg=None)
|
|
||||||
self.assertEqual(first, second, msg=None)
|
|
||||||
self.assertRaises(excClass, callableObj, *args, **kwargs)
|
|
||||||
self.fail(msg=None)
|
|
||||||
self.failIf(expr, msg=None)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_module(self):
|
|
||||||
module = pseudo
|
|
||||||
self.assert_(module.__author__)
|
|
||||||
self.assert_(module.__cvsid__)
|
|
||||||
self.assert_(module.__revision__)
|
|
||||||
self.assert_(module.PseudoFile)
|
|
||||||
self.assert_(module.PseudoFileErr)
|
|
||||||
self.assert_(module.PseudoFileIn)
|
|
||||||
self.assert_(module.PseudoFileOut)
|
|
||||||
self.assert_(module.PseudoKeyword)
|
|
||||||
|
|
||||||
|
|
||||||
class PseudoTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class PseudoFileTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class PseudoFileOutTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _write(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_PseudoFileOut_goodInit(self):
|
|
||||||
self.assert_(pseudo.PseudoFileOut(write=self._write))
|
|
||||||
|
|
||||||
def test_PseudoFileOut_badInit(self):
|
|
||||||
self.assertRaises(ValueError, pseudo.PseudoFileOut, write='bad')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
@@ -1,49 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import types
|
|
||||||
|
|
||||||
# Import from this module's parent directory.
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
sys.path.insert(0, os.pardir)
|
|
||||||
import version
|
|
||||||
del sys.path[0]
|
|
||||||
del sys
|
|
||||||
del os
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
These unittest methods are preferred:
|
|
||||||
-------------------------------------
|
|
||||||
self.assert_(expr, msg=None)
|
|
||||||
self.assertEqual(first, second, msg=None)
|
|
||||||
self.assertRaises(excClass, callableObj, *args, **kwargs)
|
|
||||||
self.fail(msg=None)
|
|
||||||
self.failIf(expr, msg=None)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_module(self):
|
|
||||||
module = version
|
|
||||||
self.assert_(module.__author__)
|
|
||||||
self.assert_(module.__cvsid__)
|
|
||||||
self.assert_(module.__revision__)
|
|
||||||
self.assert_(module.VERSION)
|
|
||||||
|
|
||||||
|
|
||||||
class VersionTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_VERSION(self):
|
|
||||||
self.assert_(type(version.VERSION) is types.StringType)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
@@ -1,25 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def suite():
|
|
||||||
"""Return a test suite containing all test cases in all test modules.
|
|
||||||
Searches the current directory for any modules matching test_*.py."""
|
|
||||||
suite = unittest.TestSuite()
|
|
||||||
for filename in glob.glob('test_*.py'):
|
|
||||||
module = __import__(os.path.splitext(filename)[0])
|
|
||||||
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(module))
|
|
||||||
return suite
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(defaultTest='suite')
|
|
||||||
|
|
@@ -1,9 +0,0 @@
|
|||||||
"""Provides an object representing the current 'version' or 'release'
|
|
||||||
of Py as a whole. Individual classes, such as the shell, filling and
|
|
||||||
interpreter, each have a revision property based on the CVS Revision."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
VERSION = '0.9.4'
|
|
Reference in New Issue
Block a user