Package: gappy-system
gappy — a Python interface to GAPgappy provides a Python interface to theGAPcomputer algebra system by linking to its
library interface.It allows calling functions in GAP directly from Python, and passing
supported Python objects back to GAP.gappy is based on SageMath’sLibGAPinterface to GAP, originally developed by Volker Braun, but is completely
independent of Sage–it does not require or use Sage at all, and can be used
in any Python code.  If there is enough interest, it may also be enhanced
with a complementary GAP package for interacting with Python from within
GAP.QuickstartInstallationPrerequisitesConda installationCygwin installationChangelogv0.1.0a3 (2021-02-15)EnhancementsBug fixesv0.1.0a2 (2021-02-03)v0.1.0a1 (2021-02-03)EnhancementsBug fixesv0.1.0a0 (2021-01-26)QuickstartTo start using GAP functions from Python, just run:>>>fromgappyimportgapThen any global variable in GAP, including functions, can be accessed as
attributes ongaplike:>>>gap.Cite()PleaseuseoneofthefollowingsamplestociteGAPversionfromthisinstallationText:[GAP]GAP–Groups,Algorithms,andProgramming,Version4.dev,TheGAPGroup,https://www.gap-system.org....All global variables that would be available in a GAP session can be
accessed in this way:>>>GAPInfo.Version"4.dev"Most basic Python types have direct equivalents in GAP, and can be passed
directly to GAP functions without explicit conversion to their equivalent
GAP types:>>>S4=gap.SymmetricGroup(4)>>>S4Sym([1..4])You can also call “methods” onGapObjs.  This is just syntactic sugar
for calling a GAP function with that object as its first argument, in cases
where that function supports the object bound to the method.  For example:>>>S4.GeneratorsOfGroup()[(1,2,3,4),(1,2)]Values returned from GAP functions are GAP objects wrapped in a Python class
for containing them calledGapObj:>>>type(S4)<class'gappy.gapobj.GapObj'>There are also specialized subclasses ofGapObjfor many types of objects
in GAP.  To explicitly convert a Python object directly to its GAP
equivalent, you cancallgaplike:>>>one=gap(1)>>>type(one)<class'gappy.gapobj.GapInteger'>GAP objects are displayed (withrepr) or stringified (withstr) the same
way they would be in GAP, when displaying the object in the REPL or when
calling GAP’sPrint()function on the object, respectively:>>>one1>>>s=gap("Hello GAP!")>>>s"Hello GAP!">>>print(s)HelloGAP!Not all GAP objects have an equivalent in basic Python types, so there is
no implicit conversion from GAP back to Python.  However, all Python types
that can be converted to GAP objects can be converted back to their
equivalent Python types in a symmetrical manner:>>>int(one)1>>>type(int(one))<class'int'>>>>str(s)'Hello GAP!'>>>type(str(s))<class'str'>Likewise forfloats,lists,dicts, among others.You can also callobj.python()to convert to its equivalent Python type
if one exists:>>>type(one.python())<class'int'>To register your own converters for GAP objects to custom Python types, see
thegap.convert_todecorator.Finally, you can execute arbitrary GAP code directly withgap.eval.
This is often the easiest way to construct more complicated GAP objects,
especially if you are more familiar with GAP syntax.  The return value ofgap.evalis the result of evaluating the same statement in GAP (the
semicolon is optional when evaluating a single statement):>>>rec=gap.eval('rec(a:=123, b:=456, Sym3:=SymmetricGroup(3))')>>>rec['Sym3']Sym([1..3])This is also an easy way to declare new GAP functions from gappy:>>>sign=gap.eval("""sign := function(n)
...     if n < 0 then
...         return -1;
...     elif n = 0 then
...         return 0;
...     else
...         return 1;
...     fi;
... end;""")>>>sign<GAPfunction"sign">>>>sign(0)0>>>sign(-99)-1See the full API documentation for many additional examples of how to use
thegapobject as well as the built-inGapObjtypes.InstallationNoteThese instructions will be updated once there are releases on PyPI.PrerequisitesSupported platforms: Linux, MacOS, Cygwin.Likely works with most other *BSD flavors but has not been tested.Python 3.6 or up with development headers installed.  On Debian-based
systems this means:$sudoapt-getinstallpython3.7-devGAP 4.10.2 or greaterIt is possible to install from PyPI (note the distribution namegappy-system,do notinstall the package “gappy” which is an
unrelated obsolete package):$pipinstallgappy-systemor from source:$gitclonehttps://github.com/embray/gappy.git$cdgappy/$pipinstall.However, depending on how GAP is installed, some extra steps may be
required.  In particular, if you installed GAP from source using the
typical instructions on theGAP websiteyou will need to make
sure the libgap shared library is built by running:$makeinstall-libgapin the GAP source directory.You will also need to point to the location of your GAP installation by
setting theGAP_ROOTenvironment variable like:$GAP_ROOT=<path/to/gap/root>pipinstall.If you needed to provideGAP_ROOTfor the installation, it is also
generally necessary to set this environment variablebeforeusing gappy,
so that it can find the path to your GAP installation.  See the
documentation for theGapclass for more information.If using GAP from a distribution system such as APT on Debian/Ubuntu or from
Conda, however, the GAP library (libgap) is typically installed in a
standard system location, and it may not be necessary to provideGAP_ROOT.  See the next section for example.Conda installationTo give an example of the above point, you can install gappy in a Conda
environment as follows:$condacreate-ngap$condaactivategap$condainstall-cconda-forgegap-defaults==4.11python==3.8$pipinstall.Alternatively, you can create the conda environment using the suppliedenvironment.ymlfile:$condaenvcreateNoteWith Conda and other distributions that install libgap to a standard
system location (e.g./usr/lib/libgap.so) it may not be necessary to
set theGAP_ROOTenvironment variable, as the library can locate
your GAP root automatically in most cases.WarningThe conda package for GAP 4.11 had dependency conflicts with Python 3.7
so you must use Python 3.8 or above, or GAP 4.10.2 with Python 3.7.Cygwin installationAdditional notes for installation on Cygwin:The dependencypsutildoes not support Cygwin.  However, there is an
unofficial fork which does at:https://github.com/embray/psutil/tree/cygwin/v3.  You can install it by
running:$pipinstallgit+https://github.com/embray/psutil.git@cygwin/v3The path to the libgap DLL (filenamecyggap-0.dll) needs to be on
yourPATHenvironment variable in order for gappy to be importable.
To do this you can either copy it from your GAP installation to a standard
location like:$cp/path/to/gap_root/.libs/cyggap-0.dll/usr/local/binor you can modify your environment to point to where GAP places the built
DLL:$exportPATH="/path/to/gap_root/.libs:$PATH"and add this to your.profile.Changelogv0.1.0a3 (2021-02-15)EnhancementsRenamed the special method_gap_, for converting arbitrary Python
objects to GAP objects, to__gap__as inspired by the discussion athttps://trac.sagemath.org/ticket/31297#comment:23Likewise, the special method_gap_init_is now named__gap_eval__to emphasize that it returns a string to be passed
toGap.eval().  It still does not take any arguments.AddedGapObj.python()method for converting aGapObjto its
equivalent type if one exists (it does not always, but it does in the
cases where there is an equivalent type built into Python).GapList.python()andGapRecord.python()also recursively convert
the values they contain to equivalent Python types if possible.New interface for registering converters to/from GAP object types:Gap.register_converteris replaced with theGap.convert_fromdecorator.TheGapObj.convert_todecorator can be used to register new
conversion methods onGapObj, or specific subclasses thereof.Added some C-level utility methods onGapIntegerto help convert to
different integer types (C long ints and mpz_t, depending on the size of
the int).  This helps with more efficient conversion to Sage Integers
without having to pass through an intermediary Pythonint.Implemented the__invert__and__neg__magic methods forGapObj.Implemented a default__bool__for allGapObjwhich returnsFalseif its value is equal to zero.Install the.pyxsources so that Cython tracebacks can work better.Bug fixesWhen converting aGapRecordto adictwithdict(rec)the
keys remain asGapStringinstead ofstr.  This is more consistent
with the fact that the values are not converted to Python equivalents.If an arbitrary GAP error occurs while looking up a global variable withGap.__getattr__it is handled and re-raised as anAttributeError.TheGap.__repr__method displays names of subclasses correctly.v0.1.0a2 (2021-02-03)Bug fixesMade fixes for MacOS and Cygwin support.v0.1.0a1 (2021-02-03)EnhancementsAdded LRU cache for functions defined withgap.gap_functions,
restoring some of the caching functionality from Sage’sGap.function_factory.Bug fixesFixed bug in multi-indexing of nested lists.Fixed minor formatting difference in the IndexError message when indexing
single lists versus multi-indexing nested lists.Fixed a bug when using functions defined withgap.gap_functionas
arguments to another GAP function before they have been called once.v0.1.0a0 (2021-01-26)Initial alpha release for testing against SageMath.