sarugaku / shellingham Goto Github PK
View Code? Open in Web Editor NEWTool to Detect Surrounding Shell
License: ISC License
Tool to Detect Surrounding Shell
License: ISC License
For example, psutil seems to have no problem finding the parent shell.
I'm hoping that shellingham's window support can be extended because what I really would like is for poetry to work on windows via (git-bash, cygwin, mingw) See bug filed over there. In poetry's case, if they'd just use shell=True when launching the subprocess, the shell detection wouldn't matter.
But if shellingham could return the actual path of the shell instead of just it's name, maybe poetry would just start working.
from typing import Tuple, List
import os
import psutil
SHELL_NAMES = {
'sh', 'bash', 'dash', 'ash', # Bourne.
'csh', 'tcsh', # C.
'ksh', 'zsh', 'fish', # Common alternatives.
'cmd', 'powershell', 'pwsh', # Microsoft.
'elvish', 'xonsh', # More exotic.
}
def find_shell_for_windows() -> Tuple[str,str]:
names_paths:List[Tuple[str,str]]=[]
current_process = psutil.Process(os.getppid())
process_name, process_path = current_process.name(), current_process.exe()
names_paths.append((process_name, process_path))
for parent in current_process.parents():
names_paths.append((parent.name(), parent.exe()))
for n,p in names_paths:
if n.lower() in SHELL_NAMES or n.lower().replace(".exe","") in SHELL_NAMES:
return n,p
return ["",""]
if __name__ == '__main__':
print(find_shell_for_windows())
results
$ python ./detect_shell.py
('bash.exe', 'C:\Program Files\Git\usr\bin\bash.exe')
And then bash is launched from powershell via & "C:\Program Files\Git\usr\bin\bash.exe" --login
I like what you are doing, it seem a little plan though.
I always feel the point of putting things on GitHub is to find and work on things as a team and make a good program better ; however I often find people do not like traveling the direction i want to go.
I wanted to try to add a couple features to this library such as
1.)* the ability to launch a shell
2.)* the ability to add text to the shell (show a helpful messages)
3.)* the ability to add command to the shell (put a complete command on the terminal and all you have to do is push enter, kind of like tab completion)
4.)* the ability to read the shell command
Would any of these features be acceptable to your project?
To give you a better understanding of what these features would do and give you an example of there use. I thought I will give you Example session of a imaginary python program called git-helper( to help people learn to use git quicker) that used my purposed features . git-helper would first give you a list of common git task and help you complete each of those task on the shell. A common task like update a git repository could be made a lot easier.
You would type git-helper at the shell , it would then display list of common git task and a helpful massage
example secession
$git-helper
welcome to git-helper. Git helper is a tool that help write git command on the command line
here is a list of common git task
1.) clone a new repository
2.) update get repository
3.) commit changes
4.)etc.
which do you want to do.
you would type some like 1 and press enter(I going to pretend you enter 1 from the menu to show feature 1 from my list)
I going to launch you preferred shell and give you an example commands to help you complete this task.
you could then monitor thing like which directory the git-helper was launch in and if found not be in a git repository for example
then display a message (feature 2 and 3 from my list)
First you have to be in a repository here is the command to do that make appropriate changes
$ cd ~/src/git
I know of a couple of methods of doing this.
1.) Fork this code but i need permission from you to do this.
2.) Create my own library and add your library as dependency
3*.) Add to this library only can be done if you want the changes.
I would preferred to use method 3 ;however such a change might be to far outside the scope of this project and might have to go with method 2.
What do you think?
Thank you for any commit.
Please note I don't have much for time and probably won't be able to implement any of this but still would love to know your
though on the best way to implement such features. I have done a lot of reading on ptty and find it very confusing yet since it is obvious that you spent a lot of time on working with the shell I was hope you would have some useful pointers.
Following up from pypa/pipenv#498, where I describe some issues using pipenv with xonsh. I had been using pipenv and xonsh without issue on an older machine (having a months old install of both pipenv and xonsh. that machine is gone now; so i don't know the package versions, unfortunately), and am now running into problems that make this environment unusable on a brand new machine, with a fresh Mac OS + Python 3.6 install [1].
To start, one of the symptoms is that processes just go into the background after running pipenv shell
. For example, in a fresh iTerm2 shell, I'm trying to launch vi
and as soon as I hit enter, the process immediately backgrounds itself:
Last login: Fri Sep 7 15:09:17 on ttys032
berto@theMBP ~
$ $SHELL
'/usr/local/bin/xonsh'
berto@theMBP ~
$ cd ~/Projects/home/ink/
berto@theMBP ~/Projects/home/ink master@19e99fc
$ pipenv shell
Launching subshell in virtual environment…
(ink-a2hdD_Vz) berto@theMBP ~/Projects/home/ink master@19e99fc
$ vi
^Z
(ink-a2hdD_Vz) berto@theMBP ~/Projects/home/ink master@19e99fc
A second symptom is that running pip install within the pipenv somehow doesn't install in the virstualenv:
berto@theMBP ~/Projects/home/ink master@19e99fc
$ pip freeze > ~/tmp/pip.1.txt
berto@theMBP ~/Projects/home/ink master@19e99fc
$ pipenv shell
Launching subshell in virtual environment…
(ink-a2hdD_Vz) berto@theMBP ~/Projects/home/ink master@19e99fc
$ which pip
/Users/berto/.local/share/virtualenvs/ink-a2hdD_Vz/bin/pip
(ink-a2hdD_Vz) berto@theMBP ~/Projects/home/ink master@19e99fc
$ pip install -e .
Obtaining file:///Users/berto/Projects/home/ink
[...]
Successfully installed ink
(ink-a2hdD_Vz) berto@theMBP ~/Projects/home/ink master@19e99fc
$ exit
# NOTE: no longer in the pipenv shell
berto@theMBP ~/Projects/home/ink master@19e99fc
$ which pip
/usr/local/bin/pip
berto@theMBP ~/Projects/home/ink master@19e99fc
$ pip freeze > ~/tmp/pip.2.txt
berto@theMBP ~/Projects/home/ink master@19e99fc
$ diff -u ~/tmp/pip.1.txt ~/tmp/pip.2.txt
--- /Users/berto/tmp/pip.1.txt 2018-09-07 15:15:13.000000000 -0400
+++ /Users/berto/tmp/pip.2.txt 2018-09-07 15:15:28.000000000 -0400
@@ -4,6 +4,7 @@
docker-pycreds==0.3.0
gnureadline==6.3.8
idna==2.7
+-e git+git@git:berto/ink.git@19e99fc075bf75eaf89fa0c4d61884e3546189a5#egg=ink
Jinja2==2.10
MarkupSafe==1.0
pipenv==2018.7.1
When I switch back to bash with chsh -s /bin/bash
and run the commands above, pipenv works the way I expect. Please let me know if there's any more info I can provide.
Thank you!
[1] High Sierra v 10.13.6 with Python 3.6.6 from python.org (and no Python things installed via Homebrew).
Not sure what is going on here:
❯ echo $SHELL
/usr/bin/zsh
❯ /usr/bin/zsh --version
zsh 5.9 (x86_64-pc-linux-gnu)
❯ python -c 'import shellingham; shellingham.detect_shell()'
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/philip/.conda/envs/ora-dev/lib/python3.11/site-packages/shellingham/__init__.py", line 24, in detect_shell
raise ShellDetectionFailure()
shellingham._core.ShellDetectionFailure
❯ python -c 'import shellingham; print(shellingham.__version__)'
1.5.1
Hi.
Are the maintainers open to accepting the addition of type annotations to this project? I am willing to do the work that's needed.
If the answer is yes, a few extra questions:
.pyi
files?from __future__ import annotations
import way (newer, nicer typing syntax) or should I go with "classic" type classes from the typing
module?We have a docker container, for which we're running into a shell detection failure:
Traceback (most recent call last):
File "/opt/conda/bin/verdi", line 8, in <module>
sys.exit(verdi())
File "/opt/conda/lib/python3.7/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/opt/conda/lib/python3.7/site-packages/click/core.py", line 777, in main
_bashcomplete(self, prog_name, complete_var)
File "/opt/conda/lib/python3.7/site-packages/click_completion/patch.py", line 122, in _shellcomplete
echo(get_code(prog_name=prog_name, env_name=complete_var))
File "/opt/conda/lib/python3.7/site-packages/click_completion/core.py", line 299, in get_code
shell = get_auto_shell()
File "/opt/conda/lib/python3.7/site-packages/click_completion/lib.py", line 125, in get_auto_shell
return shellingham.detect_shell()[0]
File "/opt/conda/lib/python3.7/site-packages/shellingham/__init__.py", line 24, in detect_shell
raise ShellDetectionFailure()
shellingham._core.ShellDetectionFailure
For some reason, this only happens when running the docker container on M1 Macbooks (on Intel Macbooks, the error in the container does not occur). Observations:
os.name
is posix
For some reason, the shell detection for posix returns None
shellingham/src/shellingham/posix/__init__.py
Lines 82 to 90 in 325c643
docker run -d -it --name aiida-core aiidateam/aiida-core:1.6.5
docker exec -it --user aiida aiida-core bash
With macOS's Terminal.app, the -$shell
prefix applies to the default shell configured in the terminal application's settings rather than that configured by $SHELL
or chsh
.
In my case, I have fish as my default shell in Terminal's settings but never bothered to run chsh -s fish
(there's really not a lot of point on macOS) so $SHELL
still points to the default of /bin/zsh
. shellingham.posix._iter_process_parents()
returns
[Process(args=('python',), pid='92236', ppid='91296'), Process(args=('-fish',), pid='91296', ppid='91295')
(note the -
in -fish
despite fish
not being my login shell!) which misleads the following line of code into checking $SHELL
.
shellingham/src/shellingham/posix/__init__.py
Lines 88 to 89 in 3e7ca60
>>> shellingham.detect_shell()
('zsh', '/bin/zsh') # <-- Nooooooooo!!!!!
The obvious (but not obviously consequence free) fix I think would be to just .lstrip()
away the leading -
and then let it continue on to the search for known shell names?
On some systems such as FreeBSD, running ps
without an assigned ttys, without login shell and without displaying header may cause ps
command to have no output and exit 1 (e.g. via ssh user@host ps -o pid=
or as part of Ansible script). When this happens, shellingham may fail with subprocess.CalledProcessError
:
In particular, I got this error when I tried to run pipenv over Ansible on FreeBSD:
Traceback (most recent call last):
File "/usr/local/bin/pipenv", line 7, in <module>
from pipenv import cli
File "/usr/local/lib/python3.6/site-packages/pipenv/__init__.py", line 23, in <module>
from .cli import cli
File "/usr/local/lib/python3.6/site-packages/pipenv/cli/__init__.py", line 3, in <module>
from .command import cli
File "/usr/local/lib/python3.6/site-packages/pipenv/cli/command.py", line 7, in <module>
import crayons
File "/usr/local/lib/python3.6/site-packages/pipenv/patched/crayons.py", line 49, in <module>
is_powershell = "powershell" in shellingham.detect_shell()[0]
File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/shellingham/__init__.py", line 22, in detect_shell
shell = get_shell(pid, max_depth=max_depth)
File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/shellingham/posix/__init__.py", line 54, in get_shell
mapping = _get_process_mapping()
File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/shellingham/posix/__init__.py", line 15, in _get_process_mapping
mapping = impl.get_process_mapping()
File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/shellingham/posix/ps.py", line 18, in get_process_mapping
'ps', '-ww', '-o', 'pid=', '-o', 'ppid=', '-o', 'args=',
File "/usr/local/lib/python3.6/subprocess.py", line 336, in check_output
**kwargs).stdout
File "/usr/local/lib/python3.6/subprocess.py", line 418, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['ps', '-ww', '-o', 'pid=', '-o', 'ppid=', '-o', 'args=']' returned non-zero exit status 1.
*** Error code 1
Stop.
$ ssh user@freebsdhost "ps -o pid= || echo $?"
1
The above command is alternating 1 and 0 for some reason, I think because sometimes ps
see a ps
process, but I have been able to reproduce this quite reliably with Vagrant (run vagrant up
then vagrant provision
):
Vagrant.configure("2") do |config|
config.vm.box = "generic/freebsd11"
config.vm.provision :shell, privileged: false, inline: <<-EOF
ps -ww -o pid=
echo $?
EOF
end
Thanks!
Treat cygwin like linux, because its ps command is limited and the proc file system works.
src/shellingham/posix/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/shellingham/posix/__init__.py b/src/shellingham/posix/__init__.py
index ec27b3a..1f4b80c 100644
--- a/src/shellingham/posix/__init__.py
+++ b/src/shellingham/posix/__init__.py
@@ -6,7 +6,7 @@ from .._consts import SHELL_NAMES
def _get_process_mapping():
system = platform.system()
- if system == 'Linux':
+ if system in ('Linux', 'CYGWIN_NT-6.1'):
from . import linux as impl
else:
from . import _default as impl
I think the "6.1" string may change a couple times a year. It may be better to do:
if system == 'Linux' or system.startswith('CYGWIN_NT'):
When I run the command pipenv install
, the exception is thrown:
Traceback (most recent call last):
File "c:\users\tianx\appdata\local\programs\python\python38-32\lib\runpy.py", line 192, in _run_module_as_main
return _run_code(code, main_globals, None,
File "c:\users\tianx\appdata\local\programs\python\python38-32\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Users\tianx\AppData\Local\Programs\Python\Python38-32\Scripts\pipenv.exe\__main__.py", line 4, in <module>
File "c:\users\tianx\appdata\local\programs\python\python38-32\lib\site-packages\pipenv\__init__.py", line 47, in <module>
from .cli import cli
File "c:\users\tianx\appdata\local\programs\python\python38-32\lib\site-packages\pipenv\cli\__init__.py", line 3, in <module>
from .command import cli
File "c:\users\tianx\appdata\local\programs\python\python38-32\lib\site-packages\pipenv\cli\command.py", line 7, in <module>
import crayons
File "C:\Users\tianx\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\pipenv\patched\crayons.py", line 49, in <module>
is_powershell = "powershell" in shellingham.detect_shell()[0]
File "C:\Users\tianx\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\pipenv\vendor\shellingham\__init__.py", line 22, in detect_shell
shell = get_shell(pid, max_depth=max_depth)
File "C:\Users\tianx\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\pipenv\vendor\shellingham\nt.py", line 100, in get_shell
processes = dict(_iter_process())
File "C:\Users\tianx\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\pipenv\vendor\shellingham\nt.py", line 78, in _iter_process
info = {'executable': str(pe.szExeFile.decode('utf-8'))}
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbf in position 0: invalid start byte
And after I changed utf-8
to gbk
in 78L, shellingham\nt.py
, the problem seemed to be solved. Since this line of code is used to get the processes in the system, I guess that it's the Chinese characters in the process name that cause this problem.
https://www.farmanager.com/download.php?l=en
C:\tmp>pipenv shell
Traceback (most recent call last):
File "c:\python36\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
...
...
File "c:\python36\lib\site-packages\pipenv\shells.py", line 29, in detect_info
raise ShellDetectionFailure
pipenv.vendor.shellingham.ShellDetectionFailure
The same under regular command prompt works fine:
C:\tmp>pipenv shell
Launching subshell in virtual environment…
Microsoft Windows [Version 10.0.16299.461]
(c) 2017 Microsoft Corporation. All rights reserved.
@uranusjr FYI
Running an Apple M1 Pro, I started to get
unsupported proc format
as part of running poetry shell
Upon digging, I found this library and saw fairly recent updates. After downgrading from 1.5.2 to 1.5.0, issues is gone.
Have you maybe introduced a regression for M1s?
FYI, I am using poetry in the alpine docker distribution, whose default shell is ash. poetry is unable to run some commands since it relies on shellingham. Please add ash to this set. :-P
shellingham/src/shellingham/_core.py
Lines 1 to 11 in a5128ef
I had the following process running in the background:
$ ps -ww -o pid= -o ppid= -o args=
...
252 197 lame --silent -V 0 -h -r - /Users/r4lv/Je m'voyais déjà.mp3
...
(note the apostrophe)
…which leads to
In [9]: shellingham.detect_shell()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-9-fdb1f77cdcba> in <module>()
----> 1 shellingham.detect_shell()
~/.local/share/virtualenvs/test-shellingham-Ew4jglHR/lib/python3.6/site-packages/shellingham/__init__.py in detect_shell(pid, max_depth)
20 except AttributeError:
21 raise RuntimeError('get_shell not implemented for {0!r}'.format(name))
---> 22 shell = get_shell(pid, max_depth=max_depth)
23 if shell:
24 return shell
~/.local/share/virtualenvs/test-shellingham-Ew4jglHR/lib/python3.6/site-packages/shellingham/posix/__init__.py in get_shell(pid, max_depth)
52 """
53 pid = str(pid or os.getpid())
---> 54 mapping = _get_process_mapping()
55 for proc_cmd in _iter_process_command(mapping, pid, max_depth):
56 if proc_cmd.startswith('-'): # Login shell! Let's use this.
~/.local/share/virtualenvs/test-shellingham-Ew4jglHR/lib/python3.6/site-packages/shellingham/posix/__init__.py in _get_process_mapping()
13 for impl in (proc, ps):
14 try:
---> 15 mapping = impl.get_process_mapping()
16 except EnvironmentError:
17 continue
~/.local/share/virtualenvs/test-shellingham-Ew4jglHR/lib/python3.6/site-packages/shellingham/posix/ps.py in get_process_mapping()
32 continue
33 processes[pid] = Process(
---> 34 args=tuple(shlex.split(args)), pid=pid, ppid=ppid,
35 )
36 return processes
/usr/local/var/pyenv/versions/3.6.5/lib/python3.6/shlex.py in split(s, comments, posix)
303 if not comments:
304 lex.commenters = ''
--> 305 return list(lex)
306
307
/usr/local/var/pyenv/versions/3.6.5/lib/python3.6/shlex.py in __next__(self)
293
294 def __next__(self):
--> 295 token = self.get_token()
296 if token == self.eof:
297 raise StopIteration
/usr/local/var/pyenv/versions/3.6.5/lib/python3.6/shlex.py in get_token(self)
103 return tok
104 # No pushback. Get a token.
--> 105 raw = self.read_token()
106 # Handle inclusions
107 if self.source is not None:
/usr/local/var/pyenv/versions/3.6.5/lib/python3.6/shlex.py in read_token(self)
185 print("shlex: I see EOF in quotes state")
186 # XXX what error should be raised here?
--> 187 raise ValueError("No closing quotation")
188 if nextchar == self.state:
189 if not self.posix:
ValueError: No closing quotation
Maybe the ps
output lines which cannot be parsed using shlex.split
could be skipped?
python 3.6.5 (pyenv)
shellingham 1.2.6
macOS High Sierra 10.13.4
>>> import shellingham
>>> shellingham.detect_shell()
ps: illegal option -- w
ps: illegal option -- w
Usage: ps [-ANPaedfklmMZ] [-n namelist] [-F Format] [-o specifier[=header],...]
[-p proclist][-G|-g grouplist] [-t termlist] [-U|-u userlist] [-c classlist] [ -T pid] [ -L pidlist]
[-@ [wparname] ]
Usage: ps [aceglnsuvwxX] [t tty] [ProcessNumber]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/QOpenSys/pkgs/lib/python3.6/site-packages/shellingham-1.3.1.dev0-py3.6.egg/shellingham/__init__.py", line 25, in detect_shell
shellingham._core.ShellDetectionFailure
The problem is that the AIX version of ps
does not support the -w
option. It does support the w
option (without the -
prefix) in Berkeley mode, but then it doesn't support the -o
option. 😞
(the title says it all)
From #12. Is there a specification on how ps
formats the command line if it contains special characters (spaces in argument, quotes, etc.)? It seems that it is not using the “normal” shell escaping syntax, which makes the it unsuitable to parse with shlex.split()
.
This started happening as of 1.5.3, while it works in 1.5.0post1.
My default shell is Fish, but occasionally I run things under bash – notably PDM activation scripts under Direnv.
With 1.5.3, on both bash and zsh import shellingham; shellingham.detect_shell()
, it always returns fish:
❯ python -m venv venv
❯ venv/bin/python -m pip install shellingham
Looking in indexes: https://pypi.vm.ag/root/vrmd/+simple/
Collecting shellingham
Using cached https://pypi.vm.ag/root/pypi/%2Bf/419/c6a164770c9c7/shellingham-1.5.3-py2.py3-none-any.whl (9.7 kB)
Installing collected packages: shellingham
Successfully installed shellingham-1.5.3
❯ venv/bin/python -c 'import shellingham; print(shellingham.detect_shell())'
('fish', '/opt/homebrew/bin/fish')
❯ zsh
hynek@nazare tmp % venv/bin/python -c 'import shellingham; print(shellingham.detect_shell())'
('fish', '/opt/homebrew/bin/fish')
hynek@nazare tmp %
❯ bash
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
$ venv/bin/python -c 'import shellingham; print(shellingham.detect_shell())'
('fish', '/opt/homebrew/bin/fish')
$ exit
❯ venv/bin/pip install shellingham==1.5.0.post1
Looking in indexes: https://pypi.vm.ag/root/vrmd/+simple/
Collecting shellingham==1.5.0.post1
Using cached https://pypi.vm.ag/root/pypi/%2Bf/368/bf8c00754fd4f/shellingham-1.5.0.post1-py2.py3-none-any.whl (9.4 kB)
Installing collected packages: shellingham
Attempting uninstall: shellingham
Found existing installation: shellingham 1.5.3
Uninstalling shellingham-1.5.3:
Successfully uninstalled shellingham-1.5.3
Successfully installed shellingham-1.5.0.post1
❯ zsh
hynek@nazare tmp % venv/bin/python -c 'import shellingham; print(shellingham.detect_shell())'
('zsh', 'zsh')
hynek@nazare tmp %
❯ bash
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
$ venv/bin/python -c 'import shellingham; print(shellingham.detect_shell())'
('bash', 'bash')
macOS 13.5.1 (22G90) on an ARM Mac; lmk if I can provide you with more information.
From git diff 1.4.0..1.5.0 setup.*
we get, so 1.5.0
should be available for python_requires = >=3.7
:
diff --git a/setup.cfg b/setup.cfg
index 9dd01be..37d4a4a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -16,20 +16,18 @@ classifier =
Intended Audience :: Developers
License :: OSI Approved :: ISC License (ISCL)
Operating System :: OS Independent
- Programming Language :: Python :: 2
- Programming Language :: Python :: 2.6
- Programming Language :: Python :: 2.7
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.4
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
+ Programming Language :: Python :: 3 :: Only
+ Programming Language :: Python :: 3.7
+ Programming Language :: Python :: 3.8
+ Programming Language :: Python :: 3.9
+ Programming Language :: Python :: 3.10
Topic :: Software Development :: Libraries :: Python Modules
[options]
package_dir =
= src
packages = find:
-python_requires = >=2.6,!=3.0,!=3.1,!=3.2,!=3.3
+python_requires = >=3.4
install_requires =
zip_safe = true
But due to above python_requires = >=3.4
, Pypi incorrectly list it as available for Python 3.6. e.g with Ubuntu 18.04:
$ sudo podman run -ti --rm ubuntu:18.04 bash
root@1924dd60b7f6:/# apt update && apt -y install python3-dev python3-pip
root@1924dd60b7f6:/# python3 --version
Python 3.6.9
root@1924dd60b7f6:/# pip3 install shellingham
root@1924dd60b7f6:/# pip3 list | grep shellingham
shellingham (1.5.0)
Please kindly remove 1.5.0
from Pypi and create a new release with python_requires = >=3.7
PS C:\Users\dopry> python
Python 3.10.8 (tags/v3.10.8:aaaf517, Oct 11 2022, 16:50:30) [MSC v.1933 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import shellingham
>>> shellingham.detect_shell()
('cmd', 'C:\\Windows\\System32\\cmd.exe')
>>>
When looking at this repo, I found that it has:
Would it make sense to introduce one - I'll not enumerate the benefits, assuming they are known for the benefits and don't want to expose how to get the PYPI Token from the CI.
https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/
https://docs.pypi.org/trusted-publishers/
From pypa/pipenv#2820. Currently the detection explodes if cmdline (or any other proc entries) is faulty. While there is no way to solve the decode error (it is entirely machine-dependant), Shellingham can at least try to ignore the file and continue looking, hoping that faulty file is not the one we’re looking for.
See pypa/pipenv#2496.
$ python -m pytest
========================================================= test session starts =========================================================
platform linux -- Python 3.11.4, pytest-7.4.0, pluggy-1.2.0
rootdir: /tmp/shellingham
plugins: mock-3.11.1
collected 1 item
tests/test_posix.py F [100%]
============================================================== FAILURES ===============================================================
__________________________________________________ test_get_shell[mapping0-result0] ___________________________________________________
mocker = <pytest_mock.plugin.MockerFixture object at 0x7f928f57d8d0>, environ = <test_posix.EnvironManager object at 0x7f9290491550>
mapping = {'1480': Process(args=('/Applications/iTerm.app/Contents/MacOS/iTerm2', '--server', 'login', '-fp', 'keegan'), pid='14...s=('screen',), pid='1556', ppid='1482'), '1558': Process(args=('-/usr/local/bin/bash',), pid='1558', ppid='1557'), ...}
result = ('bash', '==MOCKED=LOGIN=SHELL==/bash')
@pytest.mark.parametrize('mapping, result', [
( # Based on pypa/pipenv#2496, provided by @keegancsmith.
MAPPING_EXAMPLE_KEEGANCSMITH, ('bash', '==MOCKED=LOGIN=SHELL==/bash'),
),
])
def test_get_shell(mocker, environ, mapping, result):
environ.patch(SHELL='==MOCKED=LOGIN=SHELL==/bash')
> mocker.patch.object(posix, '_get_process_mapping', return_value=mapping)
tests/test_posix.py:86:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.11/site-packages/pytest_mock/plugin.py:255: in object
return self._start_patch(
.venv/lib/python3.11/site-packages/pytest_mock/plugin.py:220: in _start_patch
mocked: MockType = p.start()
/usr/lib/python3.11/unittest/mock.py:1591: in start
result = self.__enter__()
/usr/lib/python3.11/unittest/mock.py:1443: in __enter__
original, local = self.get_original()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <unittest.mock._patch object at 0x7f928f5cb850>
def get_original(self):
target = self.getter()
name = self.attribute
original = DEFAULT
local = False
try:
original = target.__dict__[name]
except (AttributeError, KeyError):
original = getattr(target, name, DEFAULT)
else:
local = True
if name in _builtins and isinstance(target, ModuleType):
self.create = True
if not self.create and original is DEFAULT:
> raise AttributeError(
"%s does not have the attribute %r" % (target, name)
)
E AttributeError: <module 'shellingham.posix' from '/tmp/shellingham/.venv/lib/python3.11/site-packages/shellingham/posix/__init__.py'> does not have the attribute '_get_process_mapping'
/usr/lib/python3.11/unittest/mock.py:1416: AttributeError
======================================================= short test summary info =======================================================
FAILED tests/test_posix.py::test_get_shell[mapping0-result0] - AttributeError: <module 'shellingham.posix' from '/tmp/shellingham/.venv/lib/python3.11/site-packages/shellingham/posix/__init__.p...
========================================================== 1 failed in 0.16s ==========================================================
This is on Gentoo Linux amd64, Python 3.11.4, shellingham 1.5.3 (b8ba512).
bisect blames 7bf9e76. Indeed, it seems that _get_process_mapping()
was removed there.
Also, it seems that CI doesn't actually run tests, since only test
env runs tests, and CI runs all the other envs that apparently only install the package.
The sdist package at PyPI is missing tests. Please add tests to sdist to make downstream testing easier. I'm packaging shellingham for OpenIndiana and this would make the integration easier. Thank you.
I'm having issues with xonsh
on arch linux 5.5.0.
Shellingham fails to detect the xonsh
process as it comes with a python
prefix as it's a python program:
$ ps -ww -o "pid=" -o "ppid=" -o "args="
1633 1624 python /usr/bin/xonsh
I've investigated shellingham
's code and it seems like the first argument is taken to determine the shell process which in this case is python
, where the second argument is the correct one in this case (/usr/bin/xonsh
).
It seems that python
prefix here is unatural but I can't debug why my machine persists on attaching it. Might be an issue with . Thus I'm not sure whether upstream changes are warranted.qtile
environment
Hi, I've hit an issue on Solaris 11.4 when trying to invoke a shell using pipenv version 2018.11.26 (python3.7)
Similar to:
detect_shell fails on IBM i / AIX #21
The messages I would see were like so:
host# pipenv shell
Traceback (most recent call last):
File "/usr/local/bin/pipenv", line 6, in <module>
from pipenv import cli
File "/usr/local/lib/python3.7/site-packages/pipenv/__init__.py", line 47, in <module>
from .cli import cli
File "/usr/local/lib/python3.7/site-packages/pipenv/cli/__init__.py", line 3, in <module>
from .command import cli
File "/usr/local/lib/python3.7/site-packages/pipenv/cli/command.py", line 7, in <module>
import crayons
File "/usr/local/lib/python3.7/site-packages/pipenv/patched/crayons.py", line 49, in <module>
is_powershell = "powershell" in shellingham.detect_shell()[0]
File "/usr/local/lib/python3.7/site-packages/pipenv/vendor/shellingham/__init__.py", line 22, in detect_shell
shell = get_shell(pid, max_depth=max_depth)
File "/usr/local/lib/python3.7/site-packages/pipenv/vendor/shellingham/posix/__init__.py", line 54, in get_shell
mapping = _get_process_mapping()
File "/usr/local/lib/python3.7/site-packages/pipenv/vendor/shellingham/posix/__init__.py", line 15, in _get_process_mapping
mapping = impl.get_process_mapping()
File "/usr/local/lib/python3.7/site-packages/pipenv/vendor/shellingham/posix/proc.py", line 64, in get_process_mapping
tty, ppid = _get_stat(pid, stat_name)
File "/usr/local/lib/python3.7/site-packages/pipenv/vendor/shellingham/posix/proc.py", line 36, in _get_stat
return parts[STAT_TTY], parts[STAT_PPID]
IndexError: list index out of range
The real issue here is that when shellingham tries to split the data it reads from /proc/PID/status, it fails, because the formatting is not as it expected.
In order to get around this, I modified posix/proc.py like so:
--- proc.py Mon Sep 9 17:31:45 2019
+++ /usr/local/lib/python3.7/site-packages/pipenv/vendor/shellingham/posix/proc.py Mon Sep 9 17:25:12 2019
@@ -4,6 +4,7 @@
import sys
from ._core import Process
+from .._core import ShellDetectionFailure
STAT_PPID = 3
@@ -33,7 +34,10 @@
with io.open(path, encoding='ascii', errors='replace') as f:
# We only care about TTY and PPID -- all numbers.
parts = STAT_PATTERN.findall(f.read())
- return parts[STAT_TTY], parts[STAT_PPID]
+ try:
+ return parts[STAT_TTY], parts[STAT_PPID]
+ except IndexError:
+ raise ShellDetectionFailure
This solved the failures on my end.
Perhaps this is already fixed by 'Switch to parse 'ps wwl' for better compatibility #23'.
I can test this if necessary.
It seems to be quite common to use sys.getfilesystemencoding() or sys.getdefaultencoding()
.
shellingham currently fails to detect shells inside docker containers running with the [Docker Desktop option to run x86 binaries with rosetta]([Docker Desktop for Mac] - Support for running x86-64 binaries with Rosetta 2).
This is due to the fact that in this case the proc_args
have /rosetta/rosetta
as their first element and the second element is the actual shell, which currently isn't checked by shellingham.
Requires an Apple Silicon machine with Docker Desktop installed and the option "Use Rosetta for x86/amd64 emulation on Apple Silicon" enabled as in the following screenshot:
Using the following Dockerfile:
FROM --platform=linux/amd64 debian:bullseye
RUN set -ex && \
apt-get update && \
apt-get -y install \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/* && \
pip3 install shellingham
Then open a shell in that docker container with
docker build . -t shellingham-rosetta-bug-mre && docker run --platform=linux/amd64 -it shellingham-rosetta-bug-mre /bin/bash
and finally in the container try to detect the shell with shellingham
python3 -c 'import shellingham; print(shellingham.detect_shell())'
Currently Python 3.6 is the most recent supported version according to the classifiers specified in setup.cfg
.
Python 3.6 is due to lose support later this year and most will probably have migrated to Python 3.8 or 3.9 at this point.
As far as I can tell shellingham
works perfectly fine on these more recent Python versions - it might be worthwhile to make the classifiers reflect this and perhaps set up a Python version test matrix on CI?
I'm currently using poetry (a tool similar to pipenv, but based on pyproject.toml), for building a python project. This tool relies on shellingham to detect the running shell and launch them in its virtual environments.
Running the command poetry shell
as a task in Visual Studio Code, like this:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "poetry shell",
"type": "shell",
"command": "poetry shell",
"problemMatcher": []
}
]
}
produces the following outcome:
> Executing task: poetry shell <
Spawning shell within /Users/nahuel/Library/Caches/pypoetry/virtualenvs/testproject-py3.6
[RuntimeError]
Unable to detect the current shell.
shell
The terminal process terminated with exit code: 1
Terminal will be reused by tasks, press any key to close it.
Would it be possible to use the $SHELL variable if there's no process in the tree with a usable shell name?
Hello,
I seem to be running into an issue with Windows 10. In the below example, I'm using ipython in the standard Windows Command Prompt. I am not sure if this is relevant, but I am using a corporate computer, where running applications in administrative is disable. I would be glad to provide additional details.
Python 3.6.5 |Anaconda custom (64-bit)| (default, Mar 29 2018, 13:32:41) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import shellingham
In [2]: shellingham.detect_shell()
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-2-fdb1f77cdcba> in <module>()
----> 1 shellingham.detect_shell()
~\AppData\Local\Continuum\anaconda3\lib\site-packages\shellingham\__init__.py in detect_shell(pid, max_depth)
20 except AttributeError:
21 raise RuntimeError('get_shell not implemented for {0!r}'.format(name))
---> 22 shell = get_shell(pid, max_depth=max_depth)
23 if shell:
24 return shell
~\AppData\Local\Continuum\anaconda3\lib\site-packages\shellingham\nt.py in get_shell(pid, max_depth)
115 if not pid:
116 pid = os.getpid()
--> 117 processes = get_all_processes()
118
119 def check_parent(pid, lvl=0):
~\AppData\Local\Continuum\anaconda3\lib\site-packages\shellingham\nt.py in get_all_processes()
95 if pe.th32ParentProcessID:
96 pids[pe.th32ProcessID]['parent_pid'] = pe.th32ParentProcessID
---> 97 pe = Process32Next(h_process, pe)
98
99 return pids
~\AppData\Local\Continuum\anaconda3\lib\site-packages\shellingham\nt.py in Process32Next(hSnapshot, pe)
72 if windll.kernel32.GetLastError() == ERROR_NO_MORE_FILES:
73 return
---> 74 raise WinError()
75 return pe
76
OSError: [WinError 122] The data area passed to a system call is too small.
In [3]: shellingham.__version__
Out[3]: '1.2.3'
pip install --no-binary=shellingham shellingham==1.3.2
Collecting shellingham==1.3.2
Downloading https://files.pythonhosted.org/packages/4b/f0/39516ebeaca978d6607609a283b15e7637622faffc5f01ecf78a49b24cd5/shellingham-1.3.2.tar.gz
Installing build dependencies ... done
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/cchow/.pyenv/versions/3.6.6/lib/python3.6/tokenize.py", line 452, in open
buffer = _builtin_open(filename, 'rb')
FileNotFoundError: [Errno 2] No such file or directory: '/private/var/folders/jz/ml8h8ykd55zfpzgrd04qc53h0000gn/T/pip-install-pka7dnps/shellingham/setup.py'
----------------------------------------
dopry@Quasar MINGW64 ~
$ python
Python 3.10.8 (tags/v3.10.8:aaaf517, Oct 11 2022, 16:50:30) [MSC v.1933 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import shellingham
>>> shellingham.detect_shell()
('cmd', 'C:\\Windows\\System32\\cmd.exe')
>>>
hi,
why i get the following errors - and how to fix it?
RuntimeError
Hash for tensorflow-io (0.26.0) from archive tensorflow_io-0.26.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl not found in known hashes (was: sha256:5e7d1243011f4fb3bdc065ab23677146e450d23ed28051890320662737725c2b)
at ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/poetry/installation/executor.py:673 in _validate_archive_hash
669│ archive_hash: str = "sha256:" + file_dep.hash()
670│ known_hashes = {f["hash"] for f in package.files}
671│
672│ if archive_hash not in known_hashes:
→ 673│ raise RuntimeError(
674│ f"Hash for {package} from archive {archive.name} not found in"
675│ f" known hashes (was: {archive_hash})"
676│ )
677│
Warning: The file chosen for install of shellingham 1.5.0 (shellingham-1.5.0-py2.py3-none-any.whl) is yanked. Reason for being yanked: Incorrect package metadata
Hi if I download the tarball file from tag 1.3.2, setup.py seems to be not add to tarball. Sorry if I'm wrong.
$ wget https://github.com/sarugaku/shellingham/archive/1.3.2.tar.gz
$ tar -tvf 1.3.2.tar.gz
drwxrwxr-x root/root 0 2020-02-12 06:23 shellingham-1.3.2/
-rw-rw-r-- root/root 71 2020-02-12 06:23 shellingham-1.3.2/.gitignore
-rw-rw-r-- root/root 3534 2020-02-12 06:23 shellingham-1.3.2/CHANGELOG.rst
-rw-rw-r-- root/root 751 2020-02-12 06:23 shellingham-1.3.2/LICENSE
-rw-rw-r-- root/root 48 2020-02-12 06:23 shellingham-1.3.2/MANIFEST.in
-rw-rw-r-- root/root 193 2020-02-12 06:23 shellingham-1.3.2/Pipfile
-rw-rw-r-- root/root 6245 2020-02-12 06:23 shellingham-1.3.2/Pipfile.lock
-rw-rw-r-- root/root 2565 2020-02-12 06:23 shellingham-1.3.2/README.rst
drwxrwxr-x root/root 0 2020-02-12 06:23 shellingham-1.3.2/news/
-rw-rw-r-- root/root 12 2020-02-12 06:23 shellingham-1.3.2/news/.gitignore
-rw-rw-r-- root/root 690 2020-02-12 06:23 shellingham-1.3.2/pyproject.toml
-rw-rw-r-- root/root 1100 2020-02-12 06:23 shellingham-1.3.2/setup.cfg
drwxrwxr-x root/root 0 2020-02-12 06:23 shellingham-1.3.2/src/
drwxrwxr-x root/root 0 2020-02-12 06:23 shellingham-1.3.2/src/shellingham/
-rw-rw-r-- root/root 624 2020-02-12 06:23 shellingham-1.3.2/src/shellingham/__init__.py
-rw-rw-r-- root/root 322 2020-02-12 06:23 shellingham-1.3.2/src/shellingham/_core.py
-rw-rw-r-- root/root 4426 2020-02-12 06:23 shellingham-1.3.2/src/shellingham/nt.py
drwxrwxr-x root/root 0 2020-02-12 06:23 shellingham-1.3.2/src/shellingham/posix/
-rw-rw-r-- root/root 2843 2020-02-12 06:23 shellingham-1.3.2/src/shellingham/posix/__init__.py
-rw-rw-r-- root/root 81 2020-02-12 06:23 shellingham-1.3.2/src/shellingham/posix/_core.py
-rw-rw-r-- root/root 2114 2020-02-12 06:23 shellingham-1.3.2/src/shellingham/posix/proc.py
-rw-rw-r-- root/root 1585 2020-02-12 06:23 shellingham-1.3.2/src/shellingham/posix/ps.py
drwxrwxr-x root/root 0 2020-02-12 06:23 shellingham-1.3.2/tasks/
-rw-rw-r-- root/root 864 2020-02-12 06:23 shellingham-1.3.2/tasks/CHANGELOG.rst.jinja2
-rw-rw-r-- root/root 3412 2020-02-12 06:23 shellingham-1.3.2/tasks/__init__.py
drwxrwxr-x root/root 0 2020-02-12 06:23 shellingham-1.3.2/tests/
-rw-rw-r-- root/root 2484 2020-02-12 06:23 shellingham-1.3.2/tests/test_posix.py
The file is missing, but needed to build an rpm package.
The real question is can we even spawn processes using this?
I noticed this on Github Actions. I haven't reproduced it locally since I don't have a Mac, and it doesn't seem to occur on Linux.
ps
normally lists processes on the same tty. It seems on Linux when run outside a tty, it just lists processes regardless of the connected terminal. But based on what I saw on Github actions, it seems this instead lists no processes.
Probably can be fixed with an appropriate argument to ps
, though some care may be required to avoid breaking anything else and to be compatible with all ps
implementations.
From pypa/pipenv#3382. Need to do something similar to #10: Try system encoding, and then utf-8, and replace unparsables.
Edit: No we don’t want to try UTF-8.
When trying to install any package or execute any pipenv
sub-command, pipenv fails with [WinError 6] The handle is invalid
Aareon@DESKTOP-K5VQOE1 MINGW64 /i/StaSH2 (master)
$ pipenv install dearpygui
Traceback (most recent call last):
File "i:\programs\pypy3.7-v7.3.4-win64\lib-python\3\runpy.py", line 196, in _r
un_module_as_main
"__main__", mod_spec)
File "i:\programs\pypy3.7-v7.3.4-win64\lib-python\3\runpy.py", line 85, in _ru
n_code
exec(code, run_globals)
File "I:\Programs\pypy3.7-v7.3.4-win64\Scripts\pipenv.exe\__main__.py", line 4
, in <module>
from pipenv import cli
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\__init__.py", line
55, in <module>
from .cli import cli
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\cli\__init__.py",
line 4, in <module>
from .command import cli # noqa
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\cli\command.py", l
ine 13, in <module>
from ..exceptions import PipenvOptionsError
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\exceptions.py", li
ne 14, in <module>
from .patched import crayons
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\patched\crayons.py
", line 49, in <module>
is_powershell = "powershell" in shellingham.detect_shell()[0]
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\vendor\shellingham
\__init__.py", line 22, in detect_shell
shell = get_shell(pid, max_depth=max_depth)
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\vendor\shellingham
\nt.py", line 111, in get_shell
processes = dict(_iter_process())
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\vendor\shellingham
\nt.py", line 77, in _iter_process
raise WinError()
OSError: [WinError 6] The handle is invalid
Using latest Pypy3, but I doubt that has anything to do with my issue as I am able to install packages perfectly fine with other terminal emulators (Windows Terminal, Powershell) & Pipenv.
Expected packages (ex. flake8) to install w/o error in Git Bash as they do in any other terminal.
[WinError 6] The handle is invalid
py -m pip install pipenv -U
pipenv install flake8
pipenv --support
result:
$ pipenv --support
Traceback (most recent call last):
File "i:\programs\pypy3.7-v7.3.4-win64\lib-python\3\runpy.py", line 196, in _r
un_module_as_main
"__main__", mod_spec)
File "i:\programs\pypy3.7-v7.3.4-win64\lib-python\3\runpy.py", line 85, in _ru
n_code
exec(code, run_globals)
File "I:\Programs\pypy3.7-v7.3.4-win64\Scripts\pipenv.exe\__main__.py", line 4
, in <module>
from pipenv import cli
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\__init__.py", line
55, in <module>
from .cli import cli
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\cli\__init__.py",
line 4, in <module>
from .command import cli # noqa
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\cli\command.py", l
ine 13, in <module>
from ..exceptions import PipenvOptionsError
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\exceptions.py", li
ne 14, in <module>
from .patched import crayons
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\patched\crayons.py
", line 49, in <module>
is_powershell = "powershell" in shellingham.detect_shell()[0]
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\vendor\shellingham
\__init__.py", line 22, in detect_shell
shell = get_shell(pid, max_depth=max_depth)
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\vendor\shellingham
\nt.py", line 111, in get_shell
processes = dict(_iter_process())
File "i:\programs\pypy3.7-v7.3.4-win64\site-packages\pipenv\vendor\shellingham
\nt.py", line 77, in _iter_process
raise WinError()
OSError: [WinError 6] The handle is invalid
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.