Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HPCC-30721 Fix Python examples to use Python3 #17989

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions initfiles/examples/embed/python-catch.ecl
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
IMPORT Python;
IMPORT Python3 AS Python;

/*
This example illustrates and tests the use of embedded Python
*/

// Mapping of exceptions from Python to ECL

integer testThrow(integer val) := EMBED(Python)
raise Exception('Error from Python')
INTEGER testThrow(integer val) := EMBED(Python)
raise Exception('Error from Python')
ENDEMBED;

// Can't catch an expression(only a dataset)
d := dataset([{ 1, '' }], { integer a, string m} ) : stored('nofold');
d := DATASET([{ 1, '' }], { INTEGER a, STRING m} ) : STORED('nofold');

d t := transform
d t := TRANSFORM
self.a := FAILCODE;
self.m := FAILMESSAGE;
self := [];
end;

catch(d(testThrow(a) = a), onfail(t));
CATCH(d(testThrow(a) = a), onfail(t));
2 changes: 1 addition & 1 deletion initfiles/examples/embed/python-import.ecl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
IMPORT python;
IMPORT Python3 AS Python;

/*
This example illustrates a call to a Python functions defined in the Python module python_cat.py
Expand Down
72 changes: 36 additions & 36 deletions initfiles/examples/embed/python-simple.ecl
Original file line number Diff line number Diff line change
@@ -1,80 +1,80 @@
IMPORT Python;
IMPORT Python3 AS Python;

/*
This example illustrates and tests the use of embedded Python
*/

// Scalar parameters and resuls

integer add1(integer val) := EMBED(Python)
val+1
INTEGER add1(INTEGER val) := EMBED(Python)
val+1
ENDEMBED;

string add2(string val) := EMBED(Python)
val+'1'
STRING add2(STRING val) := EMBED(Python)
val+'1'
ENDEMBED;

string add3(varstring val) := EMBED(Python)
val+'1'
STRING add3(VARSTRING val) := EMBED(Python)
val+'1'
ENDEMBED;

utf8 add4(utf8 val) := EMBED(Python)
val+'1'
UTF8 add4(UTF8 val) := EMBED(Python)
val+'1'
ENDEMBED;

unicode add5(unicode val) := EMBED(Python)
val+'1'
UNICODE add5(UNICODE val) := EMBED(Python)
val+'1'
ENDEMBED;

utf8 add6(utf8 val) := EMBED(Python)
return val+'1'
UTF8 add6(UTF8 val) := EMBED(Python)
return val+'1'
ENDEMBED;

unicode add7(unicode val) := EMBED(Python)
return val+'1'
UNICODE add7(UNICODE val) := EMBED(Python)
return val+'1'
ENDEMBED;

data testData(data val) := EMBED(Python)
val[0] = val[0] + 1
return val
DATA testData(DATA val) := EMBED(Python)
val[0] = val[0] + 1
return val
ENDEMBED;

// Sets in ECL map to Python lists

set of integer testSet(set of integer val) := EMBED(Python)
return sorted(val)
SET OF INTEGER testSet(SET OF INTEGER val) := EMBED(Python)
return sorted(val)
ENDEMBED;

set of string testSet2(set of string val) := EMBED(Python)
return sorted(val)
SET OF STRING testSet2(SET OF STRING val) := EMBED(Python)
return sorted(val)
ENDEMBED;

set of string testSet3(set of string8 val) := EMBED(Python)
return sorted(val)
SET OF STRING testSet3(SET OF STRING8 val) := EMBED(Python)
return sorted(val)
ENDEMBED;

set of utf8 testSet4(set of utf8 val) := EMBED(Python)
return sorted(val)
SET OF UTF8 testSet4(SET OF UTF8 val) := EMBED(Python)
return sorted(val)
ENDEMBED;

set of varstring testSet5(set of varstring val) := EMBED(Python)
return sorted(val)
SET OF VARSTRING testSet5(SET OF VARSTRING val) := EMBED(Python)
return sorted(val)
ENDEMBED;

set of varstring8 testSet6(set of varstring8 val) := EMBED(Python)
return sorted(val)
SET OF VARSTRING8 testSet6(SET OF VARSTRING8 val) := EMBED(Python)
return sorted(val)
ENDEMBED;

set of unicode testSet7(set of unicode val) := EMBED(Python)
return sorted(val)
SET OF UNICODE testSet7(SET OF UNICODE val) := EMBED(Python)
return sorted(val)
ENDEMBED;

set of unicode8 testSet8(set of unicode8 val) := EMBED(Python)
return sorted(val)
SET OF UNICODE8 testSet8(SET OF UNICODE8 val) := EMBED(Python)
return sorted(val)
ENDEMBED;

set of data testSet9(set of data val) := EMBED(Python)
return val
SET OF DATA testSet9(SET OF DATA val) := EMBED(Python)
return val
ENDEMBED;

// Now run the tests
Expand Down
4 changes: 2 additions & 2 deletions initfiles/examples/embed/python-simple2.ecl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import python;
IMPORT Python3 AS Python;
/*
This example illustrates and tests the use of embedded Python.
In this example the python that is embedded is more complex, including a definition of a function
*/


string anagram(string word) := EMBED(Python)
STRING anagram(string word) := EMBED(Python)
def anagram(w):
if word == 'cat':
return 'act'
Expand Down
54 changes: 27 additions & 27 deletions initfiles/examples/embed/python-stream.ecl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
IMPORT Python;
IMPORT Python3 AS Python;

