1
00:00:00,230 --> 00:00:01,230
Hey, welcome back.

2
00:00:01,250 --> 00:00:03,490
In this video, we're going to do two things.

3
00:00:03,500 --> 00:00:10,160
First, we're going to test this module, which is still a module, so it's not a package.

4
00:00:10,430 --> 00:00:16,040
And then the second thing we're going to do is we're going to convert this module into a package.

5
00:00:16,040 --> 00:00:23,240
So just to refresh your memory, the difference between a module and a package is that a module is one

6
00:00:23,240 --> 00:00:31,910
single.py file and a package is at least two files put inside a directory.

7
00:00:32,000 --> 00:00:33,830
So it's better to have a package.

8
00:00:33,830 --> 00:00:36,860
And I'll explain you why in the second part of this video.

9
00:00:36,860 --> 00:00:40,160
But for now let's test this module.

10
00:00:40,160 --> 00:00:44,420
So to test the module it means that it's simple.

11
00:00:44,420 --> 00:00:47,480
You just have to create a working file.

12
00:00:47,480 --> 00:00:48,620
So let's say.

13
00:00:49,550 --> 00:00:50,780
Main dot pi.

14
00:00:50,810 --> 00:00:56,030
So let's suppose that the user is using your module.

15
00:00:56,540 --> 00:01:02,780
So they create a file in their Pi charm directory and they want to import invoice.

16
00:01:03,410 --> 00:01:05,420
So that's how they would do this.

17
00:01:05,420 --> 00:01:11,780
Now, this works for now because invoice is in the same directory with main.py.

18
00:01:11,810 --> 00:01:12,530
Right.

19
00:01:12,800 --> 00:01:17,870
In a real scenario, the user would install invoice from pi.

20
00:01:17,900 --> 00:01:18,410
Pi.

21
00:01:19,160 --> 00:01:19,850
Right?

22
00:01:19,850 --> 00:01:22,280
And then they would import the same way.

23
00:01:22,730 --> 00:01:29,990
But for testing purposes we don't need to upload it to pi pi yet since we have it here.

24
00:01:29,990 --> 00:01:32,090
So import invoice and then.

25
00:01:34,430 --> 00:01:35,870
Invoice that generates.

26
00:01:36,530 --> 00:01:44,030
And now if the user don't know what to place inside here, you can hover the cursor here and it will

27
00:01:44,030 --> 00:01:45,860
tell you these parameters.

28
00:01:45,860 --> 00:01:53,720
Or alternatively you can open a python console import invoice here as well and just do help invoice

29
00:01:53,720 --> 00:02:00,020
dot generate and that will display you.

30
00:02:01,300 --> 00:02:03,400
The parameters of the function.

31
00:02:03,400 --> 00:02:06,720
So invoice path, pdf, path, etcetera.

32
00:02:06,760 --> 00:02:13,000
If we had a docstring which you can do so you can create here.

33
00:02:14,440 --> 00:02:18,050
A docstring like that, right?

34
00:02:18,490 --> 00:02:21,970
PyCharm automatically creates these.

35
00:02:22,240 --> 00:02:26,440
And then you can also add some extra information, such as?

36
00:02:27,430 --> 00:02:41,260
This function converts Excel files into or more accurately, invoice Excel files into PDF invoices.

37
00:02:44,050 --> 00:02:45,730
So save that.

38
00:02:45,760 --> 00:02:53,170
Now you need to close this console and open it again and do again import invoice.

39
00:02:53,170 --> 00:03:01,300
And if you do help invoice dot generate, you're going to get that doc string this time.

40
00:03:02,390 --> 00:03:05,990
As you can see there, and the parameters.

41
00:03:05,990 --> 00:03:14,120
So that's actual string is displayed in here, plus the generate function with its parameters.

42
00:03:14,660 --> 00:03:20,060
So now as a user, I can look at here and provide those arguments.

43
00:03:20,060 --> 00:03:25,280
So the first argument is the path where the Excel files are.

44
00:03:25,340 --> 00:03:33,350
And for that I'm going to create a new directory here, maybe name it invoices.

45
00:03:33,350 --> 00:03:37,700
And in that directory I'm going to paste those Excel files.

46
00:03:37,790 --> 00:03:39,230
I copied that earlier.

47
00:03:39,230 --> 00:03:44,300
You can find these Excel files attached in the previous video, but also in this video.

48
00:03:44,450 --> 00:03:48,410
So that folder contains these XLS files.

49
00:03:48,530 --> 00:03:58,400
And I'm going to just write here invoices, the name of the directory, the PDFs path directory.

50
00:03:58,700 --> 00:04:03,980
I'm going to create a directory for that as well, like output.

51
00:04:04,220 --> 00:04:09,500
Although we could improve this part by going to invoice and.

52
00:04:11,890 --> 00:04:13,810
Saying here that.

