增加bot.py拉起webui进程功能
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -339,6 +339,9 @@ MaiBot.code-workspace
|
|||||||
src/chat/planner_actions/planner (2).py
|
src/chat/planner_actions/planner (2).py
|
||||||
rust_video/Cargo.lock
|
rust_video/Cargo.lock
|
||||||
.claude/settings.local.json
|
.claude/settings.local.json
|
||||||
package-lock.json
|
/package-lock.json
|
||||||
package.json
|
/package.json
|
||||||
src/chat/planner_actions/新建 文本文档.txt
|
src/chat/planner_actions/新建 文本文档.txt
|
||||||
|
# WebUI不忽略
|
||||||
|
!/webui/
|
||||||
|
!/webui/**
|
||||||
|
|||||||
164
.venv311/Include/site/python3.11/greenlet/greenlet.h
Normal file
164
.venv311/Include/site/python3.11/greenlet/greenlet.h
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
|
||||||
|
|
||||||
|
/* Greenlet object interface */
|
||||||
|
|
||||||
|
#ifndef Py_GREENLETOBJECT_H
|
||||||
|
#define Py_GREENLETOBJECT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This is deprecated and undocumented. It does not change. */
|
||||||
|
#define GREENLET_VERSION "1.0.0"
|
||||||
|
|
||||||
|
#ifndef GREENLET_MODULE
|
||||||
|
#define implementation_ptr_t void*
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _greenlet {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyObject* weakreflist;
|
||||||
|
PyObject* dict;
|
||||||
|
implementation_ptr_t pimpl;
|
||||||
|
} PyGreenlet;
|
||||||
|
|
||||||
|
#define PyGreenlet_Check(op) (op && PyObject_TypeCheck(op, &PyGreenlet_Type))
|
||||||
|
|
||||||
|
|
||||||
|
/* C API functions */
|
||||||
|
|
||||||
|
/* Total number of symbols that are exported */
|
||||||
|
#define PyGreenlet_API_pointers 12
|
||||||
|
|
||||||
|
#define PyGreenlet_Type_NUM 0
|
||||||
|
#define PyExc_GreenletError_NUM 1
|
||||||
|
#define PyExc_GreenletExit_NUM 2
|
||||||
|
|
||||||
|
#define PyGreenlet_New_NUM 3
|
||||||
|
#define PyGreenlet_GetCurrent_NUM 4
|
||||||
|
#define PyGreenlet_Throw_NUM 5
|
||||||
|
#define PyGreenlet_Switch_NUM 6
|
||||||
|
#define PyGreenlet_SetParent_NUM 7
|
||||||
|
|
||||||
|
#define PyGreenlet_MAIN_NUM 8
|
||||||
|
#define PyGreenlet_STARTED_NUM 9
|
||||||
|
#define PyGreenlet_ACTIVE_NUM 10
|
||||||
|
#define PyGreenlet_GET_PARENT_NUM 11
|
||||||
|
|
||||||
|
#ifndef GREENLET_MODULE
|
||||||
|
/* This section is used by modules that uses the greenlet C API */
|
||||||
|
static void** _PyGreenlet_API = NULL;
|
||||||
|
|
||||||
|
# define PyGreenlet_Type \
|
||||||
|
(*(PyTypeObject*)_PyGreenlet_API[PyGreenlet_Type_NUM])
|
||||||
|
|
||||||
|
# define PyExc_GreenletError \
|
||||||
|
((PyObject*)_PyGreenlet_API[PyExc_GreenletError_NUM])
|
||||||
|
|
||||||
|
# define PyExc_GreenletExit \
|
||||||
|
((PyObject*)_PyGreenlet_API[PyExc_GreenletExit_NUM])
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PyGreenlet_New(PyObject *args)
|
||||||
|
*
|
||||||
|
* greenlet.greenlet(run, parent=None)
|
||||||
|
*/
|
||||||
|
# define PyGreenlet_New \
|
||||||
|
(*(PyGreenlet * (*)(PyObject * run, PyGreenlet * parent)) \
|
||||||
|
_PyGreenlet_API[PyGreenlet_New_NUM])
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PyGreenlet_GetCurrent(void)
|
||||||
|
*
|
||||||
|
* greenlet.getcurrent()
|
||||||
|
*/
|
||||||
|
# define PyGreenlet_GetCurrent \
|
||||||
|
(*(PyGreenlet * (*)(void)) _PyGreenlet_API[PyGreenlet_GetCurrent_NUM])
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PyGreenlet_Throw(
|
||||||
|
* PyGreenlet *greenlet,
|
||||||
|
* PyObject *typ,
|
||||||
|
* PyObject *val,
|
||||||
|
* PyObject *tb)
|
||||||
|
*
|
||||||
|
* g.throw(...)
|
||||||
|
*/
|
||||||
|
# define PyGreenlet_Throw \
|
||||||
|
(*(PyObject * (*)(PyGreenlet * self, \
|
||||||
|
PyObject * typ, \
|
||||||
|
PyObject * val, \
|
||||||
|
PyObject * tb)) \
|
||||||
|
_PyGreenlet_API[PyGreenlet_Throw_NUM])
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PyGreenlet_Switch(PyGreenlet *greenlet, PyObject *args)
|
||||||
|
*
|
||||||
|
* g.switch(*args, **kwargs)
|
||||||
|
*/
|
||||||
|
# define PyGreenlet_Switch \
|
||||||
|
(*(PyObject * \
|
||||||
|
(*)(PyGreenlet * greenlet, PyObject * args, PyObject * kwargs)) \
|
||||||
|
_PyGreenlet_API[PyGreenlet_Switch_NUM])
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PyGreenlet_SetParent(PyObject *greenlet, PyObject *new_parent)
|
||||||
|
*
|
||||||
|
* g.parent = new_parent
|
||||||
|
*/
|
||||||
|
# define PyGreenlet_SetParent \
|
||||||
|
(*(int (*)(PyGreenlet * greenlet, PyGreenlet * nparent)) \
|
||||||
|
_PyGreenlet_API[PyGreenlet_SetParent_NUM])
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PyGreenlet_GetParent(PyObject* greenlet)
|
||||||
|
*
|
||||||
|
* return greenlet.parent;
|
||||||
|
*
|
||||||
|
* This could return NULL even if there is no exception active.
|
||||||
|
* If it does not return NULL, you are responsible for decrementing the
|
||||||
|
* reference count.
|
||||||
|
*/
|
||||||
|
# define PyGreenlet_GetParent \
|
||||||
|
(*(PyGreenlet* (*)(PyGreenlet*)) \
|
||||||
|
_PyGreenlet_API[PyGreenlet_GET_PARENT_NUM])
|
||||||
|
|
||||||
|
/*
|
||||||
|
* deprecated, undocumented alias.
|
||||||
|
*/
|
||||||
|
# define PyGreenlet_GET_PARENT PyGreenlet_GetParent
|
||||||
|
|
||||||
|
# define PyGreenlet_MAIN \
|
||||||
|
(*(int (*)(PyGreenlet*)) \
|
||||||
|
_PyGreenlet_API[PyGreenlet_MAIN_NUM])
|
||||||
|
|
||||||
|
# define PyGreenlet_STARTED \
|
||||||
|
(*(int (*)(PyGreenlet*)) \
|
||||||
|
_PyGreenlet_API[PyGreenlet_STARTED_NUM])
|
||||||
|
|
||||||
|
# define PyGreenlet_ACTIVE \
|
||||||
|
(*(int (*)(PyGreenlet*)) \
|
||||||
|
_PyGreenlet_API[PyGreenlet_ACTIVE_NUM])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Macro that imports greenlet and initializes C API */
|
||||||
|
/* NOTE: This has actually moved to ``greenlet._greenlet._C_API``, but we
|
||||||
|
keep the older definition to be sure older code that might have a copy of
|
||||||
|
the header still works. */
|
||||||
|
# define PyGreenlet_Import() \
|
||||||
|
{ \
|
||||||
|
_PyGreenlet_API = (void**)PyCapsule_Import("greenlet._C_API", 0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* GREENLET_MODULE */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* !Py_GREENLETOBJECT_H */
|
||||||
69
.venv311/Include/site/python3.11/igraph/igraphmodule_api.h
Normal file
69
.venv311/Include/site/python3.11/igraph/igraphmodule_api.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/* -*- mode: C -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||||
|
/*
|
||||||
|
IGraph library.
|
||||||
|
Copyright (C) 2006-2023 Tamas Nepusz <ntamas@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Py_IGRAPHMODULE_H
|
||||||
|
#define Py_IGRAPHMODULE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* C API functions */
|
||||||
|
#define PyIGraph_FromCGraph_NUM 0
|
||||||
|
#define PyIGraph_FromCGraph_RETURN PyObject*
|
||||||
|
#define PyIGraph_FromCGraph_PROTO (igraph_t *graph)
|
||||||
|
|
||||||
|
#define PyIGraph_ToCGraph_NUM 1
|
||||||
|
#define PyIGraph_ToCGraph_RETURN igraph_t*
|
||||||
|
#define PyIGraph_ToCGraph_PROTO (PyObject *graph)
|
||||||
|
|
||||||
|
/* Total number of C API pointers */
|
||||||
|
#define PyIGraph_API_pointers 2
|
||||||
|
|
||||||
|
#ifdef IGRAPH_MODULE
|
||||||
|
/* This section is used when compiling igraphmodule.c */
|
||||||
|
static PyIGraph_FromCGraph_RETURN PyIGraph_FromCGraph PyIGraph_FromCGraph_PROTO;
|
||||||
|
static PyIGraph_ToCGraph_RETURN PyIGraph_ToCGraph PyIGraph_ToCGraph_PROTO;
|
||||||
|
#else
|
||||||
|
/* This section is used in modules that use igraph's API */
|
||||||
|
static void** PyIGraph_API;
|
||||||
|
# define PyIGraph_FromCGraph \
|
||||||
|
(*(PyIGraph_FromCGraph_RETURN (*)PyIGraph_FromCGraph_PROTO) \
|
||||||
|
PyIGraph_API[PyIGraph_FromCGraph_NUM])
|
||||||
|
# define PyIGraph_ToCGraph \
|
||||||
|
(*(PyIGraph_ToCGraph_RETURN (*)PyIGraph_ToCGraph_PROTO) \
|
||||||
|
PyIGraph_API[PyIGraph_ToCGraph_NUM])
|
||||||
|
|
||||||
|
/* Return -1 and set exception on error, 0 on success */
|
||||||
|
static int import_igraph(void) {
|
||||||
|
PyIGraph_API = (void **)PyCapsule_Import("igraph._igraph._C_API", 0);
|
||||||
|
return (PyIGraph_API != NULL) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !defined(Py_IGRAPHMODULE_H) */
|
||||||
502
.venv311/Scripts/Activate.ps1
Normal file
502
.venv311/Scripts/Activate.ps1
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Activate a Python virtual environment for the current PowerShell session.
|
||||||
|
|
||||||
|
.Description
|
||||||
|
Pushes the python executable for a virtual environment to the front of the
|
||||||
|
$Env:PATH environment variable and sets the prompt to signify that you are
|
||||||
|
in a Python virtual environment. Makes use of the command line switches as
|
||||||
|
well as the `pyvenv.cfg` file values present in the virtual environment.
|
||||||
|
|
||||||
|
.Parameter VenvDir
|
||||||
|
Path to the directory that contains the virtual environment to activate. The
|
||||||
|
default value for this is the parent of the directory that the Activate.ps1
|
||||||
|
script is located within.
|
||||||
|
|
||||||
|
.Parameter Prompt
|
||||||
|
The prompt prefix to display when this virtual environment is activated. By
|
||||||
|
default, this prompt is the name of the virtual environment folder (VenvDir)
|
||||||
|
surrounded by parentheses and followed by a single space (ie. '(.venv) ').
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1
|
||||||
|
Activates the Python virtual environment that contains the Activate.ps1 script.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1 -Verbose
|
||||||
|
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||||
|
and shows extra information about the activation as it executes.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
|
||||||
|
Activates the Python virtual environment located in the specified location.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1 -Prompt "MyPython"
|
||||||
|
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||||
|
and prefixes the current prompt with the specified string (surrounded in
|
||||||
|
parentheses) while the virtual environment is active.
|
||||||
|
|
||||||
|
.Notes
|
||||||
|
On Windows, it may be required to enable this Activate.ps1 script by setting the
|
||||||
|
execution policy for the user. You can do this by issuing the following PowerShell
|
||||||
|
command:
|
||||||
|
|
||||||
|
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||||
|
|
||||||
|
For more information on Execution Policies:
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=135170
|
||||||
|
|
||||||
|
#>
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[String]
|
||||||
|
$VenvDir,
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[String]
|
||||||
|
$Prompt
|
||||||
|
)
|
||||||
|
|
||||||
|
<# Function declarations --------------------------------------------------- #>
|
||||||
|
|
||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Remove all shell session elements added by the Activate script, including the
|
||||||
|
addition of the virtual environment's Python executable from the beginning of
|
||||||
|
the PATH variable.
|
||||||
|
|
||||||
|
.Parameter NonDestructive
|
||||||
|
If present, do not remove this function from the global namespace for the
|
||||||
|
session.
|
||||||
|
|
||||||
|
#>
|
||||||
|
function global:deactivate ([switch]$NonDestructive) {
|
||||||
|
# Revert to original values
|
||||||
|
|
||||||
|
# The prior prompt:
|
||||||
|
if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
|
||||||
|
Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
|
||||||
|
Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
|
||||||
|
}
|
||||||
|
|
||||||
|
# The prior PYTHONHOME:
|
||||||
|
if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
|
||||||
|
Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
|
||||||
|
Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
}
|
||||||
|
|
||||||
|
# The prior PATH:
|
||||||
|
if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
|
||||||
|
Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
|
||||||
|
Remove-Item -Path Env:_OLD_VIRTUAL_PATH
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just remove the VIRTUAL_ENV altogether:
|
||||||
|
if (Test-Path -Path Env:VIRTUAL_ENV) {
|
||||||
|
Remove-Item -Path env:VIRTUAL_ENV
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just remove VIRTUAL_ENV_PROMPT altogether.
|
||||||
|
if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
|
||||||
|
Remove-Item -Path env:VIRTUAL_ENV_PROMPT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
|
||||||
|
if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
|
||||||
|
Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
# Leave deactivate function in the global namespace if requested:
|
||||||
|
if (-not $NonDestructive) {
|
||||||
|
Remove-Item -Path function:deactivate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<#
|
||||||
|
.Description
|
||||||
|
Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
|
||||||
|
given folder, and returns them in a map.
|
||||||
|
|
||||||
|
For each line in the pyvenv.cfg file, if that line can be parsed into exactly
|
||||||
|
two strings separated by `=` (with any amount of whitespace surrounding the =)
|
||||||
|
then it is considered a `key = value` line. The left hand string is the key,
|
||||||
|
the right hand is the value.
|
||||||
|
|
||||||
|
If the value starts with a `'` or a `"` then the first and last character is
|
||||||
|
stripped from the value before being captured.
|
||||||
|
|
||||||
|
.Parameter ConfigDir
|
||||||
|
Path to the directory that contains the `pyvenv.cfg` file.
|
||||||
|
#>
|
||||||
|
function Get-PyVenvConfig(
|
||||||
|
[String]
|
||||||
|
$ConfigDir
|
||||||
|
) {
|
||||||
|
Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
|
||||||
|
|
||||||
|
# Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
|
||||||
|
$pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
|
||||||
|
|
||||||
|
# An empty map will be returned if no config file is found.
|
||||||
|
$pyvenvConfig = @{ }
|
||||||
|
|
||||||
|
if ($pyvenvConfigPath) {
|
||||||
|
|
||||||
|
Write-Verbose "File exists, parse `key = value` lines"
|
||||||
|
$pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
|
||||||
|
|
||||||
|
$pyvenvConfigContent | ForEach-Object {
|
||||||
|
$keyval = $PSItem -split "\s*=\s*", 2
|
||||||
|
if ($keyval[0] -and $keyval[1]) {
|
||||||
|
$val = $keyval[1]
|
||||||
|
|
||||||
|
# Remove extraneous quotations around a string value.
|
||||||
|
if ("'""".Contains($val.Substring(0, 1))) {
|
||||||
|
$val = $val.Substring(1, $val.Length - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
$pyvenvConfig[$keyval[0]] = $val
|
||||||
|
Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $pyvenvConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<# Begin Activate script --------------------------------------------------- #>
|
||||||
|
|
||||||
|
# Determine the containing directory of this script
|
||||||
|
$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
$VenvExecDir = Get-Item -Path $VenvExecPath
|
||||||
|
|
||||||
|
Write-Verbose "Activation script is located in path: '$VenvExecPath'"
|
||||||
|
Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
|
||||||
|
Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
|
||||||
|
|
||||||
|
# Set values required in priority: CmdLine, ConfigFile, Default
|
||||||
|
# First, get the location of the virtual environment, it might not be
|
||||||
|
# VenvExecDir if specified on the command line.
|
||||||
|
if ($VenvDir) {
|
||||||
|
Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
|
||||||
|
$VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
|
||||||
|
Write-Verbose "VenvDir=$VenvDir"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Next, read the `pyvenv.cfg` file to determine any required value such
|
||||||
|
# as `prompt`.
|
||||||
|
$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
|
||||||
|
|
||||||
|
# Next, set the prompt from the command line, or the config file, or
|
||||||
|
# just use the name of the virtual environment folder.
|
||||||
|
if ($Prompt) {
|
||||||
|
Write-Verbose "Prompt specified as argument, using '$Prompt'"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
|
||||||
|
if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
|
||||||
|
Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
|
||||||
|
$Prompt = $pyvenvCfg['prompt'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
|
||||||
|
Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
|
||||||
|
$Prompt = Split-Path -Path $venvDir -Leaf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose "Prompt = '$Prompt'"
|
||||||
|
Write-Verbose "VenvDir='$VenvDir'"
|
||||||
|
|
||||||
|
# Deactivate any currently active virtual environment, but leave the
|
||||||
|
# deactivate function in place.
|
||||||
|
deactivate -nondestructive
|
||||||
|
|
||||||
|
# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
|
||||||
|
# that there is an activated venv.
|
||||||
|
$env:VIRTUAL_ENV = $VenvDir
|
||||||
|
|
||||||
|
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
||||||
|
|
||||||
|
Write-Verbose "Setting prompt to '$Prompt'"
|
||||||
|
|
||||||
|
# Set the prompt to include the env name
|
||||||
|
# Make sure _OLD_VIRTUAL_PROMPT is global
|
||||||
|
function global:_OLD_VIRTUAL_PROMPT { "" }
|
||||||
|
Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
|
||||||
|
New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
|
||||||
|
|
||||||
|
function global:prompt {
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
|
||||||
|
_OLD_VIRTUAL_PROMPT
|
||||||
|
}
|
||||||
|
$env:VIRTUAL_ENV_PROMPT = $Prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clear PYTHONHOME
|
||||||
|
if (Test-Path -Path Env:PYTHONHOME) {
|
||||||
|
Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
Remove-Item -Path Env:PYTHONHOME
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add the venv to the PATH
|
||||||
|
Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
|
||||||
|
$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
|
||||||
|
|
||||||
|
# SIG # Begin signature block
|
||||||
|
# MIIvIwYJKoZIhvcNAQcCoIIvFDCCLxACAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||||||
|
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
||||||
|
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBnL745ElCYk8vk
|
||||||
|
# dBtMuQhLeWJ3ZGfzKW4DHCYzAn+QB6CCE8MwggWQMIIDeKADAgECAhAFmxtXno4h
|
||||||
|
# MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
|
||||||
|
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
|
||||||
|
# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z
|
||||||
|
# ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
|
||||||
|
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
|
||||||
|
# IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
|
||||||
|
# AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z
|
||||||
|
# G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ
|
||||||
|
# anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s
|
||||||
|
# Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL
|
||||||
|
# 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb
|
||||||
|
# BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3
|
||||||
|
# JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c
|
||||||
|
# AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx
|
||||||
|
# YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0
|
||||||
|
# viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL
|
||||||
|
# T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud
|
||||||
|
# EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf
|
||||||
|
# Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk
|
||||||
|
# aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS
|
||||||
|
# PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK
|
||||||
|
# 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB
|
||||||
|
# cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp
|
||||||
|
# 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg
|
||||||
|
# dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri
|
||||||
|
# RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7
|
||||||
|
# 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5
|
||||||
|
# nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3
|
||||||
|
# i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H
|
||||||
|
# EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G
|
||||||
|
# CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
|
||||||
|
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
|
||||||
|
# IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla
|
||||||
|
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
|
||||||
|
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
|
||||||
|
# ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C
|
||||||
|
# 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce
|
||||||
|
# 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da
|
||||||
|
# E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T
|
||||||
|
# SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA
|
||||||
|
# FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh
|
||||||
|
# D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM
|
||||||
|
# 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z
|
||||||
|
# 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05
|
||||||
|
# huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY
|
||||||
|
# mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP
|
||||||
|
# /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T
|
||||||
|
# AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD
|
||||||
|
# VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG
|
||||||
|
# A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY
|
||||||
|
# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj
|
||||||
|
# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV
|
||||||
|
# HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
|
||||||
|
# cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN
|
||||||
|
# BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry
|
||||||
|
# sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL
|
||||||
|
# IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf
|
||||||
|
# Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh
|
||||||
|
# OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh
|
||||||
|
# dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV
|
||||||
|
# 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j
|
||||||
|
# wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH
|
||||||
|
# Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC
|
||||||
|
# XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l
|
||||||
|
# /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW
|
||||||
|
# eE4wggd3MIIFX6ADAgECAhAHHxQbizANJfMU6yMM0NHdMA0GCSqGSIb3DQEBCwUA
|
||||||
|
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
|
||||||
|
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
|
||||||
|
# ODQgMjAyMSBDQTEwHhcNMjIwMTE3MDAwMDAwWhcNMjUwMTE1MjM1OTU5WjB8MQsw
|
||||||
|
# CQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQHEwlCZWF2ZXJ0b24x
|
||||||
|
# IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMSMwIQYDVQQDExpQ
|
||||||
|
# eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
|
||||||
|
# ADCCAgoCggIBAKgc0BTT+iKbtK6f2mr9pNMUTcAJxKdsuOiSYgDFfwhjQy89koM7
|
||||||
|
# uP+QV/gwx8MzEt3c9tLJvDccVWQ8H7mVsk/K+X+IufBLCgUi0GGAZUegEAeRlSXx
|
||||||
|
# xhYScr818ma8EvGIZdiSOhqjYc4KnfgfIS4RLtZSrDFG2tN16yS8skFa3IHyvWdb
|
||||||
|
# D9PvZ4iYNAS4pjYDRjT/9uzPZ4Pan+53xZIcDgjiTwOh8VGuppxcia6a7xCyKoOA
|
||||||
|
# GjvCyQsj5223v1/Ig7Dp9mGI+nh1E3IwmyTIIuVHyK6Lqu352diDY+iCMpk9Zanm
|
||||||
|
# SjmB+GMVs+H/gOiofjjtf6oz0ki3rb7sQ8fTnonIL9dyGTJ0ZFYKeb6BLA66d2GA
|
||||||
|
# LwxZhLe5WH4Np9HcyXHACkppsE6ynYjTOd7+jN1PRJahN1oERzTzEiV6nCO1M3U1
|
||||||
|
# HbPTGyq52IMFSBM2/07WTJSbOeXjvYR7aUxK9/ZkJiacl2iZI7IWe7JKhHohqKuc
|
||||||
|
# eQNyOzxTakLcRkzynvIrk33R9YVqtB4L6wtFxhUjvDnQg16xot2KVPdfyPAWd81w
|
||||||
|
# tZADmrUtsZ9qG79x1hBdyOl4vUtVPECuyhCxaw+faVjumapPUnwo8ygflJJ74J+B
|
||||||
|
# Yxf6UuD7m8yzsfXWkdv52DjL74TxzuFTLHPyARWCSCAbzn3ZIly+qIqDAgMBAAGj
|
||||||
|
# ggIGMIICAjAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNVHQ4E
|
||||||
|
# FgQUt/1Teh2XDuUj2WW3siYWJgkZHA8wDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM
|
||||||
|
# MAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwzLmRp
|
||||||
|
# Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNI
|
||||||
|
# QTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5jb20v
|
||||||
|
# RGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0Ex
|
||||||
|
# LmNybDA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUFBwIBFhtodHRwOi8v
|
||||||
|
# d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgZQGCCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUF
|
||||||
|
# BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6
|
||||||
|
# Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu
|
||||||
|
# aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZI
|
||||||
|
# hvcNAQELBQADggIBABxv4AeV/5ltkELHSC63fXAFYS5tadcWTiNc2rskrNLrfH1N
|
||||||
|
# s0vgSZFoQxYBFKI159E8oQQ1SKbTEubZ/B9kmHPhprHya08+VVzxC88pOEvz68nA
|
||||||
|
# 82oEM09584aILqYmj8Pj7h/kmZNzuEL7WiwFa/U1hX+XiWfLIJQsAHBla0i7QRF2
|
||||||
|
# de8/VSF0XXFa2kBQ6aiTsiLyKPNbaNtbcucaUdn6vVUS5izWOXM95BSkFSKdE45O
|
||||||
|
# q3FForNJXjBvSCpwcP36WklaHL+aHu1upIhCTUkzTHMh8b86WmjRUqbrnvdyR2yd
|
||||||
|
# I5l1OqcMBjkpPpIV6wcc+KY/RH2xvVuuoHjlUjwq2bHiNoX+W1scCpnA8YTs2d50
|
||||||
|
# jDHUgwUo+ciwpffH0Riq132NFmrH3r67VaN3TuBxjI8SIZM58WEDkbeoriDk3hxU
|
||||||
|
# 8ZWV7b8AW6oyVBGfM06UgkfMb58h+tJPrFx8VI/WLq1dTqMfZOm5cuclMnUHs2uq
|
||||||
|
# rRNtnV8UfidPBL4ZHkTcClQbCoz0UbLhkiDvIS00Dn+BBcxw/TKqVL4Oaz3bkMSs
|
||||||
|
# M46LciTeucHY9ExRVt3zy7i149sd+F4QozPqn7FrSVHXmem3r7bjyHTxOgqxRCVa
|
||||||
|
# 18Vtx7P/8bYSBeS+WHCKcliFCecspusCDSlnRUjZwyPdP0VHxaZg2unjHY3rMYIa
|
||||||
|
# tjCCGrICAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIElu
|
||||||
|
# Yy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJT
|
||||||
|
# QTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAHHxQbizANJfMU6yMM0NHdMA0GCWCGSAFl
|
||||||
|
# AwQCAQUAoIHIMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC
|
||||||
|
# AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCBnAZ6P7YvTwq0fbF62
|
||||||
|
# o7E75R0LxsW5OtyYiFESQckLhjBcBgorBgEEAYI3AgEMMU4wTKBGgEQAQgB1AGkA
|
||||||
|
# bAB0ADoAIABSAGUAbABlAGEAcwBlAF8AdgAzAC4AMQAxAC4AOQBfADIAMAAyADQA
|
||||||
|
# MAA0ADAAMgAuADAAMqECgAAwDQYJKoZIhvcNAQEBBQAEggIAg5wQO5NiKFirm9vr
|
||||||
|
# 1//X5G4t+z318Uagu8vJT/vTjkMTau86CF+SwP3pqC1H2ZMUyVYmVHae5dswKAMR
|
||||||
|
# hHY1VJV/0lJI+LdYcaxHI/WYzaFLbDrQI/Mty5cabjveG6geMlcJG4nYZlyQX+fJ
|
||||||
|
# 1k0ogeIF1owldecXP8t5e10WlHBlWb8IBnIPwMtJVZ2/y8NASxsnSJE7pEe7ijGe
|
||||||
|
# 5Bv9DXvoltKnMSVYv9u2vn7PeIq+Jm3n3kOGSIYtfdytEd1Fd6spfdcmIhqyzVk0
|
||||||
|
# Hslq7Aqd7soT0xdmNa/amzEA4HRHpWGUhzOtcC+EqEIIJk9kTjyVgCiyWaB5gGko
|
||||||
|
# OAZfsxQn+a916iWwA7RrQ+TzBZq/pleUTLZzJmI3DXFjuJ1NDP6Sdw6KREgx6Yw4
|
||||||
|
# q2NnnodKlGZkMDcGYPTM2sA4i6i6FsznWY4d8wE4J261YeUrVfIyTx+Q81W4KXoi
|
||||||
|
# C0x7Pe9Bjh4oJGM3YiLyhVL56sXZWxAC2C/vD3nvIvra9EpvlMvQh6b0xl0V4TSN
|
||||||
|
# dJ7T7VttR/WNjau46JIgbGZWCDBTTUAydQNoAZ4KnCrcIZCN6Y0qVokXsYHsVIto
|
||||||
|
# TsnM2+Ca09wxuOIfCOSKpAmqdJ/w2NwLwp+0gwrO2uzpCfbSbkAd+UQNv0joPyUp
|
||||||
|
# ywmsQndxqA8TaADp8TfkkpJywJGhghc/MIIXOwYKKwYBBAGCNwMDATGCFyswghcn
|
||||||
|
# BgkqhkiG9w0BBwKgghcYMIIXFAIBAzEPMA0GCWCGSAFlAwQCAQUAMHcGCyqGSIb3
|
||||||
|
# DQEJEAEEoGgEZjBkAgEBBglghkgBhv1sBwEwMTANBglghkgBZQMEAgEFAAQg+Jhe
|
||||||
|
# IOzOttA8vliuL+r3CiY4EJTzfvPasXkI/vwkoI8CEHZ95Ht1TmSmU8+fM0kIG00Y
|
||||||
|
# DzIwMjQwNDAyMTIzMjEwWqCCEwkwggbCMIIEqqADAgECAhAFRK/zlJ0IOaa/2z9f
|
||||||
|
# 5WEWMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdp
|
||||||
|
# Q2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2
|
||||||
|
# IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjMwNzE0MDAwMDAwWhcNMzQxMDEz
|
||||||
|
# MjM1OTU5WjBIMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4x
|
||||||
|
# IDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDIzMIICIjANBgkqhkiG9w0B
|
||||||
|
# AQEFAAOCAg8AMIICCgKCAgEAo1NFhx2DjlusPlSzI+DPn9fl0uddoQ4J3C9Io5d6
|
||||||
|
# OyqcZ9xiFVjBqZMRp82qsmrdECmKHmJjadNYnDVxvzqX65RQjxwg6seaOy+WZuNp
|
||||||
|
# 52n+W8PWKyAcwZeUtKVQgfLPywemMGjKg0La/H8JJJSkghraarrYO8pd3hkYhftF
|
||||||
|
# 6g1hbJ3+cV7EBpo88MUueQ8bZlLjyNY+X9pD04T10Mf2SC1eRXWWdf7dEKEbg8G4
|
||||||
|
# 5lKVtUfXeCk5a+B4WZfjRCtK1ZXO7wgX6oJkTf8j48qG7rSkIWRw69XloNpjsy7p
|
||||||
|
# Be6q9iT1HbybHLK3X9/w7nZ9MZllR1WdSiQvrCuXvp/k/XtzPjLuUjT71Lvr1KAs
|
||||||
|
# NJvj3m5kGQc3AZEPHLVRzapMZoOIaGK7vEEbeBlt5NkP4FhB+9ixLOFRr7StFQYU
|
||||||
|
# 6mIIE9NpHnxkTZ0P387RXoyqq1AVybPKvNfEO2hEo6U7Qv1zfe7dCv95NBB+plwK
|
||||||
|
# WEwAPoVpdceDZNZ1zY8SdlalJPrXxGshuugfNJgvOuprAbD3+yqG7HtSOKmYCaFx
|
||||||
|
# smxxrz64b5bV4RAT/mFHCoz+8LbH1cfebCTwv0KCyqBxPZySkwS0aXAnDU+3tTbR
|
||||||
|
# yV8IpHCj7ArxES5k4MsiK8rxKBMhSVF+BmbTO77665E42FEHypS34lCh8zrTioPL
|
||||||
|
# QHsCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYG
|
||||||
|
# A1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCG
|
||||||
|
# SAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57IbzAdBgNVHQ4E
|
||||||
|
# FgQUpbbvE+fvzdBkodVWqWUxo97V40kwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDov
|
||||||
|
# L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1
|
||||||
|
# NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAwJAYIKwYBBQUH
|
||||||
|
# MAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcwAoZMaHR0cDov
|
||||||
|
# L2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNI
|
||||||
|
# QTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAgRrW3qCp
|
||||||
|
# tZgXvHCNT4o8aJzYJf/LLOTN6l0ikuyMIgKpuM+AqNnn48XtJoKKcS8Y3U623mzX
|
||||||
|
# 4WCcK+3tPUiOuGu6fF29wmE3aEl3o+uQqhLXJ4Xzjh6S2sJAOJ9dyKAuJXglnSoF
|
||||||
|
# eoQpmLZXeY/bJlYrsPOnvTcM2Jh2T1a5UsK2nTipgedtQVyMadG5K8TGe8+c+nji
|
||||||
|
# kxp2oml101DkRBK+IA2eqUTQ+OVJdwhaIcW0z5iVGlS6ubzBaRm6zxbygzc0brBB
|
||||||
|
# Jt3eWpdPM43UjXd9dUWhpVgmagNF3tlQtVCMr1a9TMXhRsUo063nQwBw3syYnhmJ
|
||||||
|
# A+rUkTfvTVLzyWAhxFZH7doRS4wyw4jmWOK22z75X7BC1o/jF5HRqsBV44a/rCcs
|
||||||
|
# QdCaM0qoNtS5cpZ+l3k4SF/Kwtw9Mt911jZnWon49qfH5U81PAC9vpwqbHkB3NpE
|
||||||
|
# 5jreODsHXjlY9HxzMVWggBHLFAx+rrz+pOt5Zapo1iLKO+uagjVXKBbLafIymrLS
|
||||||
|
# 2Dq4sUaGa7oX/cR3bBVsrquvczroSUa31X/MtjjA2Owc9bahuEMs305MfR5ocMB3
|
||||||
|
# CtQC4Fxguyj/OOVSWtasFyIjTvTs0xf7UGv/B3cfcZdEQcm4RtNsMnxYL2dHZeUb
|
||||||
|
# c7aZ+WssBkbvQR7w8F/g29mtkIBEr4AQQYowggauMIIElqADAgECAhAHNje3JFR8
|
||||||
|
# 2Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
|
||||||
|
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
|
||||||
|
# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMjAzMjMwMDAwMDBaFw0z
|
||||||
|
# NzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
|
||||||
|
# SW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1
|
||||||
|
# NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
|
||||||
|
# AQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbSg9GeTKJtoLDMg/la9hGhRBVCX6SI
|
||||||
|
# 82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9/UO0hNoR8XOxs+4rgISKIhjf69o9
|
||||||
|
# xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXnHwZljZQp09nsad/ZkIdGAHvbREGJ
|
||||||
|
# 3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0VAshaG43IbtArF+y3kp9zvU5Emfv
|
||||||
|
# DqVjbOSmxR3NNg1c1eYbqMFkdECnwHLFuk4fsbVYTXn+149zk6wsOeKlSNbwsDET
|
||||||
|
# qVcplicu9Yemj052FVUmcJgmf6AaRyBD40NjgHt1biclkJg6OBGz9vae5jtb7IHe
|
||||||
|
# IhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0QCirc0PO30qhHGs4xSnzyqqWc0Jo
|
||||||
|
# n7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvvmz3+DrhkKvp1KCRB7UK/BZxmSVJQ
|
||||||
|
# 9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T/jnA+bIwpUzX6ZhKWD7TA4j+s4/T
|
||||||
|
# Xkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk42PgpuE+9sJ0sj8eCXbsq11GdeJg
|
||||||
|
# o1gJASgADoRU7s7pXcheMBK9Rp6103a50g5rmQzSM7TNsQIDAQABo4IBXTCCAVkw
|
||||||
|
# EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUuhbZbU2FL3MpdpovdYxqII+e
|
||||||
|
# yG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQD
|
||||||
|
# AgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEF
|
||||||
|
# BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRw
|
||||||
|
# Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNy
|
||||||
|
# dDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGln
|
||||||
|
# aUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglg
|
||||||
|
# hkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBAH1ZjsCTtm+YqUQiAX5m1tghQuGw
|
||||||
|
# GC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxpwc8dB+k+YMjYC+VcW9dth/qEICU0
|
||||||
|
# MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIlzpVpP0d3+3J0FNf/q0+KLHqrhc1D
|
||||||
|
# X+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQcAp876i8dU+6WvepELJd6f8oVInw
|
||||||
|
# 1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfeKuv2nrF5mYGjVoarCkXJ38SNoOeY
|
||||||
|
# +/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+jSbl3ZpHxcpzpSwJSpzd+k1OsOx0I
|
||||||
|
# SQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJshIUDQtxMkzdwdeDrknq3lNHGS1yZr
|
||||||
|
# 5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6OOmc4d0j/R0o08f56PGYX/sr2H7y
|
||||||
|
# Rp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDwN7+YAN8gFk8n+2BnFqFmut1VwDop
|
||||||
|
# hrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR81fZvAT6gt4y3wSJ8ADNXcL50CN/
|
||||||
|
# AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2VVQrH4D6wPIOK+XW+6kvRBVK5xMO
|
||||||
|
# Hds3OBqhK/bt1nz8MIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkq
|
||||||
|
# hkiG9w0BAQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j
|
||||||
|
# MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBB
|
||||||
|
# c3N1cmVkIElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5
|
||||||
|
# WjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
|
||||||
|
# ExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJv
|
||||||
|
# b3QgRzQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1K
|
||||||
|
# PDAiMGkz7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2r
|
||||||
|
# snnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C
|
||||||
|
# 8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBf
|
||||||
|
# sXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
|
||||||
|
# QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8
|
||||||
|
# rhsDdV14Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaY
|
||||||
|
# dj1ZXUJ2h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+
|
||||||
|
# wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw
|
||||||
|
# ++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+N
|
||||||
|
# P8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7F
|
||||||
|
# wI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUw
|
||||||
|
# AwEB/zAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAU
|
||||||
|
# Reuir/SSy4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEB
|
||||||
|
# BG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsG
|
||||||
|
# AQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1
|
||||||
|
# cmVkSURSb290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRp
|
||||||
|
# Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAow
|
||||||
|
# CDAGBgRVHSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/
|
||||||
|
# Vwe9mqyhhyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLe
|
||||||
|
# JLxSA8hO0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE
|
||||||
|
# 1Od/6Fmo8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9Hda
|
||||||
|
# XFSMb++hUD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbO
|
||||||
|
# byMt9H5xaiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMYID
|
||||||
|
# djCCA3ICAQEwdzBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIElu
|
||||||
|
# Yy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYg
|
||||||
|
# VGltZVN0YW1waW5nIENBAhAFRK/zlJ0IOaa/2z9f5WEWMA0GCWCGSAFlAwQCAQUA
|
||||||
|
# oIHRMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcN
|
||||||
|
# MjQwNDAyMTIzMjEwWjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBRm8CsywsLJD4Jd
|
||||||
|
# zqqKycZPGZzPQDAvBgkqhkiG9w0BCQQxIgQg58bvIvjFkyBb2O0xwLgtU8RJLcMV
|
||||||
|
# kvIdXiq3TCLuhq4wNwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQg0vbkbe10IszR1EBX
|
||||||
|
# aEE2b4KK2lWarjMWr00amtQMeCgwDQYJKoZIhvcNAQEBBQAEggIAhU3imuIvql4+
|
||||||
|
# IqPz0Anf0ZIB5hbafNTx1WEVhPEG9iJr24gpjbWvepQrbWJf0FBj8wY9GeRab6iv
|
||||||
|
# 79MMxZkPpR/DMK1qFr1vIlw67JhpqqNkaNIa5G3pAHDYdHYcB+Utw1p5XPOBRu0A
|
||||||
|
# f4wQ5fwWugys4CGGAboq4prLNRKeUGVexMDK7Eorsv9xmzK0tE9QSMA3SxLCcSIX
|
||||||
|
# mrMkKzTR3vn0dqaDG4Ge7U2w7dVnQYGBX+s6C9CCjvCtenCAQLbF+OyYhkMNDVtJ
|
||||||
|
# lTmzxxwyyA5fFZJpG/Wfo/84/P8lQXUTuwOBpFoLE65OqNEG03SoqKsW4aTqkVM7
|
||||||
|
# b6fKLsygm1w23+UlHGF/fbExeqxgOZiuJWWt/OFy9T3HIcAF1SMh7mot5ciu7btS
|
||||||
|
# xjkr/fhsi1M3M1g/giyn0I8N24mgaICPtXAzAbZW7GSC0R5T2qnW6gYoAcY62Qdz
|
||||||
|
# jl/Ey1rnOQ26TuQODyPVHhfhoIBbdIDpDJ2Vu2mxyxUnjATbizphcBgsU1fBYvZR
|
||||||
|
# v+SuK1MYZOGqgzugfiufdeFAlBDA/e64yRkJvDBEkcyGvj6FS6nVm7ekJpJhLU3z
|
||||||
|
# sSSmcYwdx1YQCr48HEjcmGrj5sAzzg4U4WU/GrLWz2sSRmh5rKcDAa0ewfYi13Z2
|
||||||
|
# a/cdr8Or2RQ5ZSQ8OHgr3GBw7koDWR8=
|
||||||
|
# SIG # End signature block
|
||||||
63
.venv311/Scripts/activate
Normal file
63
.venv311/Scripts/activate
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# This file must be used with "source bin/activate" *from bash*
|
||||||
|
# you cannot run it directly
|
||||||
|
|
||||||
|
deactivate () {
|
||||||
|
# reset old environment variables
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
|
||||||
|
PATH="${_OLD_VIRTUAL_PATH:-}"
|
||||||
|
export PATH
|
||||||
|
unset _OLD_VIRTUAL_PATH
|
||||||
|
fi
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
|
||||||
|
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
|
||||||
|
export PYTHONHOME
|
||||||
|
unset _OLD_VIRTUAL_PYTHONHOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Call hash to forget past commands. Without forgetting
|
||||||
|
# past commands the $PATH changes we made may not be respected
|
||||||
|
hash -r 2> /dev/null
|
||||||
|
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
|
||||||
|
PS1="${_OLD_VIRTUAL_PS1:-}"
|
||||||
|
export PS1
|
||||||
|
unset _OLD_VIRTUAL_PS1
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset VIRTUAL_ENV
|
||||||
|
unset VIRTUAL_ENV_PROMPT
|
||||||
|
if [ ! "${1:-}" = "nondestructive" ] ; then
|
||||||
|
# Self destruct!
|
||||||
|
unset -f deactivate
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# unset irrelevant variables
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
VIRTUAL_ENV="D:\code\MoFox_Bot\.venv311"
|
||||||
|
export VIRTUAL_ENV
|
||||||
|
|
||||||
|
_OLD_VIRTUAL_PATH="$PATH"
|
||||||
|
PATH="$VIRTUAL_ENV/Scripts:$PATH"
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
# unset PYTHONHOME if set
|
||||||
|
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
|
||||||
|
# could use `if (set -u; : $PYTHONHOME) ;` in bash
|
||||||
|
if [ -n "${PYTHONHOME:-}" ] ; then
|
||||||
|
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
|
||||||
|
unset PYTHONHOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
|
||||||
|
_OLD_VIRTUAL_PS1="${PS1:-}"
|
||||||
|
PS1="(.venv311) ${PS1:-}"
|
||||||
|
export PS1
|
||||||
|
VIRTUAL_ENV_PROMPT="(.venv311) "
|
||||||
|
export VIRTUAL_ENV_PROMPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Call hash to forget past commands. Without forgetting
|
||||||
|
# past commands the $PATH changes we made may not be respected
|
||||||
|
hash -r 2> /dev/null
|
||||||
34
.venv311/Scripts/activate.bat
Normal file
34
.venv311/Scripts/activate.bat
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
rem This file is UTF-8 encoded, so we need to update the current code page while executing it
|
||||||
|
for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do (
|
||||||
|
set _OLD_CODEPAGE=%%a
|
||||||
|
)
|
||||||
|
if defined _OLD_CODEPAGE (
|
||||||
|
"%SystemRoot%\System32\chcp.com" 65001 > nul
|
||||||
|
)
|
||||||
|
|
||||||
|
set VIRTUAL_ENV=D:\code\MoFox_Bot\.venv311
|
||||||
|
|
||||||
|
if not defined PROMPT set PROMPT=$P$G
|
||||||
|
|
||||||
|
if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT%
|
||||||
|
if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PROMPT=%PROMPT%
|
||||||
|
set PROMPT=(.venv311) %PROMPT%
|
||||||
|
|
||||||
|
if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%
|
||||||
|
set PYTHONHOME=
|
||||||
|
|
||||||
|
if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
|
||||||
|
if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%
|
||||||
|
|
||||||
|
set PATH=%VIRTUAL_ENV%\Scripts;%PATH%
|
||||||
|
set VIRTUAL_ENV_PROMPT=(.venv311)
|
||||||
|
|
||||||
|
:END
|
||||||
|
if defined _OLD_CODEPAGE (
|
||||||
|
"%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul
|
||||||
|
set _OLD_CODEPAGE=
|
||||||
|
)
|
||||||
BIN
.venv311/Scripts/chroma.exe
Normal file
BIN
.venv311/Scripts/chroma.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/coloredlogs.exe
Normal file
BIN
.venv311/Scripts/coloredlogs.exe
Normal file
Binary file not shown.
22
.venv311/Scripts/deactivate.bat
Normal file
22
.venv311/Scripts/deactivate.bat
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
if defined _OLD_VIRTUAL_PROMPT (
|
||||||
|
set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
|
||||||
|
)
|
||||||
|
set _OLD_VIRTUAL_PROMPT=
|
||||||
|
|
||||||
|
if defined _OLD_VIRTUAL_PYTHONHOME (
|
||||||
|
set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%"
|
||||||
|
set _OLD_VIRTUAL_PYTHONHOME=
|
||||||
|
)
|
||||||
|
|
||||||
|
if defined _OLD_VIRTUAL_PATH (
|
||||||
|
set "PATH=%_OLD_VIRTUAL_PATH%"
|
||||||
|
)
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PATH=
|
||||||
|
|
||||||
|
set VIRTUAL_ENV=
|
||||||
|
set VIRTUAL_ENV_PROMPT=
|
||||||
|
|
||||||
|
:END
|
||||||
BIN
.venv311/Scripts/distro.exe
Normal file
BIN
.venv311/Scripts/distro.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/dotenv.exe
Normal file
BIN
.venv311/Scripts/dotenv.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/f2py.exe
Normal file
BIN
.venv311/Scripts/f2py.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/fastapi.exe
Normal file
BIN
.venv311/Scripts/fastapi.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/fonttools.exe
Normal file
BIN
.venv311/Scripts/fonttools.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/hf.exe
Normal file
BIN
.venv311/Scripts/hf.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/httpx.exe
Normal file
BIN
.venv311/Scripts/httpx.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/huggingface-cli.exe
Normal file
BIN
.venv311/Scripts/huggingface-cli.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/humanfriendly.exe
Normal file
BIN
.venv311/Scripts/humanfriendly.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/igraph.exe
Normal file
BIN
.venv311/Scripts/igraph.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/isympy.exe
Normal file
BIN
.venv311/Scripts/isympy.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/json_repair.exe
Normal file
BIN
.venv311/Scripts/json_repair.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/jsonschema.exe
Normal file
BIN
.venv311/Scripts/jsonschema.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/markdown-it.exe
Normal file
BIN
.venv311/Scripts/markdown-it.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/mcp.exe
Normal file
BIN
.venv311/Scripts/mcp.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/normalizer.exe
Normal file
BIN
.venv311/Scripts/normalizer.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/numpy-config.exe
Normal file
BIN
.venv311/Scripts/numpy-config.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/onnxruntime_test.exe
Normal file
BIN
.venv311/Scripts/onnxruntime_test.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/openai.exe
Normal file
BIN
.venv311/Scripts/openai.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pip.exe
Normal file
BIN
.venv311/Scripts/pip.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pip3.11.exe
Normal file
BIN
.venv311/Scripts/pip3.11.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pip3.exe
Normal file
BIN
.venv311/Scripts/pip3.exe
Normal file
Binary file not shown.
228
.venv311/Scripts/pwiz.py
Normal file
228
.venv311/Scripts/pwiz.py
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
#!D:\code\MoFox_Bot\.venv311\Scripts\python.exe
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from getpass import getpass
|
||||||
|
from optparse import OptionParser
|
||||||
|
|
||||||
|
from peewee import *
|
||||||
|
from peewee import print_
|
||||||
|
from peewee import __version__ as peewee_version
|
||||||
|
from playhouse.cockroachdb import CockroachDatabase
|
||||||
|
from playhouse.reflection import *
|
||||||
|
|
||||||
|
|
||||||
|
HEADER = """from peewee import *%s
|
||||||
|
|
||||||
|
database = %s('%s'%s)
|
||||||
|
"""
|
||||||
|
|
||||||
|
BASE_MODEL = """\
|
||||||
|
class BaseModel(Model):
|
||||||
|
class Meta:
|
||||||
|
database = database
|
||||||
|
"""
|
||||||
|
|
||||||
|
UNKNOWN_FIELD = """\
|
||||||
|
class UnknownField(object):
|
||||||
|
def __init__(self, *_, **__): pass
|
||||||
|
"""
|
||||||
|
|
||||||
|
DATABASE_ALIASES = {
|
||||||
|
CockroachDatabase: ['cockroach', 'cockroachdb', 'crdb'],
|
||||||
|
MySQLDatabase: ['mysql', 'mysqldb'],
|
||||||
|
PostgresqlDatabase: ['postgres', 'postgresql'],
|
||||||
|
SqliteDatabase: ['sqlite', 'sqlite3'],
|
||||||
|
}
|
||||||
|
|
||||||
|
DATABASE_MAP = dict((value, key)
|
||||||
|
for key in DATABASE_ALIASES
|
||||||
|
for value in DATABASE_ALIASES[key])
|
||||||
|
|
||||||
|
def make_introspector(database_type, database_name, **kwargs):
|
||||||
|
if database_type not in DATABASE_MAP:
|
||||||
|
err('Unrecognized database, must be one of: %s' %
|
||||||
|
', '.join(DATABASE_MAP.keys()))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
schema = kwargs.pop('schema', None)
|
||||||
|
DatabaseClass = DATABASE_MAP[database_type]
|
||||||
|
db = DatabaseClass(database_name, **kwargs)
|
||||||
|
return Introspector.from_database(db, schema=schema)
|
||||||
|
|
||||||
|
def print_models(introspector, tables=None, preserve_order=False,
|
||||||
|
include_views=False, ignore_unknown=False, snake_case=True):
|
||||||
|
database = introspector.introspect(table_names=tables,
|
||||||
|
include_views=include_views,
|
||||||
|
snake_case=snake_case)
|
||||||
|
|
||||||
|
db_kwargs = introspector.get_database_kwargs()
|
||||||
|
header = HEADER % (
|
||||||
|
introspector.get_additional_imports(),
|
||||||
|
introspector.get_database_class().__name__,
|
||||||
|
introspector.get_database_name().replace('\\', '\\\\'),
|
||||||
|
', **%s' % repr(db_kwargs) if db_kwargs else '')
|
||||||
|
print_(header)
|
||||||
|
|
||||||
|
if not ignore_unknown:
|
||||||
|
print_(UNKNOWN_FIELD)
|
||||||
|
|
||||||
|
print_(BASE_MODEL)
|
||||||
|
|
||||||
|
def _print_table(table, seen, accum=None):
|
||||||
|
accum = accum or []
|
||||||
|
foreign_keys = database.foreign_keys[table]
|
||||||
|
for foreign_key in foreign_keys:
|
||||||
|
dest = foreign_key.dest_table
|
||||||
|
|
||||||
|
# In the event the destination table has already been pushed
|
||||||
|
# for printing, then we have a reference cycle.
|
||||||
|
if dest in accum and table not in accum:
|
||||||
|
print_('# Possible reference cycle: %s' % dest)
|
||||||
|
|
||||||
|
# If this is not a self-referential foreign key, and we have
|
||||||
|
# not already processed the destination table, do so now.
|
||||||
|
if dest not in seen and dest not in accum:
|
||||||
|
seen.add(dest)
|
||||||
|
if dest != table:
|
||||||
|
_print_table(dest, seen, accum + [table])
|
||||||
|
|
||||||
|
print_('class %s(BaseModel):' % database.model_names[table])
|
||||||
|
columns = database.columns[table].items()
|
||||||
|
if not preserve_order:
|
||||||
|
columns = sorted(columns)
|
||||||
|
primary_keys = database.primary_keys[table]
|
||||||
|
for name, column in columns:
|
||||||
|
skip = all([
|
||||||
|
name in primary_keys,
|
||||||
|
name == 'id',
|
||||||
|
len(primary_keys) == 1,
|
||||||
|
column.field_class in introspector.pk_classes])
|
||||||
|
if skip:
|
||||||
|
continue
|
||||||
|
if column.primary_key and len(primary_keys) > 1:
|
||||||
|
# If we have a CompositeKey, then we do not want to explicitly
|
||||||
|
# mark the columns as being primary keys.
|
||||||
|
column.primary_key = False
|
||||||
|
|
||||||
|
is_unknown = column.field_class is UnknownField
|
||||||
|
if is_unknown and ignore_unknown:
|
||||||
|
disp = '%s - %s' % (column.name, column.raw_column_type or '?')
|
||||||
|
print_(' # %s' % disp)
|
||||||
|
else:
|
||||||
|
print_(' %s' % column.get_field())
|
||||||
|
|
||||||
|
print_('')
|
||||||
|
print_(' class Meta:')
|
||||||
|
print_(' table_name = \'%s\'' % table)
|
||||||
|
multi_column_indexes = database.multi_column_indexes(table)
|
||||||
|
if multi_column_indexes:
|
||||||
|
print_(' indexes = (')
|
||||||
|
for fields, unique in sorted(multi_column_indexes):
|
||||||
|
print_(' ((%s), %s),' % (
|
||||||
|
', '.join("'%s'" % field for field in fields),
|
||||||
|
unique,
|
||||||
|
))
|
||||||
|
print_(' )')
|
||||||
|
|
||||||
|
if introspector.schema:
|
||||||
|
print_(' schema = \'%s\'' % introspector.schema)
|
||||||
|
if len(primary_keys) > 1:
|
||||||
|
pk_field_names = sorted([
|
||||||
|
field.name for col, field in columns
|
||||||
|
if col in primary_keys])
|
||||||
|
pk_list = ', '.join("'%s'" % pk for pk in pk_field_names)
|
||||||
|
print_(' primary_key = CompositeKey(%s)' % pk_list)
|
||||||
|
elif not primary_keys:
|
||||||
|
print_(' primary_key = False')
|
||||||
|
print_('')
|
||||||
|
|
||||||
|
seen.add(table)
|
||||||
|
|
||||||
|
seen = set()
|
||||||
|
for table in sorted(database.model_names.keys()):
|
||||||
|
if table not in seen:
|
||||||
|
if not tables or table in tables:
|
||||||
|
_print_table(table, seen)
|
||||||
|
|
||||||
|
def print_header(cmd_line, introspector):
|
||||||
|
timestamp = datetime.datetime.now()
|
||||||
|
print_('# Code generated by:')
|
||||||
|
print_('# python -m pwiz %s' % cmd_line)
|
||||||
|
print_('# Date: %s' % timestamp.strftime('%B %d, %Y %I:%M%p'))
|
||||||
|
print_('# Database: %s' % introspector.get_database_name())
|
||||||
|
print_('# Peewee version: %s' % peewee_version)
|
||||||
|
print_('')
|
||||||
|
|
||||||
|
|
||||||
|
def err(msg):
|
||||||
|
sys.stderr.write('\033[91m%s\033[0m\n' % msg)
|
||||||
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
def get_option_parser():
|
||||||
|
parser = OptionParser(usage='usage: %prog [options] database_name')
|
||||||
|
ao = parser.add_option
|
||||||
|
ao('-H', '--host', dest='host')
|
||||||
|
ao('-p', '--port', dest='port', type='int')
|
||||||
|
ao('-u', '--user', dest='user')
|
||||||
|
ao('-P', '--password', dest='password', action='store_true')
|
||||||
|
engines = sorted(DATABASE_MAP)
|
||||||
|
ao('-e', '--engine', dest='engine', choices=engines,
|
||||||
|
help=('Database type, e.g. sqlite, mysql, postgresql or cockroachdb. '
|
||||||
|
'Default is "postgresql".'))
|
||||||
|
ao('-s', '--schema', dest='schema')
|
||||||
|
ao('-t', '--tables', dest='tables',
|
||||||
|
help=('Only generate the specified tables. Multiple table names should '
|
||||||
|
'be separated by commas.'))
|
||||||
|
ao('-v', '--views', dest='views', action='store_true',
|
||||||
|
help='Generate model classes for VIEWs in addition to tables.')
|
||||||
|
ao('-i', '--info', dest='info', action='store_true',
|
||||||
|
help=('Add database information and other metadata to top of the '
|
||||||
|
'generated file.'))
|
||||||
|
ao('-o', '--preserve-order', action='store_true', dest='preserve_order',
|
||||||
|
help='Model definition column ordering matches source table.')
|
||||||
|
ao('-I', '--ignore-unknown', action='store_true', dest='ignore_unknown',
|
||||||
|
help='Ignore fields whose type cannot be determined.')
|
||||||
|
ao('-L', '--legacy-naming', action='store_true', dest='legacy_naming',
|
||||||
|
help='Use legacy table- and column-name generation.')
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def get_connect_kwargs(options):
|
||||||
|
ops = ('host', 'port', 'user', 'schema')
|
||||||
|
kwargs = dict((o, getattr(options, o)) for o in ops if getattr(options, o))
|
||||||
|
if options.password:
|
||||||
|
kwargs['password'] = getpass()
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
raw_argv = sys.argv
|
||||||
|
|
||||||
|
parser = get_option_parser()
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
|
if len(args) < 1:
|
||||||
|
err('Missing required parameter "database"')
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
connect = get_connect_kwargs(options)
|
||||||
|
database = args[-1]
|
||||||
|
|
||||||
|
tables = None
|
||||||
|
if options.tables:
|
||||||
|
tables = [table.strip() for table in options.tables.split(',')
|
||||||
|
if table.strip()]
|
||||||
|
|
||||||
|
engine = options.engine
|
||||||
|
if engine is None:
|
||||||
|
engine = 'sqlite' if os.path.exists(database) else 'postgresql'
|
||||||
|
|
||||||
|
introspector = make_introspector(engine, database, **connect)
|
||||||
|
if options.info:
|
||||||
|
cmd_line = ' '.join(raw_argv[1:])
|
||||||
|
print_header(cmd_line, introspector)
|
||||||
|
|
||||||
|
print_models(introspector, tables, options.preserve_order, options.views,
|
||||||
|
options.ignore_unknown, not options.legacy_naming)
|
||||||
BIN
.venv311/Scripts/pybase64.exe
Normal file
BIN
.venv311/Scripts/pybase64.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyftmerge.exe
Normal file
BIN
.venv311/Scripts/pyftmerge.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyftsubset.exe
Normal file
BIN
.venv311/Scripts/pyftsubset.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pygmentize.exe
Normal file
BIN
.venv311/Scripts/pygmentize.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyjson5.exe
Normal file
BIN
.venv311/Scripts/pyjson5.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pypinyin.exe
Normal file
BIN
.venv311/Scripts/pypinyin.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyproject-build.exe
Normal file
BIN
.venv311/Scripts/pyproject-build.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyrsa-decrypt.exe
Normal file
BIN
.venv311/Scripts/pyrsa-decrypt.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyrsa-encrypt.exe
Normal file
BIN
.venv311/Scripts/pyrsa-encrypt.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyrsa-keygen.exe
Normal file
BIN
.venv311/Scripts/pyrsa-keygen.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyrsa-priv2pub.exe
Normal file
BIN
.venv311/Scripts/pyrsa-priv2pub.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyrsa-sign.exe
Normal file
BIN
.venv311/Scripts/pyrsa-sign.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pyrsa-verify.exe
Normal file
BIN
.venv311/Scripts/pyrsa-verify.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/python.exe
Normal file
BIN
.venv311/Scripts/python.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pythonw.exe
Normal file
BIN
.venv311/Scripts/pythonw.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/pywin32_postinstall.exe
Normal file
BIN
.venv311/Scripts/pywin32_postinstall.exe
Normal file
Binary file not shown.
733
.venv311/Scripts/pywin32_postinstall.py
Normal file
733
.venv311/Scripts/pywin32_postinstall.py
Normal file
@@ -0,0 +1,733 @@
|
|||||||
|
# postinstall script for pywin32
|
||||||
|
#
|
||||||
|
# copies pywintypesXX.dll and pythoncomXX.dll into the system directory,
|
||||||
|
# and creates a pth file
|
||||||
|
import argparse
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import sysconfig
|
||||||
|
import tempfile
|
||||||
|
import winreg
|
||||||
|
|
||||||
|
tee_f = open(
|
||||||
|
os.path.join(
|
||||||
|
tempfile.gettempdir(), # Send output somewhere so it can be found if necessary...
|
||||||
|
"pywin32_postinstall.log",
|
||||||
|
),
|
||||||
|
"w",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Tee:
|
||||||
|
def __init__(self, file):
|
||||||
|
self.f = file
|
||||||
|
|
||||||
|
def write(self, what):
|
||||||
|
if self.f is not None:
|
||||||
|
try:
|
||||||
|
self.f.write(what.replace("\n", "\r\n"))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
tee_f.write(what)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
if self.f is not None:
|
||||||
|
try:
|
||||||
|
self.f.flush()
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
tee_f.flush()
|
||||||
|
|
||||||
|
|
||||||
|
sys.stderr = Tee(sys.stderr)
|
||||||
|
sys.stdout = Tee(sys.stdout)
|
||||||
|
|
||||||
|
com_modules = [
|
||||||
|
# module_name, class_names
|
||||||
|
("win32com.servers.interp", "Interpreter"),
|
||||||
|
("win32com.servers.dictionary", "DictionaryPolicy"),
|
||||||
|
("win32com.axscript.client.pyscript", "PyScript"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Is this a 'silent' install - ie, avoid all dialogs.
|
||||||
|
# Different than 'verbose'
|
||||||
|
silent = 0
|
||||||
|
|
||||||
|
# Verbosity of output messages.
|
||||||
|
verbose = 1
|
||||||
|
|
||||||
|
root_key_name = "Software\\Python\\PythonCore\\" + sys.winver
|
||||||
|
|
||||||
|
|
||||||
|
def get_root_hkey():
|
||||||
|
try:
|
||||||
|
winreg.OpenKey(
|
||||||
|
winreg.HKEY_LOCAL_MACHINE, root_key_name, 0, winreg.KEY_CREATE_SUB_KEY
|
||||||
|
)
|
||||||
|
return winreg.HKEY_LOCAL_MACHINE
|
||||||
|
except OSError:
|
||||||
|
# Either not exist, or no permissions to create subkey means
|
||||||
|
# must be HKCU
|
||||||
|
return winreg.HKEY_CURRENT_USER
|
||||||
|
|
||||||
|
|
||||||
|
# Create a function with the same signature as create_shortcut
|
||||||
|
# previously provided by bdist_wininst
|
||||||
|
def create_shortcut(
|
||||||
|
path, description, filename, arguments="", workdir="", iconpath="", iconindex=0
|
||||||
|
):
|
||||||
|
import pythoncom
|
||||||
|
from win32com.shell import shell
|
||||||
|
|
||||||
|
ilink = pythoncom.CoCreateInstance(
|
||||||
|
shell.CLSID_ShellLink,
|
||||||
|
None,
|
||||||
|
pythoncom.CLSCTX_INPROC_SERVER,
|
||||||
|
shell.IID_IShellLink,
|
||||||
|
)
|
||||||
|
ilink.SetPath(path)
|
||||||
|
ilink.SetDescription(description)
|
||||||
|
if arguments:
|
||||||
|
ilink.SetArguments(arguments)
|
||||||
|
if workdir:
|
||||||
|
ilink.SetWorkingDirectory(workdir)
|
||||||
|
if iconpath or iconindex:
|
||||||
|
ilink.SetIconLocation(iconpath, iconindex)
|
||||||
|
# now save it.
|
||||||
|
ipf = ilink.QueryInterface(pythoncom.IID_IPersistFile)
|
||||||
|
ipf.Save(filename, 0)
|
||||||
|
|
||||||
|
|
||||||
|
# Support the same list of "path names" as bdist_wininst used to
|
||||||
|
def get_special_folder_path(path_name):
|
||||||
|
from win32com.shell import shell, shellcon
|
||||||
|
|
||||||
|
for maybe in """
|
||||||
|
CSIDL_COMMON_STARTMENU CSIDL_STARTMENU CSIDL_COMMON_APPDATA
|
||||||
|
CSIDL_LOCAL_APPDATA CSIDL_APPDATA CSIDL_COMMON_DESKTOPDIRECTORY
|
||||||
|
CSIDL_DESKTOPDIRECTORY CSIDL_COMMON_STARTUP CSIDL_STARTUP
|
||||||
|
CSIDL_COMMON_PROGRAMS CSIDL_PROGRAMS CSIDL_PROGRAM_FILES_COMMON
|
||||||
|
CSIDL_PROGRAM_FILES CSIDL_FONTS""".split():
|
||||||
|
if maybe == path_name:
|
||||||
|
csidl = getattr(shellcon, maybe)
|
||||||
|
return shell.SHGetSpecialFolderPath(0, csidl, False)
|
||||||
|
raise ValueError(f"{path_name} is an unknown path ID")
|
||||||
|
|
||||||
|
|
||||||
|
def CopyTo(desc, src, dest):
|
||||||
|
import win32api
|
||||||
|
import win32con
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
try:
|
||||||
|
win32api.CopyFile(src, dest, 0)
|
||||||
|
return
|
||||||
|
except win32api.error as details:
|
||||||
|
if details.winerror == 5: # access denied - user not admin.
|
||||||
|
raise
|
||||||
|
if silent:
|
||||||
|
# Running silent mode - just re-raise the error.
|
||||||
|
raise
|
||||||
|
full_desc = (
|
||||||
|
f"Error {desc}\n\n"
|
||||||
|
"If you have any Python applications running, "
|
||||||
|
f"please close them now\nand select 'Retry'\n\n{details.strerror}"
|
||||||
|
)
|
||||||
|
rc = win32api.MessageBox(
|
||||||
|
0, full_desc, "Installation Error", win32con.MB_ABORTRETRYIGNORE
|
||||||
|
)
|
||||||
|
if rc == win32con.IDABORT:
|
||||||
|
raise
|
||||||
|
elif rc == win32con.IDIGNORE:
|
||||||
|
return
|
||||||
|
# else retry - around we go again.
|
||||||
|
|
||||||
|
|
||||||
|
# We need to import win32api to determine the Windows system directory,
|
||||||
|
# so we can copy our system files there - but importing win32api will
|
||||||
|
# load the pywintypes.dll already in the system directory preventing us
|
||||||
|
# from updating them!
|
||||||
|
# So, we pull the same trick pywintypes.py does, but it loads from
|
||||||
|
# our pywintypes_system32 directory.
|
||||||
|
def LoadSystemModule(lib_dir, modname):
|
||||||
|
# See if this is a debug build.
|
||||||
|
import importlib.machinery
|
||||||
|
import importlib.util
|
||||||
|
|
||||||
|
suffix = "_d" if "_d.pyd" in importlib.machinery.EXTENSION_SUFFIXES else ""
|
||||||
|
filename = "%s%d%d%s.dll" % (
|
||||||
|
modname,
|
||||||
|
sys.version_info.major,
|
||||||
|
sys.version_info.minor,
|
||||||
|
suffix,
|
||||||
|
)
|
||||||
|
filename = os.path.join(lib_dir, "pywin32_system32", filename)
|
||||||
|
loader = importlib.machinery.ExtensionFileLoader(modname, filename)
|
||||||
|
spec = importlib.machinery.ModuleSpec(name=modname, loader=loader, origin=filename)
|
||||||
|
mod = importlib.util.module_from_spec(spec)
|
||||||
|
loader.exec_module(mod)
|
||||||
|
|
||||||
|
|
||||||
|
def SetPyKeyVal(key_name, value_name, value):
|
||||||
|
root_hkey = get_root_hkey()
|
||||||
|
root_key = winreg.OpenKey(root_hkey, root_key_name)
|
||||||
|
try:
|
||||||
|
my_key = winreg.CreateKey(root_key, key_name)
|
||||||
|
try:
|
||||||
|
winreg.SetValueEx(my_key, value_name, 0, winreg.REG_SZ, value)
|
||||||
|
if verbose:
|
||||||
|
print(f"-> {root_key_name}\\{key_name}[{value_name}]={value!r}")
|
||||||
|
finally:
|
||||||
|
my_key.Close()
|
||||||
|
finally:
|
||||||
|
root_key.Close()
|
||||||
|
|
||||||
|
|
||||||
|
def UnsetPyKeyVal(key_name, value_name, delete_key=False):
|
||||||
|
root_hkey = get_root_hkey()
|
||||||
|
root_key = winreg.OpenKey(root_hkey, root_key_name)
|
||||||
|
try:
|
||||||
|
my_key = winreg.OpenKey(root_key, key_name, 0, winreg.KEY_SET_VALUE)
|
||||||
|
try:
|
||||||
|
winreg.DeleteValue(my_key, value_name)
|
||||||
|
if verbose:
|
||||||
|
print(f"-> DELETE {root_key_name}\\{key_name}[{value_name}]")
|
||||||
|
finally:
|
||||||
|
my_key.Close()
|
||||||
|
if delete_key:
|
||||||
|
winreg.DeleteKey(root_key, key_name)
|
||||||
|
if verbose:
|
||||||
|
print(f"-> DELETE {root_key_name}\\{key_name}")
|
||||||
|
except OSError as why:
|
||||||
|
winerror = getattr(why, "winerror", why.errno)
|
||||||
|
if winerror != 2: # file not found
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
root_key.Close()
|
||||||
|
|
||||||
|
|
||||||
|
def RegisterCOMObjects(register=True):
|
||||||
|
import win32com.server.register
|
||||||
|
|
||||||
|
if register:
|
||||||
|
func = win32com.server.register.RegisterClasses
|
||||||
|
else:
|
||||||
|
func = win32com.server.register.UnregisterClasses
|
||||||
|
flags = {}
|
||||||
|
if not verbose:
|
||||||
|
flags["quiet"] = 1
|
||||||
|
for module, klass_name in com_modules:
|
||||||
|
__import__(module)
|
||||||
|
mod = sys.modules[module]
|
||||||
|
flags["finalize_register"] = getattr(mod, "DllRegisterServer", None)
|
||||||
|
flags["finalize_unregister"] = getattr(mod, "DllUnregisterServer", None)
|
||||||
|
klass = getattr(mod, klass_name)
|
||||||
|
func(klass, **flags)
|
||||||
|
|
||||||
|
|
||||||
|
def RegisterHelpFile(register=True, lib_dir=None):
|
||||||
|
if lib_dir is None:
|
||||||
|
lib_dir = sysconfig.get_paths()["platlib"]
|
||||||
|
if register:
|
||||||
|
# Register the .chm help file.
|
||||||
|
chm_file = os.path.join(lib_dir, "PyWin32.chm")
|
||||||
|
if os.path.isfile(chm_file):
|
||||||
|
# This isn't recursive, so if 'Help' doesn't exist, we croak
|
||||||
|
SetPyKeyVal("Help", None, None)
|
||||||
|
SetPyKeyVal("Help\\Pythonwin Reference", None, chm_file)
|
||||||
|
return chm_file
|
||||||
|
else:
|
||||||
|
print("NOTE: PyWin32.chm can not be located, so has not been registered")
|
||||||
|
else:
|
||||||
|
UnsetPyKeyVal("Help\\Pythonwin Reference", None, delete_key=True)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def RegisterPythonwin(register=True, lib_dir=None):
|
||||||
|
"""Add (or remove) Pythonwin to context menu for python scripts.
|
||||||
|
??? Should probably also add Edit command for pys files also.
|
||||||
|
Also need to remove these keys on uninstall, but there's no function
|
||||||
|
to add registry entries to uninstall log ???
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
if lib_dir is None:
|
||||||
|
lib_dir = sysconfig.get_paths()["platlib"]
|
||||||
|
classes_root = get_root_hkey()
|
||||||
|
## Installer executable doesn't seem to pass anything to postinstall script indicating if it's a debug build
|
||||||
|
pythonwin_exe = os.path.join(lib_dir, "Pythonwin", "Pythonwin.exe")
|
||||||
|
pythonwin_edit_command = pythonwin_exe + ' -edit "%1"'
|
||||||
|
|
||||||
|
keys_vals = [
|
||||||
|
(
|
||||||
|
"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Pythonwin.exe",
|
||||||
|
"",
|
||||||
|
pythonwin_exe,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Software\\Classes\\Python.File\\shell\\Edit with Pythonwin",
|
||||||
|
"command",
|
||||||
|
pythonwin_edit_command,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Software\\Classes\\Python.NoConFile\\shell\\Edit with Pythonwin",
|
||||||
|
"command",
|
||||||
|
pythonwin_edit_command,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
if register:
|
||||||
|
for key, sub_key, val in keys_vals:
|
||||||
|
## Since winreg only uses the character Api functions, this can fail if Python
|
||||||
|
## is installed to a path containing non-ascii characters
|
||||||
|
hkey = winreg.CreateKey(classes_root, key)
|
||||||
|
if sub_key:
|
||||||
|
hkey = winreg.CreateKey(hkey, sub_key)
|
||||||
|
winreg.SetValueEx(hkey, None, 0, winreg.REG_SZ, val)
|
||||||
|
hkey.Close()
|
||||||
|
else:
|
||||||
|
for key, sub_key, val in keys_vals:
|
||||||
|
try:
|
||||||
|
if sub_key:
|
||||||
|
hkey = winreg.OpenKey(classes_root, key)
|
||||||
|
winreg.DeleteKey(hkey, sub_key)
|
||||||
|
hkey.Close()
|
||||||
|
winreg.DeleteKey(classes_root, key)
|
||||||
|
except OSError as why:
|
||||||
|
winerror = getattr(why, "winerror", why.errno)
|
||||||
|
if winerror != 2: # file not found
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
# tell windows about the change
|
||||||
|
from win32com.shell import shell, shellcon
|
||||||
|
|
||||||
|
shell.SHChangeNotify(
|
||||||
|
shellcon.SHCNE_ASSOCCHANGED, shellcon.SHCNF_IDLIST, None, None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_shortcuts_folder():
|
||||||
|
if get_root_hkey() == winreg.HKEY_LOCAL_MACHINE:
|
||||||
|
try:
|
||||||
|
fldr = get_special_folder_path("CSIDL_COMMON_PROGRAMS")
|
||||||
|
except OSError:
|
||||||
|
# No CSIDL_COMMON_PROGRAMS on this platform
|
||||||
|
fldr = get_special_folder_path("CSIDL_PROGRAMS")
|
||||||
|
else:
|
||||||
|
# non-admin install - always goes in this user's start menu.
|
||||||
|
fldr = get_special_folder_path("CSIDL_PROGRAMS")
|
||||||
|
|
||||||
|
try:
|
||||||
|
install_group = winreg.QueryValue(
|
||||||
|
get_root_hkey(), root_key_name + "\\InstallPath\\InstallGroup"
|
||||||
|
)
|
||||||
|
except OSError:
|
||||||
|
install_group = "Python %d.%d" % (
|
||||||
|
sys.version_info.major,
|
||||||
|
sys.version_info.minor,
|
||||||
|
)
|
||||||
|
return os.path.join(fldr, install_group)
|
||||||
|
|
||||||
|
|
||||||
|
# Get the system directory, which may be the Wow64 directory if we are a 32bit
|
||||||
|
# python on a 64bit OS.
|
||||||
|
def get_system_dir():
|
||||||
|
import win32api # we assume this exists.
|
||||||
|
|
||||||
|
try:
|
||||||
|
import pythoncom
|
||||||
|
import win32process
|
||||||
|
from win32com.shell import shell, shellcon
|
||||||
|
|
||||||
|
try:
|
||||||
|
if win32process.IsWow64Process():
|
||||||
|
return shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_SYSTEMX86)
|
||||||
|
return shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_SYSTEM)
|
||||||
|
except (pythoncom.com_error, win32process.error):
|
||||||
|
return win32api.GetSystemDirectory()
|
||||||
|
except ImportError:
|
||||||
|
return win32api.GetSystemDirectory()
|
||||||
|
|
||||||
|
|
||||||
|
def fixup_dbi():
|
||||||
|
# We used to have a dbi.pyd with our .pyd files, but now have a .py file.
|
||||||
|
# If the user didn't uninstall, they will find the .pyd which will cause
|
||||||
|
# problems - so handle that.
|
||||||
|
import win32api
|
||||||
|
import win32con
|
||||||
|
|
||||||
|
pyd_name = os.path.join(os.path.dirname(win32api.__file__), "dbi.pyd")
|
||||||
|
pyd_d_name = os.path.join(os.path.dirname(win32api.__file__), "dbi_d.pyd")
|
||||||
|
py_name = os.path.join(os.path.dirname(win32con.__file__), "dbi.py")
|
||||||
|
for this_pyd in (pyd_name, pyd_d_name):
|
||||||
|
this_dest = this_pyd + ".old"
|
||||||
|
if os.path.isfile(this_pyd) and os.path.isfile(py_name):
|
||||||
|
try:
|
||||||
|
if os.path.isfile(this_dest):
|
||||||
|
print(
|
||||||
|
f"Old dbi '{this_dest}' already exists - deleting '{this_pyd}'"
|
||||||
|
)
|
||||||
|
os.remove(this_pyd)
|
||||||
|
else:
|
||||||
|
os.rename(this_pyd, this_dest)
|
||||||
|
print(f"renamed '{this_pyd}'->'{this_pyd}.old'")
|
||||||
|
except OSError as exc:
|
||||||
|
print(f"FAILED to rename '{this_pyd}': {exc}")
|
||||||
|
|
||||||
|
|
||||||
|
def install(lib_dir):
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
# The .pth file is now installed as a regular file.
|
||||||
|
# Create the .pth file in the site-packages dir, and use only relative paths
|
||||||
|
# We used to write a .pth directly to sys.prefix - clobber it.
|
||||||
|
if os.path.isfile(os.path.join(sys.prefix, "pywin32.pth")):
|
||||||
|
os.unlink(os.path.join(sys.prefix, "pywin32.pth"))
|
||||||
|
# The .pth may be new and therefore not loaded in this session.
|
||||||
|
# Setup the paths just in case.
|
||||||
|
for name in "win32 win32\\lib Pythonwin".split():
|
||||||
|
sys.path.append(os.path.join(lib_dir, name))
|
||||||
|
# It is possible people with old versions installed with still have
|
||||||
|
# pywintypes and pythoncom registered. We no longer need this, and stale
|
||||||
|
# entries hurt us.
|
||||||
|
for name in "pythoncom pywintypes".split():
|
||||||
|
keyname = "Software\\Python\\PythonCore\\" + sys.winver + "\\Modules\\" + name
|
||||||
|
for root in winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER:
|
||||||
|
try:
|
||||||
|
winreg.DeleteKey(root, keyname + "\\Debug")
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
winreg.DeleteKey(root, keyname)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
LoadSystemModule(lib_dir, "pywintypes")
|
||||||
|
LoadSystemModule(lib_dir, "pythoncom")
|
||||||
|
import win32api
|
||||||
|
|
||||||
|
# and now we can get the system directory:
|
||||||
|
files = glob.glob(os.path.join(lib_dir, "pywin32_system32\\*.*"))
|
||||||
|
if not files:
|
||||||
|
raise RuntimeError("No system files to copy!!")
|
||||||
|
# Try the system32 directory first - if that fails due to "access denied",
|
||||||
|
# it implies a non-admin user, and we use sys.prefix
|
||||||
|
for dest_dir in [get_system_dir(), sys.prefix]:
|
||||||
|
# and copy some files over there
|
||||||
|
worked = 0
|
||||||
|
try:
|
||||||
|
for fname in files:
|
||||||
|
base = os.path.basename(fname)
|
||||||
|
dst = os.path.join(dest_dir, base)
|
||||||
|
CopyTo("installing %s" % base, fname, dst)
|
||||||
|
if verbose:
|
||||||
|
print(f"Copied {base} to {dst}")
|
||||||
|
worked = 1
|
||||||
|
# Nuke any other versions that may exist - having
|
||||||
|
# duplicates causes major headaches.
|
||||||
|
bad_dest_dirs = [
|
||||||
|
os.path.join(sys.prefix, "Library\\bin"),
|
||||||
|
os.path.join(sys.prefix, "Lib\\site-packages\\win32"),
|
||||||
|
]
|
||||||
|
if dest_dir != sys.prefix:
|
||||||
|
bad_dest_dirs.append(sys.prefix)
|
||||||
|
for bad_dest_dir in bad_dest_dirs:
|
||||||
|
bad_fname = os.path.join(bad_dest_dir, base)
|
||||||
|
if os.path.exists(bad_fname):
|
||||||
|
# let exceptions go here - delete must succeed
|
||||||
|
os.unlink(bad_fname)
|
||||||
|
if worked:
|
||||||
|
break
|
||||||
|
except win32api.error as details:
|
||||||
|
if details.winerror == 5:
|
||||||
|
# access denied - user not admin - try sys.prefix dir,
|
||||||
|
# but first check that a version doesn't already exist
|
||||||
|
# in that place - otherwise that one will still get used!
|
||||||
|
if os.path.exists(dst):
|
||||||
|
msg = (
|
||||||
|
"The file '%s' exists, but can not be replaced "
|
||||||
|
"due to insufficient permissions. You must "
|
||||||
|
"reinstall this software as an Administrator" % dst
|
||||||
|
)
|
||||||
|
print(msg)
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
continue
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
"You don't have enough permissions to install the system files"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Register our demo COM objects.
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
RegisterCOMObjects()
|
||||||
|
except win32api.error as details:
|
||||||
|
if details.winerror != 5: # ERROR_ACCESS_DENIED
|
||||||
|
raise
|
||||||
|
print("You do not have the permissions to install COM objects.")
|
||||||
|
print("The sample COM objects were not registered.")
|
||||||
|
except Exception:
|
||||||
|
print("FAILED to register the Python COM objects")
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# There may be no main Python key in HKCU if, eg, an admin installed
|
||||||
|
# python itself.
|
||||||
|
winreg.CreateKey(get_root_hkey(), root_key_name)
|
||||||
|
|
||||||
|
chm_file = None
|
||||||
|
try:
|
||||||
|
chm_file = RegisterHelpFile(True, lib_dir)
|
||||||
|
except Exception:
|
||||||
|
print("Failed to register help file")
|
||||||
|
traceback.print_exc()
|
||||||
|
else:
|
||||||
|
if verbose:
|
||||||
|
print("Registered help file")
|
||||||
|
|
||||||
|
# misc other fixups.
|
||||||
|
fixup_dbi()
|
||||||
|
|
||||||
|
# Register Pythonwin in context menu
|
||||||
|
try:
|
||||||
|
RegisterPythonwin(True, lib_dir)
|
||||||
|
except Exception:
|
||||||
|
print("Failed to register pythonwin as editor")
|
||||||
|
traceback.print_exc()
|
||||||
|
else:
|
||||||
|
if verbose:
|
||||||
|
print("Pythonwin has been registered in context menu")
|
||||||
|
|
||||||
|
# Create the win32com\gen_py directory.
|
||||||
|
make_dir = os.path.join(lib_dir, "win32com", "gen_py")
|
||||||
|
if not os.path.isdir(make_dir):
|
||||||
|
if verbose:
|
||||||
|
print(f"Creating directory {make_dir}")
|
||||||
|
os.mkdir(make_dir)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# create shortcuts
|
||||||
|
# CSIDL_COMMON_PROGRAMS only available works on NT/2000/XP, and
|
||||||
|
# will fail there if the user has no admin rights.
|
||||||
|
fldr = get_shortcuts_folder()
|
||||||
|
# If the group doesn't exist, then we don't make shortcuts - its
|
||||||
|
# possible that this isn't a "normal" install.
|
||||||
|
if os.path.isdir(fldr):
|
||||||
|
dst = os.path.join(fldr, "PythonWin.lnk")
|
||||||
|
create_shortcut(
|
||||||
|
os.path.join(lib_dir, "Pythonwin\\Pythonwin.exe"),
|
||||||
|
"The Pythonwin IDE",
|
||||||
|
dst,
|
||||||
|
"",
|
||||||
|
sys.prefix,
|
||||||
|
)
|
||||||
|
if verbose:
|
||||||
|
print("Shortcut for Pythonwin created")
|
||||||
|
# And the docs.
|
||||||
|
if chm_file:
|
||||||
|
dst = os.path.join(fldr, "Python for Windows Documentation.lnk")
|
||||||
|
doc = "Documentation for the PyWin32 extensions"
|
||||||
|
create_shortcut(chm_file, doc, dst)
|
||||||
|
if verbose:
|
||||||
|
print("Shortcut to documentation created")
|
||||||
|
else:
|
||||||
|
if verbose:
|
||||||
|
print(f"Can't install shortcuts - {fldr!r} is not a folder")
|
||||||
|
except Exception as details:
|
||||||
|
print(details)
|
||||||
|
|
||||||
|
# importing win32com.client ensures the gen_py dir created - not strictly
|
||||||
|
# necessary to do now, but this makes the installation "complete"
|
||||||
|
try:
|
||||||
|
import win32com.client # noqa
|
||||||
|
except ImportError:
|
||||||
|
# Don't let this error sound fatal
|
||||||
|
pass
|
||||||
|
print("The pywin32 extensions were successfully installed.")
|
||||||
|
|
||||||
|
|
||||||
|
def uninstall(lib_dir):
|
||||||
|
# First ensure our system modules are loaded from pywin32_system, so
|
||||||
|
# we can remove the ones we copied...
|
||||||
|
LoadSystemModule(lib_dir, "pywintypes")
|
||||||
|
LoadSystemModule(lib_dir, "pythoncom")
|
||||||
|
|
||||||
|
try:
|
||||||
|
RegisterCOMObjects(False)
|
||||||
|
except Exception as why:
|
||||||
|
print(f"Failed to unregister COM objects: {why}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
RegisterHelpFile(False, lib_dir)
|
||||||
|
except Exception as why:
|
||||||
|
print(f"Failed to unregister help file: {why}")
|
||||||
|
else:
|
||||||
|
if verbose:
|
||||||
|
print("Unregistered help file")
|
||||||
|
|
||||||
|
try:
|
||||||
|
RegisterPythonwin(False, lib_dir)
|
||||||
|
except Exception as why:
|
||||||
|
print(f"Failed to unregister Pythonwin: {why}")
|
||||||
|
else:
|
||||||
|
if verbose:
|
||||||
|
print("Unregistered Pythonwin")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# remove gen_py directory.
|
||||||
|
gen_dir = os.path.join(lib_dir, "win32com", "gen_py")
|
||||||
|
if os.path.isdir(gen_dir):
|
||||||
|
shutil.rmtree(gen_dir)
|
||||||
|
if verbose:
|
||||||
|
print(f"Removed directory {gen_dir}")
|
||||||
|
|
||||||
|
# Remove pythonwin compiled "config" files.
|
||||||
|
pywin_dir = os.path.join(lib_dir, "Pythonwin", "pywin")
|
||||||
|
for fname in glob.glob(os.path.join(pywin_dir, "*.cfc")):
|
||||||
|
os.remove(fname)
|
||||||
|
|
||||||
|
# The dbi.pyd.old files we may have created.
|
||||||
|
try:
|
||||||
|
os.remove(os.path.join(lib_dir, "win32", "dbi.pyd.old"))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
os.remove(os.path.join(lib_dir, "win32", "dbi_d.pyd.old"))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
except Exception as why:
|
||||||
|
print(f"Failed to remove misc files: {why}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
fldr = get_shortcuts_folder()
|
||||||
|
for link in ("PythonWin.lnk", "Python for Windows Documentation.lnk"):
|
||||||
|
fqlink = os.path.join(fldr, link)
|
||||||
|
if os.path.isfile(fqlink):
|
||||||
|
os.remove(fqlink)
|
||||||
|
if verbose:
|
||||||
|
print(f"Removed {link}")
|
||||||
|
except Exception as why:
|
||||||
|
print(f"Failed to remove shortcuts: {why}")
|
||||||
|
# Now remove the system32 files.
|
||||||
|
files = glob.glob(os.path.join(lib_dir, "pywin32_system32\\*.*"))
|
||||||
|
# Try the system32 directory first - if that fails due to "access denied",
|
||||||
|
# it implies a non-admin user, and we use sys.prefix
|
||||||
|
try:
|
||||||
|
for dest_dir in [get_system_dir(), sys.prefix]:
|
||||||
|
# and copy some files over there
|
||||||
|
worked = 0
|
||||||
|
for fname in files:
|
||||||
|
base = os.path.basename(fname)
|
||||||
|
dst = os.path.join(dest_dir, base)
|
||||||
|
if os.path.isfile(dst):
|
||||||
|
try:
|
||||||
|
os.remove(dst)
|
||||||
|
worked = 1
|
||||||
|
if verbose:
|
||||||
|
print("Removed file %s" % (dst))
|
||||||
|
except Exception:
|
||||||
|
print(f"FAILED to remove {dst}")
|
||||||
|
if worked:
|
||||||
|
break
|
||||||
|
except Exception as why:
|
||||||
|
print(f"FAILED to remove system files: {why}")
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: This used to be run from inside the bdist_wininst created binary un/installer.
|
||||||
|
# From inside the binary installer this script HAD to NOT
|
||||||
|
# call sys.exit() or raise SystemExit, otherwise the installer would also terminate!
|
||||||
|
# Out of principle, we're still not using system exits.
|
||||||
|
|
||||||
|
|
||||||
|
def verify_destination(location: str) -> str:
|
||||||
|
location = os.path.abspath(location)
|
||||||
|
if not os.path.isdir(location):
|
||||||
|
raise argparse.ArgumentTypeError(
|
||||||
|
f'Path "{location}" is not an existing directory!'
|
||||||
|
)
|
||||||
|
return location
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description="""A post-install script for the pywin32 extensions.
|
||||||
|
|
||||||
|
* Typical usage:
|
||||||
|
|
||||||
|
> python -m pywin32_postinstall -install
|
||||||
|
|
||||||
|
* or (shorter but you don't have control over which python environment is used)
|
||||||
|
|
||||||
|
> pywin32_postinstall -install
|
||||||
|
|
||||||
|
You need to execute this script, with a '-install' parameter,
|
||||||
|
to ensure the environment is setup correctly to install COM objects, services, etc.
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-install",
|
||||||
|
default=False,
|
||||||
|
action="store_true",
|
||||||
|
help="Configure the Python environment correctly for pywin32.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-remove",
|
||||||
|
default=False,
|
||||||
|
action="store_true",
|
||||||
|
help="Try and remove everything that was installed or copied.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-wait",
|
||||||
|
type=int,
|
||||||
|
help="Wait for the specified process to terminate before starting.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-silent",
|
||||||
|
default=False,
|
||||||
|
action="store_true",
|
||||||
|
help='Don\'t display the "Abort/Retry/Ignore" dialog for files in use.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-quiet",
|
||||||
|
default=False,
|
||||||
|
action="store_true",
|
||||||
|
help="Don't display progress messages.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-destination",
|
||||||
|
default=sysconfig.get_paths()["platlib"],
|
||||||
|
type=verify_destination,
|
||||||
|
help="Location of the PyWin32 installation",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if not args.quiet:
|
||||||
|
print(f"Parsed arguments are: {args}")
|
||||||
|
|
||||||
|
if not args.install ^ args.remove:
|
||||||
|
parser.error("You need to either choose to -install or -remove!")
|
||||||
|
|
||||||
|
if args.wait is not None:
|
||||||
|
try:
|
||||||
|
os.waitpid(args.wait, 0)
|
||||||
|
except OSError:
|
||||||
|
# child already dead
|
||||||
|
pass
|
||||||
|
|
||||||
|
silent = args.silent
|
||||||
|
verbose = not args.quiet
|
||||||
|
|
||||||
|
if args.install:
|
||||||
|
install(args.destination)
|
||||||
|
|
||||||
|
if args.remove:
|
||||||
|
uninstall(args.destination)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
BIN
.venv311/Scripts/pywin32_testall.exe
Normal file
BIN
.venv311/Scripts/pywin32_testall.exe
Normal file
Binary file not shown.
120
.venv311/Scripts/pywin32_testall.py
Normal file
120
.venv311/Scripts/pywin32_testall.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
"""A test runner for pywin32"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import site
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# locate the dirs based on where this script is - it may be either in the
|
||||||
|
# source tree, or in an installed Python 'Scripts' tree.
|
||||||
|
project_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||||
|
site_packages = [site.getusersitepackages()] + site.getsitepackages()
|
||||||
|
|
||||||
|
failures = []
|
||||||
|
|
||||||
|
|
||||||
|
# Run a test using subprocess and wait for the result.
|
||||||
|
# If we get an returncode != 0, we know that there was an error, but we don't
|
||||||
|
# abort immediately - we run as many tests as we can.
|
||||||
|
def run_test(script, cmdline_extras):
|
||||||
|
dirname, scriptname = os.path.split(script)
|
||||||
|
# some tests prefer to be run from their directory.
|
||||||
|
cmd = [sys.executable, "-u", scriptname] + cmdline_extras
|
||||||
|
print("--- Running '%s' ---" % script)
|
||||||
|
sys.stdout.flush()
|
||||||
|
result = subprocess.run(cmd, check=False, cwd=dirname)
|
||||||
|
print(f"*** Test script '{script}' exited with {result.returncode}")
|
||||||
|
sys.stdout.flush()
|
||||||
|
if result.returncode:
|
||||||
|
failures.append(script)
|
||||||
|
|
||||||
|
|
||||||
|
def find_and_run(possible_locations, extras):
|
||||||
|
for maybe in possible_locations:
|
||||||
|
if os.path.isfile(maybe):
|
||||||
|
run_test(maybe, extras)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
"Failed to locate a test script in one of %s" % possible_locations
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
code_directories = [project_root] + site_packages
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="A script to trigger tests in all subprojects of PyWin32."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-no-user-interaction",
|
||||||
|
default=False,
|
||||||
|
action="store_true",
|
||||||
|
help="(This is now the default - use `-user-interaction` to include them)",
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-user-interaction",
|
||||||
|
action="store_true",
|
||||||
|
help="Include tests which require user interaction",
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-skip-adodbapi",
|
||||||
|
default=False,
|
||||||
|
action="store_true",
|
||||||
|
help="Skip the adodbapi tests; useful for CI where there's no provider",
|
||||||
|
)
|
||||||
|
|
||||||
|
args, remains = parser.parse_known_args()
|
||||||
|
|
||||||
|
# win32, win32ui / Pythonwin
|
||||||
|
|
||||||
|
extras = []
|
||||||
|
if args.user_interaction:
|
||||||
|
extras.append("-user-interaction")
|
||||||
|
extras.extend(remains)
|
||||||
|
scripts = [
|
||||||
|
"win32/test/testall.py",
|
||||||
|
"Pythonwin/pywin/test/all.py",
|
||||||
|
]
|
||||||
|
for script in scripts:
|
||||||
|
maybes = [os.path.join(directory, script) for directory in code_directories]
|
||||||
|
find_and_run(maybes, extras)
|
||||||
|
|
||||||
|
# win32com
|
||||||
|
maybes = [
|
||||||
|
os.path.join(directory, "win32com", "test", "testall.py")
|
||||||
|
for directory in [os.path.join(project_root, "com")] + site_packages
|
||||||
|
]
|
||||||
|
extras = remains + ["1"] # only run "level 1" tests in CI
|
||||||
|
find_and_run(maybes, extras)
|
||||||
|
|
||||||
|
# adodbapi
|
||||||
|
if not args.skip_adodbapi:
|
||||||
|
maybes = [
|
||||||
|
os.path.join(directory, "adodbapi", "test", "adodbapitest.py")
|
||||||
|
for directory in code_directories
|
||||||
|
]
|
||||||
|
find_and_run(maybes, remains)
|
||||||
|
# This script has a hard-coded sql server name in it, (and markh typically
|
||||||
|
# doesn't have a different server to test on) but there is now supposed to be a server out there on the Internet
|
||||||
|
# just to run these tests, so try it...
|
||||||
|
maybes = [
|
||||||
|
os.path.join(directory, "adodbapi", "test", "test_adodbapi_dbapi20.py")
|
||||||
|
for directory in code_directories
|
||||||
|
]
|
||||||
|
find_and_run(maybes, remains)
|
||||||
|
|
||||||
|
if failures:
|
||||||
|
print("The following scripts failed")
|
||||||
|
for failure in failures:
|
||||||
|
print(">", failure)
|
||||||
|
sys.exit(1)
|
||||||
|
print("All tests passed \\o/")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
BIN
.venv311/Scripts/ruff.exe
Normal file
BIN
.venv311/Scripts/ruff.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/strawberry.exe
Normal file
BIN
.venv311/Scripts/strawberry.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/tiny-agents.exe
Normal file
BIN
.venv311/Scripts/tiny-agents.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/tqdm.exe
Normal file
BIN
.venv311/Scripts/tqdm.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/ttx.exe
Normal file
BIN
.venv311/Scripts/ttx.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/typer.exe
Normal file
BIN
.venv311/Scripts/typer.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/uvicorn.exe
Normal file
BIN
.venv311/Scripts/uvicorn.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/watchfiles.exe
Normal file
BIN
.venv311/Scripts/watchfiles.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/websockets.exe
Normal file
BIN
.venv311/Scripts/websockets.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/wheel.exe
Normal file
BIN
.venv311/Scripts/wheel.exe
Normal file
Binary file not shown.
BIN
.venv311/Scripts/wsdump.exe
Normal file
BIN
.venv311/Scripts/wsdump.exe
Normal file
Binary file not shown.
5
.venv311/pyvenv.cfg
Normal file
5
.venv311/pyvenv.cfg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
home = C:\Users\Administrator\AppData\Local\Programs\Python\Python311
|
||||||
|
include-system-site-packages = false
|
||||||
|
version = 3.11.9
|
||||||
|
executable = C:\Users\Administrator\AppData\Local\Programs\Python\Python311\python.exe
|
||||||
|
command = C:\Users\Administrator\AppData\Local\Programs\Python\Python311\python.exe -m venv D:\code\MoFox_Bot\.venv311
|
||||||
188
.venv311/share/man/man1/isympy.1
Normal file
188
.venv311/share/man/man1/isympy.1
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
'\" -*- coding: us-ascii -*-
|
||||||
|
.if \n(.g .ds T< \\FC
|
||||||
|
.if \n(.g .ds T> \\F[\n[.fam]]
|
||||||
|
.de URL
|
||||||
|
\\$2 \(la\\$1\(ra\\$3
|
||||||
|
..
|
||||||
|
.if \n(.g .mso www.tmac
|
||||||
|
.TH isympy 1 2007-10-8 "" ""
|
||||||
|
.SH NAME
|
||||||
|
isympy \- interactive shell for SymPy
|
||||||
|
.SH SYNOPSIS
|
||||||
|
'nh
|
||||||
|
.fi
|
||||||
|
.ad l
|
||||||
|
\fBisympy\fR \kx
|
||||||
|
.if (\nx>(\n(.l/2)) .nr x (\n(.l/5)
|
||||||
|
'in \n(.iu+\nxu
|
||||||
|
[\fB-c\fR | \fB--console\fR] [\fB-p\fR ENCODING | \fB--pretty\fR ENCODING] [\fB-t\fR TYPE | \fB--types\fR TYPE] [\fB-o\fR ORDER | \fB--order\fR ORDER] [\fB-q\fR | \fB--quiet\fR] [\fB-d\fR | \fB--doctest\fR] [\fB-C\fR | \fB--no-cache\fR] [\fB-a\fR | \fB--auto\fR] [\fB-D\fR | \fB--debug\fR] [
|
||||||
|
-- | PYTHONOPTIONS]
|
||||||
|
'in \n(.iu-\nxu
|
||||||
|
.ad b
|
||||||
|
'hy
|
||||||
|
'nh
|
||||||
|
.fi
|
||||||
|
.ad l
|
||||||
|
\fBisympy\fR \kx
|
||||||
|
.if (\nx>(\n(.l/2)) .nr x (\n(.l/5)
|
||||||
|
'in \n(.iu+\nxu
|
||||||
|
[
|
||||||
|
{\fB-h\fR | \fB--help\fR}
|
||||||
|
|
|
||||||
|
{\fB-v\fR | \fB--version\fR}
|
||||||
|
]
|
||||||
|
'in \n(.iu-\nxu
|
||||||
|
.ad b
|
||||||
|
'hy
|
||||||
|
.SH DESCRIPTION
|
||||||
|
isympy is a Python shell for SymPy. It is just a normal python shell
|
||||||
|
(ipython shell if you have the ipython package installed) that executes
|
||||||
|
the following commands so that you don't have to:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
\*(T<
|
||||||
|
>>> from __future__ import division
|
||||||
|
>>> from sympy import *
|
||||||
|
>>> x, y, z = symbols("x,y,z")
|
||||||
|
>>> k, m, n = symbols("k,m,n", integer=True)
|
||||||
|
\*(T>
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
So starting isympy is equivalent to starting python (or ipython) and
|
||||||
|
executing the above commands by hand. It is intended for easy and quick
|
||||||
|
experimentation with SymPy. For more complicated programs, it is recommended
|
||||||
|
to write a script and import things explicitly (using the "from sympy
|
||||||
|
import sin, log, Symbol, ..." idiom).
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-c \fR\*(T>\fISHELL\fR, \*(T<\fB\-\-console=\fR\*(T>\fISHELL\fR
|
||||||
|
Use the specified shell (python or ipython) as
|
||||||
|
console backend instead of the default one (ipython
|
||||||
|
if present or python otherwise).
|
||||||
|
|
||||||
|
Example: isympy -c python
|
||||||
|
|
||||||
|
\fISHELL\fR could be either
|
||||||
|
\&'ipython' or 'python'
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-p \fR\*(T>\fIENCODING\fR, \*(T<\fB\-\-pretty=\fR\*(T>\fIENCODING\fR
|
||||||
|
Setup pretty printing in SymPy. By default, the most pretty, unicode
|
||||||
|
printing is enabled (if the terminal supports it). You can use less
|
||||||
|
pretty ASCII printing instead or no pretty printing at all.
|
||||||
|
|
||||||
|
Example: isympy -p no
|
||||||
|
|
||||||
|
\fIENCODING\fR must be one of 'unicode',
|
||||||
|
\&'ascii' or 'no'.
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-t \fR\*(T>\fITYPE\fR, \*(T<\fB\-\-types=\fR\*(T>\fITYPE\fR
|
||||||
|
Setup the ground types for the polys. By default, gmpy ground types
|
||||||
|
are used if gmpy2 or gmpy is installed, otherwise it falls back to python
|
||||||
|
ground types, which are a little bit slower. You can manually
|
||||||
|
choose python ground types even if gmpy is installed (e.g., for testing purposes).
|
||||||
|
|
||||||
|
Note that sympy ground types are not supported, and should be used
|
||||||
|
only for experimental purposes.
|
||||||
|
|
||||||
|
Note that the gmpy1 ground type is primarily intended for testing; it the
|
||||||
|
use of gmpy even if gmpy2 is available.
|
||||||
|
|
||||||
|
This is the same as setting the environment variable
|
||||||
|
SYMPY_GROUND_TYPES to the given ground type (e.g.,
|
||||||
|
SYMPY_GROUND_TYPES='gmpy')
|
||||||
|
|
||||||
|
The ground types can be determined interactively from the variable
|
||||||
|
sympy.polys.domains.GROUND_TYPES inside the isympy shell itself.
|
||||||
|
|
||||||
|
Example: isympy -t python
|
||||||
|
|
||||||
|
\fITYPE\fR must be one of 'gmpy',
|
||||||
|
\&'gmpy1' or 'python'.
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-o \fR\*(T>\fIORDER\fR, \*(T<\fB\-\-order=\fR\*(T>\fIORDER\fR
|
||||||
|
Setup the ordering of terms for printing. The default is lex, which
|
||||||
|
orders terms lexicographically (e.g., x**2 + x + 1). You can choose
|
||||||
|
other orderings, such as rev-lex, which will use reverse
|
||||||
|
lexicographic ordering (e.g., 1 + x + x**2).
|
||||||
|
|
||||||
|
Note that for very large expressions, ORDER='none' may speed up
|
||||||
|
printing considerably, with the tradeoff that the order of the terms
|
||||||
|
in the printed expression will have no canonical order
|
||||||
|
|
||||||
|
Example: isympy -o rev-lax
|
||||||
|
|
||||||
|
\fIORDER\fR must be one of 'lex', 'rev-lex', 'grlex',
|
||||||
|
\&'rev-grlex', 'grevlex', 'rev-grevlex', 'old', or 'none'.
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-q\fR\*(T>, \*(T<\fB\-\-quiet\fR\*(T>
|
||||||
|
Print only Python's and SymPy's versions to stdout at startup, and nothing else.
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-d\fR\*(T>, \*(T<\fB\-\-doctest\fR\*(T>
|
||||||
|
Use the same format that should be used for doctests. This is
|
||||||
|
equivalent to '\fIisympy -c python -p no\fR'.
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-C\fR\*(T>, \*(T<\fB\-\-no\-cache\fR\*(T>
|
||||||
|
Disable the caching mechanism. Disabling the cache may slow certain
|
||||||
|
operations down considerably. This is useful for testing the cache,
|
||||||
|
or for benchmarking, as the cache can result in deceptive benchmark timings.
|
||||||
|
|
||||||
|
This is the same as setting the environment variable SYMPY_USE_CACHE
|
||||||
|
to 'no'.
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-a\fR\*(T>, \*(T<\fB\-\-auto\fR\*(T>
|
||||||
|
Automatically create missing symbols. Normally, typing a name of a
|
||||||
|
Symbol that has not been instantiated first would raise NameError,
|
||||||
|
but with this option enabled, any undefined name will be
|
||||||
|
automatically created as a Symbol. This only works in IPython 0.11.
|
||||||
|
|
||||||
|
Note that this is intended only for interactive, calculator style
|
||||||
|
usage. In a script that uses SymPy, Symbols should be instantiated
|
||||||
|
at the top, so that it's clear what they are.
|
||||||
|
|
||||||
|
This will not override any names that are already defined, which
|
||||||
|
includes the single character letters represented by the mnemonic
|
||||||
|
QCOSINE (see the "Gotchas and Pitfalls" document in the
|
||||||
|
documentation). You can delete existing names by executing "del
|
||||||
|
name" in the shell itself. You can see if a name is defined by typing
|
||||||
|
"'name' in globals()".
|
||||||
|
|
||||||
|
The Symbols that are created using this have default assumptions.
|
||||||
|
If you want to place assumptions on symbols, you should create them
|
||||||
|
using symbols() or var().
|
||||||
|
|
||||||
|
Finally, this only works in the top level namespace. So, for
|
||||||
|
example, if you define a function in isympy with an undefined
|
||||||
|
Symbol, it will not work.
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-D\fR\*(T>, \*(T<\fB\-\-debug\fR\*(T>
|
||||||
|
Enable debugging output. This is the same as setting the
|
||||||
|
environment variable SYMPY_DEBUG to 'True'. The debug status is set
|
||||||
|
in the variable SYMPY_DEBUG within isympy.
|
||||||
|
.TP
|
||||||
|
-- \fIPYTHONOPTIONS\fR
|
||||||
|
These options will be passed on to \fIipython (1)\fR shell.
|
||||||
|
Only supported when ipython is being used (standard python shell not supported).
|
||||||
|
|
||||||
|
Two dashes (--) are required to separate \fIPYTHONOPTIONS\fR
|
||||||
|
from the other isympy options.
|
||||||
|
|
||||||
|
For example, to run iSymPy without startup banner and colors:
|
||||||
|
|
||||||
|
isympy -q -c ipython -- --colors=NoColor
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-h\fR\*(T>, \*(T<\fB\-\-help\fR\*(T>
|
||||||
|
Print help output and exit.
|
||||||
|
.TP
|
||||||
|
\*(T<\fB\-v\fR\*(T>, \*(T<\fB\-\-version\fR\*(T>
|
||||||
|
Print isympy version information and exit.
|
||||||
|
.SH FILES
|
||||||
|
.TP
|
||||||
|
\*(T<\fI${HOME}/.sympy\-history\fR\*(T>
|
||||||
|
Saves the history of commands when using the python
|
||||||
|
shell as backend.
|
||||||
|
.SH BUGS
|
||||||
|
The upstreams BTS can be found at \(lahttps://github.com/sympy/sympy/issues\(ra
|
||||||
|
Please report all bugs that you find in there, this will help improve
|
||||||
|
the overall quality of SymPy.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
\fBipython\fR(1), \fBpython\fR(1)
|
||||||
225
.venv311/share/man/man1/ttx.1
Normal file
225
.venv311/share/man/man1/ttx.1
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
.Dd May 18, 2004
|
||||||
|
.\" ttx is not specific to any OS, but contrary to what groff_mdoc(7)
|
||||||
|
.\" seems to imply, entirely omitting the .Os macro causes 'BSD' to
|
||||||
|
.\" be used, so I give a zero-width space as its argument.
|
||||||
|
.Os \&
|
||||||
|
.\" The "FontTools Manual" argument apparently has no effect in
|
||||||
|
.\" groff 1.18.1. I think it is a bug in the -mdoc groff package.
|
||||||
|
.Dt TTX 1 "FontTools Manual"
|
||||||
|
.Sh NAME
|
||||||
|
.Nm ttx
|
||||||
|
.Nd tool for manipulating TrueType and OpenType fonts
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Bk
|
||||||
|
.Op Ar option ...
|
||||||
|
.Ek
|
||||||
|
.Bk
|
||||||
|
.Ar file ...
|
||||||
|
.Ek
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
is a tool for manipulating TrueType and OpenType fonts. It can convert
|
||||||
|
TrueType and OpenType fonts to and from an
|
||||||
|
.Tn XML Ns -based format called
|
||||||
|
.Tn TTX .
|
||||||
|
.Tn TTX
|
||||||
|
files have a
|
||||||
|
.Ql .ttx
|
||||||
|
extension.
|
||||||
|
.Pp
|
||||||
|
For each
|
||||||
|
.Ar file
|
||||||
|
argument it is given,
|
||||||
|
.Nm
|
||||||
|
detects whether it is a
|
||||||
|
.Ql .ttf ,
|
||||||
|
.Ql .otf
|
||||||
|
or
|
||||||
|
.Ql .ttx
|
||||||
|
file and acts accordingly: if it is a
|
||||||
|
.Ql .ttf
|
||||||
|
or
|
||||||
|
.Ql .otf
|
||||||
|
file, it generates a
|
||||||
|
.Ql .ttx
|
||||||
|
file; if it is a
|
||||||
|
.Ql .ttx
|
||||||
|
file, it generates a
|
||||||
|
.Ql .ttf
|
||||||
|
or
|
||||||
|
.Ql .otf
|
||||||
|
file.
|
||||||
|
.Pp
|
||||||
|
By default, every output file is created in the same directory as the
|
||||||
|
corresponding input file and with the same name except for the
|
||||||
|
extension, which is substituted appropriately.
|
||||||
|
.Nm
|
||||||
|
never overwrites existing files; if necessary, it appends a suffix to
|
||||||
|
the output file name before the extension, as in
|
||||||
|
.Pa Arial#1.ttf .
|
||||||
|
.Ss "General options"
|
||||||
|
.Bl -tag -width ".Fl t Ar table"
|
||||||
|
.It Fl h
|
||||||
|
Display usage information.
|
||||||
|
.It Fl d Ar dir
|
||||||
|
Write the output files to directory
|
||||||
|
.Ar dir
|
||||||
|
instead of writing every output file to the same directory as the
|
||||||
|
corresponding input file.
|
||||||
|
.It Fl o Ar file
|
||||||
|
Write the output to
|
||||||
|
.Ar file
|
||||||
|
instead of writing it to the same directory as the
|
||||||
|
corresponding input file.
|
||||||
|
.It Fl v
|
||||||
|
Be verbose. Write more messages to the standard output describing what
|
||||||
|
is being done.
|
||||||
|
.It Fl a
|
||||||
|
Allow virtual glyphs ID's on compile or decompile.
|
||||||
|
.El
|
||||||
|
.Ss "Dump options"
|
||||||
|
The following options control the process of dumping font files
|
||||||
|
(TrueType or OpenType) to
|
||||||
|
.Tn TTX
|
||||||
|
files.
|
||||||
|
.Bl -tag -width ".Fl t Ar table"
|
||||||
|
.It Fl l
|
||||||
|
List table information. Instead of dumping the font to a
|
||||||
|
.Tn TTX
|
||||||
|
file, display minimal information about each table.
|
||||||
|
.It Fl t Ar table
|
||||||
|
Dump table
|
||||||
|
.Ar table .
|
||||||
|
This option may be given multiple times to dump several tables at
|
||||||
|
once. When not specified, all tables are dumped.
|
||||||
|
.It Fl x Ar table
|
||||||
|
Exclude table
|
||||||
|
.Ar table
|
||||||
|
from the list of tables to dump. This option may be given multiple
|
||||||
|
times to exclude several tables from the dump. The
|
||||||
|
.Fl t
|
||||||
|
and
|
||||||
|
.Fl x
|
||||||
|
options are mutually exclusive.
|
||||||
|
.It Fl s
|
||||||
|
Split tables. Dump each table to a separate
|
||||||
|
.Tn TTX
|
||||||
|
file and write (under the name that would have been used for the output
|
||||||
|
file if the
|
||||||
|
.Fl s
|
||||||
|
option had not been given) one small
|
||||||
|
.Tn TTX
|
||||||
|
file containing references to the individual table dump files. This
|
||||||
|
file can be used as input to
|
||||||
|
.Nm
|
||||||
|
as long as the referenced files can be found in the same directory.
|
||||||
|
.It Fl i
|
||||||
|
.\" XXX: I suppose OpenType programs (exist and) are also affected.
|
||||||
|
Don't disassemble TrueType instructions. When this option is specified,
|
||||||
|
all TrueType programs (glyph programs, the font program and the
|
||||||
|
pre-program) are written to the
|
||||||
|
.Tn TTX
|
||||||
|
file as hexadecimal data instead of
|
||||||
|
assembly. This saves some time and results in smaller
|
||||||
|
.Tn TTX
|
||||||
|
files.
|
||||||
|
.It Fl y Ar n
|
||||||
|
When decompiling a TrueType Collection (TTC) file,
|
||||||
|
decompile font number
|
||||||
|
.Ar n ,
|
||||||
|
starting from 0.
|
||||||
|
.El
|
||||||
|
.Ss "Compilation options"
|
||||||
|
The following options control the process of compiling
|
||||||
|
.Tn TTX
|
||||||
|
files into font files (TrueType or OpenType):
|
||||||
|
.Bl -tag -width ".Fl t Ar table"
|
||||||
|
.It Fl m Ar fontfile
|
||||||
|
Merge the input
|
||||||
|
.Tn TTX
|
||||||
|
file
|
||||||
|
.Ar file
|
||||||
|
with
|
||||||
|
.Ar fontfile .
|
||||||
|
No more than one
|
||||||
|
.Ar file
|
||||||
|
argument can be specified when this option is used.
|
||||||
|
.It Fl b
|
||||||
|
Don't recalculate glyph bounding boxes. Use the values in the
|
||||||
|
.Tn TTX
|
||||||
|
file as is.
|
||||||
|
.El
|
||||||
|
.Sh "THE TTX FILE FORMAT"
|
||||||
|
You can find some information about the
|
||||||
|
.Tn TTX
|
||||||
|
file format in
|
||||||
|
.Pa documentation.html .
|
||||||
|
In particular, you will find in that file the list of tables understood by
|
||||||
|
.Nm
|
||||||
|
and the relations between TrueType GlyphIDs and the glyph names used in
|
||||||
|
.Tn TTX
|
||||||
|
files.
|
||||||
|
.Sh EXAMPLES
|
||||||
|
In the following examples, all files are read from and written to the
|
||||||
|
current directory. Additionally, the name given for the output file
|
||||||
|
assumes in every case that it did not exist before
|
||||||
|
.Nm
|
||||||
|
was invoked.
|
||||||
|
.Pp
|
||||||
|
Dump the TrueType font contained in
|
||||||
|
.Pa FreeSans.ttf
|
||||||
|
to
|
||||||
|
.Pa FreeSans.ttx :
|
||||||
|
.Pp
|
||||||
|
.Dl ttx FreeSans.ttf
|
||||||
|
.Pp
|
||||||
|
Compile
|
||||||
|
.Pa MyFont.ttx
|
||||||
|
into a TrueType or OpenType font file:
|
||||||
|
.Pp
|
||||||
|
.Dl ttx MyFont.ttx
|
||||||
|
.Pp
|
||||||
|
List the tables in
|
||||||
|
.Pa FreeSans.ttf
|
||||||
|
along with some information:
|
||||||
|
.Pp
|
||||||
|
.Dl ttx -l FreeSans.ttf
|
||||||
|
.Pp
|
||||||
|
Dump the
|
||||||
|
.Sq cmap
|
||||||
|
table from
|
||||||
|
.Pa FreeSans.ttf
|
||||||
|
to
|
||||||
|
.Pa FreeSans.ttx :
|
||||||
|
.Pp
|
||||||
|
.Dl ttx -t cmap FreeSans.ttf
|
||||||
|
.Sh NOTES
|
||||||
|
On MS\-Windows and MacOS,
|
||||||
|
.Nm
|
||||||
|
is available as a graphical application to which files can be dropped.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Pa documentation.html
|
||||||
|
.Pp
|
||||||
|
.Xr fontforge 1 ,
|
||||||
|
.Xr ftinfo 1 ,
|
||||||
|
.Xr gfontview 1 ,
|
||||||
|
.Xr xmbdfed 1 ,
|
||||||
|
.Xr Font::TTF 3pm
|
||||||
|
.Sh AUTHORS
|
||||||
|
.Nm
|
||||||
|
was written by
|
||||||
|
.An -nosplit
|
||||||
|
.An "Just van Rossum" Aq just@letterror.com .
|
||||||
|
.Pp
|
||||||
|
This manual page was written by
|
||||||
|
.An "Florent Rougon" Aq f.rougon@free.fr
|
||||||
|
for the Debian GNU/Linux system based on the existing FontTools
|
||||||
|
documentation. It may be freely used, modified and distributed without
|
||||||
|
restrictions.
|
||||||
|
.\" For Emacs:
|
||||||
|
.\" Local Variables:
|
||||||
|
.\" fill-column: 72
|
||||||
|
.\" sentence-end: "[.?!][]\"')}]*\\($\\| $\\| \\| \\)[ \n]*"
|
||||||
|
.\" sentence-end-double-space: t
|
||||||
|
.\" End:
|
||||||
176
bot.py
176
bot.py
@@ -215,6 +215,12 @@ class ShutdownManager:
|
|||||||
logger.info("正在优雅关闭麦麦...")
|
logger.info("正在优雅关闭麦麦...")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
|
# 停止WebUI开发服务(如果有)
|
||||||
|
try:
|
||||||
|
await WebUIManager.stop_dev_server()
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"停止WebUI开发服务时出错: {e}")
|
||||||
|
|
||||||
# 停止异步任务
|
# 停止异步任务
|
||||||
tasks_stopped = await TaskManager.stop_async_tasks()
|
tasks_stopped = await TaskManager.stop_async_tasks()
|
||||||
|
|
||||||
@@ -355,6 +361,169 @@ class EasterEgg:
|
|||||||
logger.info(rainbow_text)
|
logger.info(rainbow_text)
|
||||||
|
|
||||||
|
|
||||||
|
class WebUIManager:
|
||||||
|
"""WebUI 开发服务器管理"""
|
||||||
|
|
||||||
|
_process = None
|
||||||
|
_drain_task = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def start_dev_server(timeout: float = 60.0) -> bool:
|
||||||
|
"""启动 ../webui 的 `npm run dev` 并在超时内检测是否启动成功。
|
||||||
|
|
||||||
|
返回 True 表示检测到成功信号;False 表示失败/超时/进程退出。
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
webui_dir = Path(__file__).resolve().parent.parent / "webui"
|
||||||
|
if not webui_dir.exists():
|
||||||
|
logger.error(f"未找到 webui 目录: {webui_dir}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if WebUIManager._process and WebUIManager._process.returncode is None:
|
||||||
|
logger.info("WebUI 开发服务器已在运行,跳过重复启动")
|
||||||
|
return True
|
||||||
|
|
||||||
|
logger.info(f"正在启动 WebUI 开发服务器: npm run dev (cwd={webui_dir})")
|
||||||
|
npm_exe = "npm.cmd" if platform.system().lower() == "windows" else "npm"
|
||||||
|
proc = await asyncio.create_subprocess_exec(
|
||||||
|
npm_exe,
|
||||||
|
"run",
|
||||||
|
"dev",
|
||||||
|
cwd=str(webui_dir),
|
||||||
|
stdout=asyncio.subprocess.PIPE,
|
||||||
|
stderr=asyncio.subprocess.STDOUT,
|
||||||
|
)
|
||||||
|
WebUIManager._process = proc
|
||||||
|
|
||||||
|
success_keywords = [
|
||||||
|
"compiled successfully",
|
||||||
|
"ready in",
|
||||||
|
"local:",
|
||||||
|
"listening on",
|
||||||
|
"running at:",
|
||||||
|
"started server",
|
||||||
|
"app running at:",
|
||||||
|
"ready - started server",
|
||||||
|
]
|
||||||
|
failure_keywords = [
|
||||||
|
"err!",
|
||||||
|
"error",
|
||||||
|
"eaddrinuse",
|
||||||
|
"address already in use",
|
||||||
|
"syntaxerror",
|
||||||
|
"fatal",
|
||||||
|
]
|
||||||
|
|
||||||
|
start_ts = time.time()
|
||||||
|
detected_success = False
|
||||||
|
|
||||||
|
async def _drain_and_detect():
|
||||||
|
nonlocal detected_success
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
line = await proc.stdout.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
text = line.decode(errors="ignore").rstrip()
|
||||||
|
logger.info(f"[webui] {text}")
|
||||||
|
low = text.lower()
|
||||||
|
if any(k in low for k in success_keywords):
|
||||||
|
detected_success = True
|
||||||
|
break
|
||||||
|
if any(k in low for k in failure_keywords):
|
||||||
|
detected_success = False
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"webui 输出读取异常: {e}")
|
||||||
|
|
||||||
|
# 在检测窗口内读取输出判定成功/失败
|
||||||
|
while True:
|
||||||
|
if proc.returncode is not None:
|
||||||
|
if proc.returncode != 0:
|
||||||
|
logger.error(f"WebUI 进程提前退出,退出码: {proc.returncode}")
|
||||||
|
else:
|
||||||
|
logger.warning("WebUI 进程已退出")
|
||||||
|
break
|
||||||
|
|
||||||
|
# 使用短期读取以便及时检查超时
|
||||||
|
try:
|
||||||
|
line = await asyncio.wait_for(proc.stdout.readline(), timeout=1.0)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
line = b""
|
||||||
|
|
||||||
|
if line:
|
||||||
|
text = line.decode(errors="ignore").rstrip()
|
||||||
|
logger.info(f"[webui] {text}")
|
||||||
|
low = text.lower()
|
||||||
|
if any(k in low for k in success_keywords):
|
||||||
|
detected_success = True
|
||||||
|
break
|
||||||
|
if any(k in low for k in failure_keywords):
|
||||||
|
detected_success = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if time.time() - start_ts > timeout:
|
||||||
|
logger.warning("WebUI 启动检测超时")
|
||||||
|
break
|
||||||
|
|
||||||
|
# 后台持续清空输出,避免缓冲区阻塞
|
||||||
|
async def _drain_rest():
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
line = await proc.stdout.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
text = line.decode(errors="ignore").rstrip()
|
||||||
|
logger.info(f"[webui] {text}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"webui 日志读取停止: {e}")
|
||||||
|
|
||||||
|
WebUIManager._drain_task = asyncio.create_task(_drain_rest())
|
||||||
|
|
||||||
|
return bool(detected_success)
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
logger.error("未找到 npm,请确认已安装 Node.js 并将 npm 加入 PATH")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"启动 WebUI 开发服务器失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def stop_dev_server(timeout: float = 5.0) -> bool:
|
||||||
|
"""停止 WebUI 开发服务器(如果在运行)。"""
|
||||||
|
proc = WebUIManager._process
|
||||||
|
if not proc:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
if proc.returncode is None:
|
||||||
|
try:
|
||||||
|
proc.terminate()
|
||||||
|
except ProcessLookupError:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"发送终止信号失败: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
await asyncio.wait_for(proc.wait(), timeout=timeout)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
try:
|
||||||
|
proc.kill()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
# 处理输出清空任务
|
||||||
|
if WebUIManager._drain_task and not WebUIManager._drain_task.done():
|
||||||
|
WebUIManager._drain_task.cancel()
|
||||||
|
try:
|
||||||
|
await WebUIManager._drain_task
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
logger.info("WebUI 开发服务器已停止")
|
||||||
|
return True
|
||||||
|
finally:
|
||||||
|
WebUIManager._process = None
|
||||||
|
WebUIManager._drain_task = None
|
||||||
|
|
||||||
class MaiBotMain:
|
class MaiBotMain:
|
||||||
"""麦麦机器人主程序类"""
|
"""麦麦机器人主程序类"""
|
||||||
|
|
||||||
@@ -455,6 +624,13 @@ async def main_async():
|
|||||||
# 确保环境文件存在
|
# 确保环境文件存在
|
||||||
ConfigManager.ensure_env_file()
|
ConfigManager.ensure_env_file()
|
||||||
|
|
||||||
|
# 启动 WebUI 开发服务器
|
||||||
|
webui_ok = await WebUIManager.start_dev_server(timeout=60)
|
||||||
|
if webui_ok:
|
||||||
|
logger.info("WebUI 启动成功,继续下一步骤")
|
||||||
|
else:
|
||||||
|
logger.error("WebUI 启动失败,继续下一步骤")
|
||||||
|
|
||||||
# 创建主程序实例并执行初始化
|
# 创建主程序实例并执行初始化
|
||||||
maibot = MaiBotMain()
|
maibot = MaiBotMain()
|
||||||
main_system = await maibot.run_sync_init()
|
main_system = await maibot.run_sync_init()
|
||||||
|
|||||||
Reference in New Issue
Block a user