/*
This example illustrates and tests the use of embedded Python.
Expand All @@ -9,17 +9,17 @@ IMPORT Python;
// These are the record structures we will be returning - note the child records, datasets and dictionaries in it

childrec := RECORD
string name => unsigned value;
STRING name => UNSIGNED value;
END;

eclRecord := RECORD
STRING name1;
STRING10 name2;
LINKCOUNTED DATASET(childrec) childnames;
LINKCOUNTED DICTIONARY(childrec) childdict{linkcounted};
LINKCOUNTED DICTIONARY(childrec) childdict{LINKCOUNTED};
childrec r;
unsigned1 val1;
integer1 val2;
UNSIGNED1 val1;
INTEGER1 val2;
UTF8 u1;
UNICODE u2;
UNICODE8 u3;
Expand All @@ -30,103 +30,103 @@ eclRecord := RECORD
END;

namerec := RECORD
string name;
STRING name;
END;

namerec2 := RECORD
string name;
string name2;
STRING name;
STRING name2;
END;

// To return a dataset, we can return a list of tuples, each one correponding to a field in the resulting ECL record
// In this example, the fields are mapped by position
// Just to spice things up we proved a couple of parameters too

dataset(eclRecord) streamedNames(data d, utf8 u) := EMBED(Python)
DATASET(eclRecord) streamedNames(DATA d, utf8 u) := EMBED(Python)
return [ \
("Gavin", "Halliday", [("a", 1),("b", 2),("c", 3)], [("aa", 11)], ("aaa", 111), 250, -1, U'là', U'là', U'là', 0x01000000, d, False, {"1","2"}), \
("John", "Smith", [], [], ("c", 3), 250, -1, U'là', U'là', u, 0x02000000, d, True, []) \
]
ENDEMBED;

output(streamedNames(d'AA', u'là'));
OUTPUT(streamedNames(d'AA', u'là'));

// We can also return a dataset by using a Python generator, which will be lazy-evaluated as the records are required by ECL code...

dataset(childrec) testGenerator(unsigned lim) := EMBED(Python)
DATASET(childrec) testGenerator(unsigned lim) := EMBED(Python)
num = 0
while num < lim:
yield ("Generated", num)
num += 1
ENDEMBED;

output (testGenerator(10));
OUTPUT (testGenerator(10));

// If the returned tuples are namedtuples, we map fields by name rather than by position

// Test use of Python named tuple...

dataset(childrec) testNamedTuples() := EMBED(Python)
DATASET(childrec) testNamedTuples() := EMBED(Python)
import collections
ChildRec = collections.namedtuple("childrec", "value, name") # Note - order is reverse of childrec - but works as we get fields by name
c1 = ChildRec(1, "name1")
c2 = ChildRec(name="name2", value=2)
return [ c1, c2 ]
ENDEMBED;

output(testNamedTuples());
OUTPUT(testNamedTuples());

// To return a record, just return a tuple (or namedtuple)

childrec testRecord(integer value, string s) := EMBED(Python)
return (s, value)
ENDEMBED;

output(testRecord(1,'Hello').value);
output(testRecord(1,'Hello').name);
OUTPUT(testRecord(1,'Hello').value);
OUTPUT(testRecord(1,'Hello').name);

// If the record has a single field, you don't need to put the field into a tuple...

dataset(namerec) testMissingTuple1(unsigned lim) := EMBED(Python)
DATASET(namerec) testMissingTuple1(unsigned lim) := EMBED(Python)
return [ '1', '2', '3' ]
ENDEMBED;
output (testMissingTuple1(10));
OUTPUT (testMissingTuple1(10));

// ... but you can if you want

dataset(namerec) testMissingTuple2(unsigned lim) := EMBED(Python)
DATASET(namerec) testMissingTuple2(unsigned lim) := EMBED(Python)
return [ ('1'), ('2'), ('3') ]
ENDEMBED;
output (testMissingTuple2(10));
OUTPUT (testMissingTuple2(10));

// You can define a transform in Python, using a function that returns a record (i.e. a Python tuple)
// Note that the tuple we pass to Python is a namedtuple

transform(childrec) testTransform(namerec inrec, unsigned c) := EMBED(Python)
TRANSFORM(childrec) testTransform(namerec inrec, unsigned c) := EMBED(Python)
return (inrec.name, c)
ENDEMBED;

d := dataset([{'Richard'},{'Gavin'}], namerec);
d := DATASET([{'Richard'},{'Gavin'}], namerec);

output(project(d, testTransform(LEFT, COUNTER)));
OUTPUT(PROJECT(d, testTransform(LEFT, COUNTER)));

// Most transforms take a record as the input, but it's not a requirement

transform(childrec) testTransformNoRow(unsigned lim) := EMBED(Python)
TRANSFORM(childrec) testTransformNoRow(unsigned lim) := EMBED(Python)
return ("Hello", lim)
ENDEMBED;

output(row(testTransformNoRow(10)));
OUTPUT(ROW(testTransformNoRow(10)));

// When passing datasets to Python, we get an iterator of named tuples
// They are actually implemented as generators, meaning they are lazy-evaluated

names := DATASET([{'Richard'}, {'James'}, {'Andrew'}], namerec);

string datasetAsIterator(dataset(namerec) input) := EMBED(Python)
STRING datasetAsIterator(DATASET(namerec) input) := EMBED(Python)
s = ''
for n in input:
s = s + ' ' + n.name
return s;
ENDEMBED;
output(datasetAsIterator(names));
OUTPUT(datasetAsIterator(names));
Loading