53
00:04:13,810 --> 00:04:26,140
So at the very end here, at the last two lines, we say if OS dot path, dot exists, PDFs, path,

54
00:04:27,010 --> 00:04:32,470
colon and then indent this actually it should be not if not.

55
00:04:33,270 --> 00:04:37,410
So if the path does not exist, we create it.

56
00:04:37,500 --> 00:04:38,270
Right.

57
00:04:38,280 --> 00:04:44,550
So that means the user doesn't need to create a output folder here.

58
00:04:44,580 --> 00:04:52,770
They just want to declare what name they want their new folder to have and Python will create it for

59
00:04:52,770 --> 00:04:53,340
them.

60
00:04:53,700 --> 00:05:01,890
If it doesn't exist, so then the image path, if you have an image, you can find a PNG image attached

61
00:05:01,890 --> 00:05:04,230
in the previous video or this one as well.

62
00:05:04,230 --> 00:05:09,630
And I want you to please paste that image in the root directory of the project.

63
00:05:09,870 --> 00:05:11,730
So here it is, Python.

64
00:05:11,730 --> 00:05:16,260
Hello, dot PNG in the root directory and I'm going to specify that name here.

65
00:05:16,260 --> 00:05:16,650
Python.

66
00:05:16,650 --> 00:05:17,220
Hello.

67
00:05:18,210 --> 00:05:20,430
Dot PNG.

68
00:05:22,000 --> 00:05:25,420
Then we want to specify the names of the columns.

69
00:05:25,630 --> 00:05:29,080
So for that we need to look at our Excel file.

70
00:05:29,080 --> 00:05:33,640
So product ID, product name in the given order product ID.

71
00:05:34,510 --> 00:05:37,420
I'll split this line here.

72
00:05:38,890 --> 00:05:41,230
Product Underscore Name.

73
00:05:45,140 --> 00:05:47,390
Then we have amount purchased.

74
00:05:53,410 --> 00:05:56,380
Then we have price per unit and total price.

75
00:05:56,560 --> 00:06:00,790
Price underscore per unit.

76
00:06:00,790 --> 00:06:01,570
And.

77
00:06:02,680 --> 00:06:04,270
Total price.

78
00:06:05,310 --> 00:06:07,230
So, yeah, that's it.

79
00:06:07,230 --> 00:06:12,180
That's about the arguments and that's how the user would use this library.

80
00:06:12,180 --> 00:06:15,270
So now we're ready to call this run main.

81
00:06:16,460 --> 00:06:25,100
This obviously needs this library open Pi XL, which normally it will be installed as a dependency when

82
00:06:25,100 --> 00:06:29,720
the user installs the invoice package.

83
00:06:30,230 --> 00:06:38,210
But since we are locally now, we need to install it separately using Pip install open pi XL.

84
00:06:38,210 --> 00:06:40,040
So this is to read.

85
00:06:40,040 --> 00:06:45,470
This is needed to read xls X files and let's run again.

86
00:06:46,920 --> 00:06:48,090
This time no errors.

87
00:06:48,090 --> 00:06:48,770
So let's see.

88
00:06:48,780 --> 00:06:52,620
Output and yeah, it seems to be working.

89
00:06:53,340 --> 00:06:56,010
So the testing of the library was successful.

90
00:06:56,040 --> 00:07:01,980
Now let's convert this library, which is actually a module into a package.

91
00:07:01,980 --> 00:07:11,010
So we use the words library module and package Library refers to either a module or a package, and

92
00:07:11,010 --> 00:07:14,790
a module is just one file as it is now.

93
00:07:15,360 --> 00:07:17,370
So it's just one file.

94
00:07:17,400 --> 00:07:18,720
Please ignore.

95
00:07:20,190 --> 00:07:21,240
These directories.

96
00:07:21,240 --> 00:07:26,240
So these are for testing only, but our module has only one.

97
00:07:26,460 --> 00:07:27,290
PY file.

98
00:07:27,300 --> 00:07:36,300
So if we wanted to add more codes in the future, let's say we want to expand our code.

99
00:07:38,040 --> 00:07:42,290
To also convert the Excel files into HTML.

100
00:07:42,300 --> 00:07:46,650
So for that we would need to add another function, right?

101
00:07:47,190 --> 00:07:55,140
But it would be better to have that function in a separate file, not inside invoice.py, but somewhere

102
00:07:55,140 --> 00:07:55,680
else.

103
00:07:55,680 --> 00:08:03,290
And in that case we would need a package because a package is more than one module.

104
00:08:03,300 --> 00:08:11,250
So currently we have the invoice.py module and a package would be a directory with multiple modules

105
00:08:11,250 --> 00:08:11,730
inside.

106
00:08:11,730 --> 00:08:13,710
So let's turn this into a package.

107
00:08:13,710 --> 00:08:19,880
Even though we only have one function at for now for the sake of scalability.

