From dce3393bfcd9f275e9255e505e213dcba121b7cf Mon Sep 17 00:00:00 2001 From: jpawlowski Date: Thu, 14 Mar 2019 00:45:06 +0000 Subject: [PATCH] 98_Installer: add rudimentary visibility for nodejs and python dependencies git-svn-id: https://svn.fhem.de/fhem/trunk@18892 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/42_npmjs.pm | 12 ++ fhem/FHEM/98_Installer.pm | 287 +++++++++++++++++++++++++++++++++++++- fhem/FHEM/Meta.pm | 94 ++----------- 3 files changed, 303 insertions(+), 90 deletions(-) diff --git a/fhem/FHEM/42_npmjs.pm b/fhem/FHEM/42_npmjs.pm index 7ae6c6a8e..007ac8d51 100644 --- a/fhem/FHEM/42_npmjs.pm +++ b/fhem/FHEM/42_npmjs.pm @@ -1778,6 +1778,18 @@ sub ToDay() { } } }, + "x_prereqs_nodejs": { + "runtime": { + "requires": { + "node": 8.0, + "npm": 0 + }, + "recommends": { + }, + "suggests": { + } + } + }, "x_prereqs_binary_exec": { "runtime": { "requires": { diff --git a/fhem/FHEM/98_Installer.pm b/fhem/FHEM/98_Installer.pm index 13547357a..f06a077f4 100644 --- a/fhem/FHEM/98_Installer.pm +++ b/fhem/FHEM/98_Installer.pm @@ -217,7 +217,8 @@ my @perlCoreModules = qw( BEGIN { # Import from main:: GP_Import( - qw(readingsSingleUpdate + qw( + readingsSingleUpdate readingsBulkUpdate readingsBulkUpdateIfChanged readingsBeginUpdate @@ -239,10 +240,20 @@ BEGIN { init_done gettimeofday InternalTimer - RemoveInternalTimer) + RemoveInternalTimer + LoadModule + ) ); } +# Load dependent FHEM modules as packages, +# no matter if user also defined FHEM devices or not. +# We want to use their functions here :-) +#TODO let this make Meta.pm for me +#LoadModule('apt'); +#LoadModule('pypip'); +LoadModule('npmjs'); + sub Define($$) { my ( $hash, $def ) = @_; my @a = split( "[ \t][ \t]*", $def ); @@ -1175,6 +1186,7 @@ sub CreateMetadataList ($$$) { $l .= $colOpenMinWidth . $txtOpen . $mAttrName . $txtClose . $colClose; + # these attributes do not exist under that name in META.json if ( !defined( $modMeta->{$mAttr} ) ) { $l .= $colOpen; @@ -1381,14 +1393,25 @@ sub CreateMetadataList ($$$) { : ( $modMeta->{resources}{bugtracker}{web} =~ m/^(?:https?:\/\/)?forum\.fhem\.de/i ? 'FHEM Forum' - : '' + : ( + $modMeta->{resources}{bugtracker}{web} =~ + m/^(?:https?:\/\/)?github\.com\/fhem/i + ? 'Github Issues: ' . $modMeta->{name} + : $modMeta->{resources}{bugtracker}{web} + ) ); + # add prefix if user defined title $title = 'FHEM Forum: ' . $title if ( $title ne '' && $title !~ m/^FHEM Forum/i && $modMeta->{resources}{bugtracker}{web} =~ m/^(?:https?:\/\/)?forum\.fhem\.de/i ); + $title = 'Github Issues: ' . $title + if ( $title ne '' + && $title !~ m/^Github issues/i + && $modMeta->{resources}{bugtracker}{web} =~ + m/^(?:https?:\/\/)?github\.com\/fhem/i ); $l .= '' + . $prereq . '' + if ($html); + + $l .= + $colOpenMinWidth + . $prereq + . ( $version ne '' ? " ($version)" : '' ) + . $colClose; + $l .= $colOpenMinWidth . $importance . $colClose; + $l .= $colOpenMinWidth . $installed . $colClose; + + $l .= $rowClose; + + push @ret, $l; + $linecount++; + } + } + + push @ret, $tableClose; + + } + + if ( defined( $modMeta->{x_prereqs_python} ) + && defined( $modMeta->{x_prereqs_python}{runtime} ) ) + { + push @ret, '

Python Packages

