Recent

Author Topic: RANT: Python (it's not funny)  (Read 6340 times)

vfclists

  • Hero Member
  • *****
  • Posts: 1013
    • HowTos Considered Harmful?
Re: RANT: Python (it's not funny)
« Reply #15 on: February 02, 2021, 05:24:41 pm »
One of the problem Lazarus with its LCL GUI is that they don't have much support from scripting or embedded languages.

The only one I can think of is vclua and there is also Py4Delphi/Py4Lazarus.

Another is gabrielrcouto/php-gui] Extensionless PHP Graphic User Interface library (Github), which interfaces with the LCL over XM-RPC, or is that JSON.
Lazarus 3.0/FPC 3.2.2

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: RANT: Python (it's not funny)
« Reply #16 on: February 02, 2021, 07:16:30 pm »
I've been using something based on Meta-2 for this sort of thing for a /long/ time... I mean "long" as in "predating Delphi". Alternatively there's Lua, plus a couple of Python implementations (at least three if you count the one I've been hacking).

I've got Python2 running with both static and dynamic linkage, although I've only transcribed enough of the API to do /exactly/ what I need so far. Organising it so that Python can call back into the Lazarus runtimes looks as though it will be pretty easy.

The .inc file I've edited to contain the API declarations and comments describing each function comes to about 300K, Lazarus picks the descriptions up properly as hover-over hints. Much as I loathe Python's syntax, its documentation is pretty good with notes of when functions were introduced and had major changes.

Code: Pascal  [Select][+][-]
  1. program PythonDemo;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. { define DYNAMIC }
  6. {$define PYTHON2 }
  7.  
  8. (* Assume that there is only superficial similarity between the Python v2 and   *)
  9. (* v3 script syntax and semantics. This demo is, more than anything else, the   *)
  10. (* "point of contact" between the various implementation possibilities at the   *)
  11. (* time of development.                                                         *)
  12.  
  13. {$ifdef PYTHON2 }
  14. {$unitpath ./python2 }
  15. {$note ===== Intending to link to Python v2 ===== }
  16. {$else          }
  17. {$unitpath ./python3 }
  18. {$note ===== Intending to link to Python v3 ===== }
  19. {$endif PYTHON2 }
  20.  
  21. (* WARNING: since the unit path is being set up during compilation, Lazarus's   *)
  22. (* build facility might not successfully retire unwanted files. If in doubt do  *)
  23. (* a "Clean directory".                                                         *)
  24.  
  25. uses
  26.   {$IFDEF UNIX}
  27.   cthreads,
  28.   {$ENDIF}
  29.   Classes,
  30. {$ifdef DYNAMIC }
  31.   python_dynamic;                       (* "Python" is a shared-library object  *)
  32. {$note ===== Intending to link dynamically ===== }
  33. {$else          }
  34.   python;                               (* "Python" is a unit file              *)
  35. {$note ===== Intending to link statically ===== }
  36. {$endif DYNAMIC }
  37.  
  38. var
  39.   localArgv: array of PChar;
  40.   debugging: boolean= false;
  41.  
  42.  
  43. (* Generate an array of pointers from the flat block of null-terminated strings,
  44.   excluding the --DEBUG-- option which is handled specially.
  45.  
  46.   This is temporary, and should be moved to the Python unit/object even if it's
  47.   not handled automatically.
  48. *)
  49. procedure initArgv;
  50.  
  51. var
  52.   i, j: integer;
  53.  
  54. begin
  55.   SetLength(localArgv, 1);
  56.   localArgv[0] := System.Argv^;         (* Program name                         *)
  57.   j := 1;
  58.   for i := 1 to ParamCount() do
  59.     if ParamStr(i) = '--DEBUG--' then
  60.       debugging := true
  61.     else begin
  62.       SetLength(localArgv, j + 1);
  63.       localArgv[j] := localArgv[i - 1] + StrLen(localArgv[i - 1]) + 1;
  64.       j += 1
  65.     end
  66. end { initArgv } ;
  67.  
  68.  
  69. begin
  70.   InitializeLibrary;                    (* Ensures Python.ModuleInMemory valid  *)
  71.   if Python.IsDynamic then
  72.     Write('Python is dynamically linked, ')
  73.   else
  74.     Write('Python is statically linked, ');
  75.   if Python.ModuleInMemory then
  76.     Write('and has ')
  77.   else
  78.     Write('but has not ');
  79.   WriteLn('been successfully loaded.');
  80.   initArgv;                             (* localArgv and debugging flag         *)
  81.   if debugging then
  82.     WriteLn('Debugging is enabled.');   (* Special --DEBUG-- option             *)
  83.  
  84. (* Report Python version etc., this calls into libpython but does not rely on   *)
  85. (* script execution. Note that while Py_SetProgramName() has to be called       *)
  86. (* before Py_Initialize in order to set up internal paths etc., PySys_SetArgv() *)
  87. (* has to be called afterwards.                                                 *)
  88.  
  89.   WriteLn(StrPas(Python.Py_GetVersion()));
  90.   Python.Py_SetProgramName(PChar(ParamStr(0))); (* Before _Initialize           *)
  91.  
  92. (* Initialise the embedded Python implementation and run the traditional        *)
  93. (* trivial script. For the moment at least, expect output to go to the console. *)
  94.  
  95.   Python.Py_Initialize;
  96.   try
  97. //    Py_InitModule("emb", EmbMethods);   // emb would be part of this Pascal program
  98.     Python.PySys_SetArgv(Length(localArgv), @localArgv[0]);
  99.     Python.PyRun_SimpleString(
  100.         'import sys' + LineEnding +     (* Just to check EOL convention         *)
  101.         'print(sys.argv[0:])' + LineEnding +
  102.         'print("Hello, World!")' + LineEnding
  103.     );
  104.   finally
  105.     Python.Py_Finalize
  106.   end
  107. end.
  108.  

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

vfclists

  • Hero Member
  • *****
  • Posts: 1013
    • HowTos Considered Harmful?
Re: RANT: Python (it's not funny)
« Reply #17 on: February 03, 2021, 12:59:52 am »
I've been using something based on Meta-2 for this sort of thing for a /long/ time... I mean "long" as in "predating Delphi". Alternatively there's Lua, plus a couple of Python implementations (at least three if you count the one I've been hacking).

I've got Python2 running with both static and dynamic linkage, although I've only transcribed enough of the API to do /exactly/ what I need so far. Organising it so that Python can call back into the Lazarus runtimes looks as though it will be pretty easy.

The .inc file I've edited to contain the API declarations and comments describing each function comes to about 300K, Lazarus picks the descriptions up properly as hover-over hints. Much as I loathe Python's syntax, its documentation is pretty good with notes of when functions were introduced and had major changes.

Code: Pascal  [Select][+][-]
  1. program PythonDemo;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. <snip>
  6.   finally
  7.     Python.Py_Finalize
  8.   end
  9. end.
  10.  

MarkMLl

So the code above enables Python 2 execution from within Lazarus, but how about calling Lazarus LCL functions from Python?

Does that require Lazarus to export its functionality as DLLs, or a special build of Python that is linked with some Lazarus obj or DLL?
Lazarus 3.0/FPC 3.2.2

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: RANT: Python (it's not funny)
« Reply #18 on: February 03, 2021, 08:43:56 am »
So the code above enables Python 2 execution from within Lazarus, but how about calling Lazarus LCL functions from Python?

Does that require Lazarus to export its functionality as DLLs, or a special build of Python that is linked with some Lazarus obj or DLL?

I'm using a standard build of Python, linked either statically or dynamically.

Code: [Select]
//    Py_InitModule("emb", EmbMethods);   // emb would be part of this Pascal program

That's the magic line, hence https://docs.python.org/3/extending/embedding.html section 1.4.

In practical terms, anything that the LCL etc. wanted to export would need to be wrapped in a function of the appropriate form, and the Python runtimes advised of it. Once that was done a Python program could call the LCL or whatever via the emb module.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5469
  • Compiler Developer
Re: RANT: Python (it's not funny)
« Reply #19 on: February 03, 2021, 09:59:04 am »
So the code above enables Python 2 execution from within Lazarus, but how about calling Lazarus LCL functions from Python?

Does that require Lazarus to export its functionality as DLLs, or a special build of Python that is linked with some Lazarus obj or DLL?

Python4Delphi provides various wrapper classes that provide access to the VCL for Python scripts. I don't know if these units are yet tested with FPC/Lazarus, but in theory they should work as well. And I think there is a general wrapper that uses published properties thus any published property can be used as well as long as you tell Python4Delphi about that type.

In addition to that the Extended RTTI (which FPC does not yet provide) could be used in theory to automatically provide access to types and their fields/methods/properties though of course a corresponding wrapper code needs to be written first (one needs to be careful with smartlinking then however).

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: RANT: Python (it's not funny)
« Reply #20 on: February 03, 2021, 10:07:19 am »
Python4Delphi provides various wrapper classes that provide access to the VCL for Python scripts. I don't know if these units are yet tested with FPC/Lazarus, but in theory they should work as well. And I think there is a general wrapper that uses published properties thus any published property can be used as well as long as you tell Python4Delphi about that type.

Yes, there's a variant that works with FPC but it's walked away from Python2 which is what I need for the moment (as per OP, I've got some Python which doesn't work properly and I want to find out why without getting embroiled in converting the whole damn thing to v3). So I'm taking this opportunity to repackage.

I'd also observe that there is a tendency for Delphi... no, I /am/ going to say "Object Pascal" here... programmers to be excessively clever and wrap a whole lot of stuff in classes etc. simply because doing so suggests elegance. That can be extremely counter-productive, since the result bears absolutely no resemblance to the examples published and used as foundation works by the non-Pascal community. So what I put in the example I posted yesterday was very much a line-by-line transcript of what a C/C++ programmer approaching embedded Python would find, and I intend to keep it that way.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5469
  • Compiler Developer
Re: RANT: Python (it's not funny)
« Reply #21 on: February 03, 2021, 01:24:42 pm »
Python4Delphi provides various wrapper classes that provide access to the VCL for Python scripts. I don't know if these units are yet tested with FPC/Lazarus, but in theory they should work as well. And I think there is a general wrapper that uses published properties thus any published property can be used as well as long as you tell Python4Delphi about that type.

Yes, there's a variant that works with FPC but it's walked away from Python2 which is what I need for the moment (as per OP, I've got some Python which doesn't work properly and I want to find out why without getting embroiled in converting the whole damn thing to v3). So I'm taking this opportunity to repackage.

My answer was mainly to vfclists as I'm already aware that you also use Python 2 (though one could fork Python4Delphi before this commit from middle of October).

I'd also observe that there is a tendency for Delphi... no, I /am/ going to say "Object Pascal" here... programmers to be excessively clever and wrap a whole lot of stuff in classes etc. simply because doing so suggests elegance. That can be extremely counter-productive, since the result bears absolutely no resemblance to the examples published and used as foundation works by the non-Pascal community. So what I put in the example I posted yesterday was very much a line-by-line transcript of what a C/C++ programmer approaching embedded Python would find, and I intend to keep it that way.

I don't agree here. A point that Delphi makes is convenient access for various functionality. Think about COM which is more a hazzle in (plain) C++, but which Delphi did in a rather strong way that even the C++ devs were envious back then. Similar for Python4Delphi: I most cases I won't even need the C tutorials. (And when I had first looked at Python4Delphi around 15 years ago I had no clue about C, so that wouldn't have helped me anyway)
« Last Edit: February 03, 2021, 01:26:27 pm by PascalDragon »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: RANT: Python (it's not funny)
« Reply #22 on: February 03, 2021, 01:35:39 pm »
Yes, I'm working from the October version.

I'd also observe that there is a tendency for Delphi... no, I /am/ going to say "Object Pascal" here... programmers to be excessively clever and wrap a whole lot of stuff in classes etc. simply because doing so suggests elegance. That can be extremely counter-productive, since the result bears absolutely no resemblance to the examples published and used as foundation works by the non-Pascal community. So what I put in the example I posted yesterday was very much a line-by-line transcript of what a C/C++ programmer approaching embedded Python would find, and I intend to keep it that way.

I don't agree here. A point that Delphi makes is convenient access for various functionality. Think about COM which is more a hazzle in (plain) C++, but which Delphi did in a rather strong way that even the C++ devs were envious back then. Similar for Python4Delphi: I most cases I won't even need the C tutorials. (And when I had first looked at Python4Delphi around 15 years ago I had no clue about C, so that wouldn't have helped me anyway)

In that case we'll have to agree to disagree. Oh, BTW: are you of the opinion that documentation should be written in Loglan because of its elegance and precision? :-)

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5469
  • Compiler Developer
Re: RANT: Python (it's not funny)
« Reply #23 on: February 04, 2021, 09:15:12 am »
I'd also observe that there is a tendency for Delphi... no, I /am/ going to say "Object Pascal" here... programmers to be excessively clever and wrap a whole lot of stuff in classes etc. simply because doing so suggests elegance. That can be extremely counter-productive, since the result bears absolutely no resemblance to the examples published and used as foundation works by the non-Pascal community. So what I put in the example I posted yesterday was very much a line-by-line transcript of what a C/C++ programmer approaching embedded Python would find, and I intend to keep it that way.

I don't agree here. A point that Delphi makes is convenient access for various functionality. Think about COM which is more a hazzle in (plain) C++, but which Delphi did in a rather strong way that even the C++ devs were envious back then. Similar for Python4Delphi: I most cases I won't even need the C tutorials. (And when I had first looked at Python4Delphi around 15 years ago I had no clue about C, so that wouldn't have helped me anyway)

In that case we'll have to agree to disagree. Oh, BTW: are you of the opinion that documentation should be written in Loglan because of its elegance and precision? :-)

I have no idea what Loglan is. And like most everything documentation should be written in whatever is the most useful and convenient.

dsiders

  • Hero Member
  • *****
  • Posts: 1080
Re: RANT: Python (it's not funny)
« Reply #24 on: February 04, 2021, 07:33:12 pm »
I have no idea what Loglan is. And like most everything documentation should be written in whatever is the most useful and convenient.

Think Esperanto for the criminally insane.
Preview Lazarus 3.99 documentation at: https://dsiders.gitlab.io/lazdocsnext

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: RANT: Python (it's not funny)
« Reply #25 on: February 17, 2021, 09:54:46 am »
I've got Python2 running with both static and dynamic linkage, although I've only transcribed enough of the API to do /exactly/ what I need so far. Organising it so that Python can call back into the Lazarus runtimes looks as though it will be pretty easy.

The .inc file I've edited to contain the API declarations and comments describing each function comes to about 300K, Lazarus picks the descriptions up properly as hover-over hints. Much as I loathe Python's syntax, its documentation is pretty good with notes of when functions were introduced and had major changes.

I'm now at the point where I've got a single .inc file describing the bulk of the Python v2.7 API plus a preprocessor which generates unit files from it: one for a static interface to an external library and another for a dynamic on-demand interface. No manual tweaks are necessary, any locally-defined functions (usually standing in for a C/C++ macro) go into another .inc file which is pulled in automatically if it exists.

A program calling this interface sees either a unit (python.pas) or an object in a unit (TPython in python_dynamic.pas) and is unchanged irrespective of the type of linkage.

I intend to extend this to replace some extremely cruddy UI stuff (hence the tenor of the start of this thread) and support Python debugging.

I've got a problem relating to functions marked as varargs which I'll raise in a separate thread. I'm not sure whether I need them but my eventual aim is to support the entire documented Python API, Python4Delphi is not at all complete.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018