108
00:08:19,890 --> 00:08:26,940
So to prepare for the scenario when we want to add more codes later, we want to convert this into a

109
00:08:26,940 --> 00:08:28,170
package right now.

110
00:08:28,170 --> 00:08:35,880
So to do that, you want to create a new folder in your root directory, let's call our package invoicing,

111
00:08:35,880 --> 00:08:37,860
perhaps invoicing.

112
00:08:38,710 --> 00:08:39,309
Right.

113
00:08:39,520 --> 00:08:46,030
And you want to drag invoice.py to invoicing and press on refactor here.

114
00:08:46,540 --> 00:08:53,530
And so now we have a package with one module inside and if you want to add more modules later, you

115
00:08:53,530 --> 00:08:57,940
can go to new and create a new python file.

116
00:08:58,090 --> 00:09:01,570
Right now a good practice is to have.

117
00:09:03,730 --> 00:09:04,050
Eight.

118
00:09:04,510 --> 00:09:05,150
Underscore.

119
00:09:05,170 --> 00:09:06,320
Underscore init.

120
00:09:06,370 --> 00:09:06,990
Underscore.

121
00:09:06,990 --> 00:09:11,380
Underscore dot pi file in invoicing.

122
00:09:11,380 --> 00:09:15,600
So press enter and that will create this dot pi file.

123
00:09:15,610 --> 00:09:17,830
Why is this a good practice?

124
00:09:18,220 --> 00:09:22,540
This was mandatory actually before python 3.3.

125
00:09:22,870 --> 00:09:28,510
If you wanted that folder to behave as a package, you would have to have this file.

126
00:09:28,510 --> 00:09:35,620
Now, it's not necessary, but sometimes it's still good to have it because you can import in any dot

127
00:09:35,620 --> 00:09:38,440
pi things from invoice dot pi.

128
00:09:38,560 --> 00:09:40,630
Let me talk about that in one minute.

129
00:09:41,020 --> 00:09:49,720
But now that we have this invoicing package, we can go here and we would need to import it as from

130
00:09:49,720 --> 00:09:51,160
invoicing import invoice.

131
00:09:51,160 --> 00:09:56,440
You see PyCharm updated this line automatically because before it was just import invoice.

132
00:09:56,440 --> 00:10:03,920
So when we moved invoice to invoicing PyCharm refactored all the projects.

133
00:10:03,920 --> 00:10:05,540
So now we have this.

134
00:10:05,540 --> 00:10:10,940
So with the package, the import statement would be different as you can see you say from invoicing

135
00:10:10,940 --> 00:10:11,930
import invoice.

136
00:10:12,410 --> 00:10:18,680
Now you cannot do for example from invoicing, import generate, right?

137
00:10:20,120 --> 00:10:27,350
So if I run this I'm going to get an error cannot import name generate because invoicing doesn't have

138
00:10:27,350 --> 00:10:29,330
a name generate here.

139
00:10:29,330 --> 00:10:29,930
Right.

140
00:10:31,100 --> 00:10:39,110
But if you want users to be able to import generate like that, you should go to init.py and do from

141
00:10:39,470 --> 00:10:41,630
dot invoice.

142
00:10:41,660 --> 00:10:45,410
So we're inside invoicing here, right?

143
00:10:45,650 --> 00:10:48,140
Import generate.

144
00:10:50,380 --> 00:10:55,990
And now as a user, you can successfully execute this code.

145
00:10:56,560 --> 00:11:00,460
So that's the purpose of the init file.

146
00:11:00,670 --> 00:11:07,690
Basically, you can make available certain names at the level of the package, right?

147
00:11:07,690 --> 00:11:08,740
So.

148
00:11:10,060 --> 00:11:13,540
As you can see from invoices, import generates.

149
00:11:13,540 --> 00:11:22,810
So you skipped this module and you made available that function or that module like that.

150
00:11:23,170 --> 00:11:29,530
So this is not usually the case, but if you need to do that, that's how you do it.

151
00:11:30,070 --> 00:11:34,420
And yeah, that's our package invoicing.

152
00:11:34,420 --> 00:11:44,500
And now we can delete these files from our project because in the next video we're going to upload the

153
00:11:44,500 --> 00:11:46,320
package to pypi.

154
00:11:46,510 --> 00:11:52,060
So I'm deleting all those testing files and also main.py.

155
00:11:52,420 --> 00:11:59,020
So I'm going to keep only the package with init insights invoice.py and the image here.

156
00:11:59,930 --> 00:12:03,370
Also the image we don't need because it was part of testing.

157
00:12:04,730 --> 00:12:10,640
So just the package directory within it and invoice.py and yeah, that's about this video.

158
00:12:10,760 --> 00:12:12,890
Let's upload the package to py py.

159
00:12:12,920 --> 00:12:13,840
In the next video.

160
00:12:13,850 --> 00:12:14,210
See you.