'; + + my @mAttrs = qw( + requires + recommends + suggests + ); + + push @ret, $tableOpen; + + push @ret, $colOpenMinWidth . $txtOpen . 'Name' . $txtClose . $colClose; + + push @ret, + $colOpenMinWidth . $txtOpen . 'Importance' . $txtClose . $colClose; + + push @ret, + $colOpenMinWidth . $txtOpen . 'Status' . $txtClose . $colClose; + + my $linecount = 1; + foreach my $mAttr (@mAttrs) { + next + unless ( defined( $modMeta->{x_prereqs_python}{runtime}{$mAttr} ) + && keys %{ $modMeta->{x_prereqs_python}{runtime}{$mAttr} } > + 0 ); + + foreach my $prereq ( + sort keys %{ $modMeta->{x_prereqs_python}{runtime}{$mAttr} } ) + { + my $l = $linecount % 2 == 0 ? $rowOpenEven : $rowOpenOdd; + + my $importance = $mAttr; + $importance = 'required' if ( $mAttr eq 'requires' ); + $importance = 'recommended' if ( $mAttr eq 'recommends' ); + $importance = 'suggested' if ( $mAttr eq 'suggests' ); + + my $version = + $modMeta->{x_prereqs_python}{runtime}{$mAttr}{$prereq}; + $version = '' if ( !defined($version) || $version eq '0' ); + + my $check = __IsInstalledPython($prereq); + my $installed = ''; + if ($check) { + if ( $check =~ m/^\d+\./ ) { + my $nverReq = + $version ne '' + ? $version + : 0; + my $nverInst = $check; + + #TODO suport for version range: + #https://metacpan.org/pod/CPAN::Meta::Spec#Version-Range + if ( $nverReq > 0 && $nverInst < $nverReq ) { + $installed .= + $colorRed + . 'OUTDATED' + . $colorClose . ' (' + . $check . ')'; + } + else { + $installed = 'installed'; + } + } + else { + $installed = 'installed'; + } + } + else { + $installed = $colorRed . 'MISSING' . $colorClose + if ( $importance eq 'required' ); + } + + my $isPerlPragma = ModuleIsPerlPragma($prereq); + my $isPerlCore = $isPerlPragma ? 0 : ModuleIsPerlCore($prereq); + my $isFhem = + $isPerlPragma || $isPerlCore ? 0 : ModuleIsInternal($prereq); + if ( $isPerlPragma || $isPerlCore || $prereq eq 'perl' ) { + $installed = + $installed ne 'installed' + ? "$installed (Perl built-in)" + : 'built-in'; + } + elsif ($isFhem) { + $installed = + $installed ne 'installed' + ? "$installed (FHEM included)" + : 'included'; + } + elsif ( $installed eq 'installed' ) { + $installed = $colorGreen . $installed . $colorClose; + } + + $prereq = + '' + . $prereq . '' + if ( $html + && !$isFhem + && !$isPerlCore + && !$isPerlPragma + && $prereq ne 'perl' ); + + $l .= + $colOpenMinWidth + . $prereq + . ( $version ne '' ? " ($version)" : '' ) + . $colClose; + $l .= $colOpenMinWidth . $importance . $colClose; + $l .= $colOpenMinWidth . $installed . $colClose; + + $l .= $rowClose; + + push @ret, $l; + $linecount++; + } + } + + push @ret, $tableClose; + + } + push @ret, 'Based on data generated by ' . $modMeta->{generated_by}; return $header . join( "\n", @ret ) . $footer; @@ -1865,6 +2120,24 @@ sub __IsInstalledPerl($) { } } +# Checks whether a NodeJS package is installed in the system +sub __IsInstalledNodejs($) { + return 0 unless ( __PACKAGE__ eq caller(0) ); + return 0 unless (@_); + my ($pkg) = @_; + + return 0; +} + +# Checks whether a Python package is installed in the system +sub __IsInstalledPython($) { + return 0 unless ( __PACKAGE__ eq caller(0) ); + return 0 unless (@_); + my ($pkg) = @_; + + return 0; +} + sub ModuleIsPerlCore { my ($module) = @_; return grep ( /^$module$/, @perlCoreModules ) @@ -2050,7 +2323,8 @@ sub ToDay() { "HttpUtils": 0, "File::stat": 0, "Encode": 0, - "version": 0 + "version": 0, + "FHEM::npmjs": 0 }, "recommends": { "Perl::PrereqScanner::NotQuiteLite": 0, @@ -2062,8 +2336,7 @@ sub ToDay() { }, "resources": { "bugtracker": { - "web": "https://forum.fhem.de/index.php/board,44.0.html", - "x_web_title": "FHEM Forum: Unterstützende Dienste" + "web": "https://github.com/fhem/Installer/issues" } } } diff --git a/fhem/FHEM/Meta.pm b/fhem/FHEM/Meta.pm index 9933c0467..0adbc5c01 100644 --- a/fhem/FHEM/Meta.pm +++ b/fhem/FHEM/Meta.pm @@ -362,7 +362,15 @@ sub import(@) { __GetUpdatedata() unless ( defined($coreUpdate) ); __GetMaintainerdata() unless ( keys %moduleMaintainers > 0 ); - if ( $pkg ne "main" ) { + #TODO Export a function to main context so that + # a device may use metadata to load Perl dependencies from META.json. + # This will provide a central place to maintain module dependencies + # w/o source code analysis. + if ( $pkg eq "main" ) { + } + + # Not sure yet what else could be done by just loading the module + else { } } @@ -1721,26 +1729,6 @@ sub __SetXVersion { } } }, - "x_prereqs_nodejs": { - "runtime": { - "requires": { - }, - "recommends": { - }, - "suggests": { - } - } - }, - "x_prereqs_python": { - "runtime": { - "requires": { - }, - "recommends": { - }, - "suggests": { - } - } - }, "x_prereqs_binary_exec": { "runtime": { "requires": { @@ -1793,11 +1781,11 @@ sub __SetXVersion { =for :application/json;q=META.json fhem.pl { "abstract": "FHEM® is a Perl server for house automation", - "description": "FHEM® (registered trademark) is a GPL'd perl server for house automation. It is used to automate some common tasks in the household like switching lamps / shutters / heating / etc. and to log events like temperature / humidity / power consumption.\\n\\nThe program runs as a server, you can control it via web or smartphone frontends, telnet or TCP/IP directly.\\n\\nIn order to use FHEM you'll need a 24/7 server (NAS, RPi, PC, MacMini, etc) with a perl interpreter and some attached hardware like the CUL-, EnOcean-, Z-Wave-USB-Stick, etc. to access the actors and sensors.\\n\\nIt is pronounced without the h, like in feminine.", + "description": "FHEM® (registered trademark) is a GPL'd Perl server for house automation. It is used to automate some common tasks in the household like switching lamps / shutters / heating / etc. and to log events like temperature / humidity / power consumption.\\n\\nThe program runs as a server, you can control it via web or smartphone frontends, telnet or TCP/IP directly.\\n\\nIn order to use FHEM you'll need a 24/7 server (NAS, RPi, PC, Mac Mini, etc.) with a Perl interpreter and some attached hardware like the CUL-, EnOcean-, Z-Wave-USB-Stick, etc. to access the actors and sensors.\\n\\nIt is pronounced without the h, like in feminine.", "x_lang": { "de": { "abstract": "FHEM® ist ein Perl Server zur Hausautomatisierung", - "description": "FHEM® (eingetragene Marke) ist ein in Perl geschriebener, GPL lizensierter Server für die Heimautomatisierung. Man kann mit FHEM häufig auftretende Aufgaben automatisieren, wie z.Bsp. Lampen / Rollladen / Heizung / usw. schalten, oder Ereignisse wie Temperatur / Feuchtigkeit / Stromverbrauch protokollieren und visualisieren.\\n\\nDas Programm läuft als Server, man kann es über WEB, dedizierte Smartphone Apps oder telnet bedienen, TCP Schnittstellen für JSON und XML existieren ebenfalls.\\n\\nUm es zu verwenden benötigt man einen 24/7 Rechner (NAS, RPi, PC, MacMini, etc) mit einem Perl Interpreter und angeschlossene Hardware-Komponenten wie CUL-, EnOcean-, Z-Wave-USB-Stick, etc. für einen Zugang zu den Aktoren und Sensoren.\\n\\nAusgesprochen wird es ohne h, wie bei feminin." + "description": "FHEM® (eingetragene Marke) ist ein in Perl geschriebener, GPL lizensierter Server für die Heimautomatisierung. Man kann mit FHEM häufig auftretende Aufgaben automatisieren, wie z.Bsp. Lampen / Rollladen / Heizung / usw. schalten, oder Ereignisse wie Temperatur / Feuchtigkeit / Stromverbrauch protokollieren und visualisieren.\\n\\nDas Programm läuft als Server, man kann es über WEB, dedizierte Smartphone Apps oder telnet bedienen, TCP Schnittstellen für JSON und XML existieren ebenfalls.\\n\\nUm es zu verwenden benötigt man einen 24/7 Rechner (NAS, RPi, PC, Mac Mini, etc.) mit einem Perl Interpreter und angeschlossene Hardware-Komponenten wie CUL-, EnOcean-, Z-Wave-USB-Stick, etc. für einen Zugang zu den Aktoren und Sensoren.\\n\\nAusgesprochen wird es ohne h, wie bei feminin." } }, "keywords": [ @@ -1905,66 +1893,6 @@ sub __SetXVersion { } } }, - "x_prereqs_nodejs": { - "runtime": { - "requires": { - }, - "recommends": { - }, - "suggests": { - } - } - }, - "x_prereqs_python": { - "runtime": { - "requires": { - }, - "recommends": { - }, - "suggests": { - } - } - }, - "x_prereqs_binary_exec": { - "runtime": { - "requires": { - }, - "recommends": { - }, - "suggests": { - } - } - }, - "x_prereqs_sudo": { - "runtime": { - "requires": { - }, - "recommends": { - }, - "suggests": { - } - } - }, - "x_prereqs_permissions_fileown": { - "runtime": { - "requires": { - }, - "recommends": { - }, - "suggests": { - } - } - }, - "x_prereqs_permissions_filemod": { - "runtime": { - "requires": { - }, - "recommends": { - }, - "suggests": { - } - } - }, "resources": { "x_copyright": { "web": "https://verein.fhem.de/"