Lesson-17: Python Os Module:

Python Os Module

Python Os Module : When we want to write a program that will run on all operating systems we have to consider these differences and different situations when we should write separate code for each os us to save us the trouble and the module through a common interface with many function which enables different operating systems to communicate in a manner that is consistent and quality.

In this course, we will try to consider the most important and most commonly used functions and attributes offered by the os module in as much detail as possible.

First, we must import the os module into our program.

import os


the name attribute of the os module, which we mentioned in previous courses, gives us information about which operating system our users run the code we write.

We use this attribute as follows:

>>> os.name

If our codes are run on the Windows operating system, we get the following output from here:


MacOS and GNU/Linux operating systems give the following answer to this command:


Hence os.name using its attribute, we can write programs that run differently on different operating systems.


the sep attribute of the os module shows us what the directory separator of the operating system on which our code is running is.

If we use this attribute on the Windows operating system, we get the following output:

print (os.sep)

MacOS and GNU/Linux operating systems give the following answer to this command:

>>> os.sep


So, what does this quality do?

Using this attribute, you can create directory paths specific to different operating systems. For example:

>>> liste = ['aylar', 'mayıs', 'test']
>>> os.sep.join(liste)

Here is the join() method of character arrays os.note that we use it together with sep.

When you issue this command in Windows, you receive the following output:


When you give the same command in GNU/Linux, the following output:


In other words, when you give the above command in Windows, Python acts as if it has received the following command:

>>> liste = ['aylar', 'mayıs', 'test']
>>> '\\'.join(liste)

In GNU / Linux, the following command:

>>> liste = ['aylar', 'mayıs', 'test']
>>> '/'.join(liste)

So you don’t have to think about which operating system uses which Directory separator in the programs you write; Python thinks about it for you…


the getcwd() function of the OS module gives us the name of the directory we are currently in:

>>> os.getcwd()



the chdir() function of the os module allows us to switch from one directory to another.

For example, in GNU / Linux, we can use the following command to switch from the directory we are currently in to the directory named /usr/bin:

>>> os.chdir('/usr/bin/')

veya Windows’ta C:\Documents and Settings\fozgul\Desktop adlı dizine geçmek için şunu:

>>> os.chdir('C:\\Documents and Settings\\fozgul\\Desktop')

As you can see, the directory name we want to go to is os.chdir () function as a parameter is enough to give.


the listdir() function of the OS module allows us to list files and folders in a directory. listdir () is one of the most useful functions of the OS module.

For example, if we want to list the files and folders in the directory we are currently in, we can use this function as follows:

>>> mevcut_dizin = os.getcwd()
>>> os.listdir(mevcut_dizin)

Ekran Çıktısı:
C:\Users\Can\PycharmProjects\int\venv\Scripts\python.exe C:/Users/Can/PycharmProjects/int/dd.py
 ['.idea', 'dd.py', 'file_9f.py', 'file_deneme.py', 'meyveler.txt', 'python.txt', 'venv']

If we want to list the contents of a different directory, we just need to type the name of that directory as a parameter:

>>> os.listdir('/var/www')

As you can see, os.the output of the listdir() command is a data type of the list type. So you can do everything you can with lists with this. For example, you can set a loop on this list:

>>> for i in os.listdir(os.getcwd()):
...     print(i)

Or, you can filter files in a directory with a specific extension:

>>> for i in os.listdir(os.getcwd()):
...     if i.endswith('.doc'):
...         print(i)

These codes are for us, his name .it will list all files ending in

By the way, you remember the endswith() method of character sequences, don’t you?


To show the current directory in most operating systems ‘. an array of characters named ‘ is used. For example:

>>> os.listdir(os.getcwd())

you can also use the following command instead of a command such as:

>>> os.listdir('.')

we give the listdir() function as a parameter ‘.'the array of characters represents the directory we are currently in.

If you do not want to write this sequence of characters manually, you can also use the curdir attribute in the os module:

>>> os.listdir(os.curdir)

By the way, os.os with getcwd ().you must not confuse curdir. These two are not the same thing. os.getcwd () gives the name of the directory we are currently in as output. os.curdir, on the other hand, contains the value of what is an array of characters in the operating system that represents the directory that is currently located. This value is ‘in most operating systems.’is a series of characters named.


Just ‘.’like a string of characters, to show a parent directory in most operating systems’.. an array of characters named ‘ is used. For example:

>>> os.listdir('..')

the command lists the file and directory names in a parent directory, not in the directory you are currently in. It’s just like os again.as in the curdir nature, if you do not want to manually write this sequence of characters yourself, the os that contains this sequence of characters.you can take advantage of a qualification called pardir:

>>> os.listdir(os.pardir)

Bu komut, os.listdir('..') ile aynı çıktıyı verir.


This function works only on Windows. In GNU / Linux operating systems, this function is not defined.

the task of the startfile() function in the os module is to open any file on our computer with the program it is associated with.

Let’s give an example right away.

Don’t try on the knee we’re in at the moment.assume that you have a file deneme.txt. Now let’s give the following command:

>>> os.startfile('deneme.txt')

Your operating system .the startfile() function does not experiment with which program it associates files with the txt extension.it will open a file named txt with this program. In Windows .because txt files are usually associated with the Notepad program, it is probably trial when you issue the above command.the contents of the txt file will be displayed through the Notepad program.

In the same way, experiment in the directory where we are currently located.let’s assume that there is a file deneme.docx and let’s give the following command:

>>> os.startfile('deneme.docx')

This command will also allow the deneme.docx file to be opened with software called Microsoft Word.

If you give the startfile() function the name of a directory, not a file, as a parameter, This directory opens with Windows Explorer. For example, let’s open the directory we are in with Windows Explorer:

>>> os.startfile(os.curdir)

Instead, you also know that you can use the following command:

>>> os.startfile('.')


>>> os.startfile(os.getcwd())

All three commands perform the same function.

So what do we do if we want to open a parent directory?

Look carefully:

>>> os.startfile(os.pardir)


>>> os.startfile('..')

Both commands will allow you to display the parent directory using Windows Explorer.

Of course, you can also name a specific directory as a parameter to the startfile() function:

>>> os.startfile(r"C:\Documents and Settings\fozgul")

os.startfile () is a very useful function. You can even use this function not only to open files, but also to open internet pages:

>>> os.startfile('www.btogrenme.com')

Note, however, that this command will only run on Windows. So instead, it would be more accurate to use the webbrowser module that we learned earlier.


the mkdir() function of the os module allows us to create new directories.


>>> os.mkdir('yenidizin')

This command will create a directory called ‘new’ in the directory we are currently in.

Of course, if you want to create a directory in a different location, rather than in the directory you are currently in, you can specify the Open address of that location:

If the directory you are trying to create already exists os.mkdir () will give an error:


os.the makedirs () function is the os that we just learned.although it is very similar to the mkdir() function, there are significant differences between them.

Just now, os.mkdir() function when describing an example as follows:

>>> os.mkdir(r'C:\Documents and Settings\yenidizin')

For this command to work, the path C:Documents and Settingsfozgul must already exist on our computer. If any of the directories that make up this path do not exist, the function `mkdir () ” cannot create a directory named new. For this function to work, you must create all nonexistent directories one by one.

os.makedirs () is os.unlike the mkdir () function, it also has the ability to create nonexistent parent and subdirectories. For example:

>>> os.makedirs('/can/Desktop/aylar/mayıs/ödeme/')

This command will nest directories named months, May, and payment, respectively. I mean, os.in order for the makedirs() command to create a directory named payment, it is not necessary that the directories named months and may already exist. Os whether these directories exist or not.the makedirs () command can create the payment directory. But os.the mkdir () function is not like this. If os.if you want to create a payment index with the mkdir() function, you must first create the indexes months and may.


we can change the names of directories using the OS module’s rename() function. This function takes two parameters:

>>> os.rename('dizinin_şimdiki_adı', 'dizinin_yeni_adı')

For example, if there is a directory named ‘Test’ in the current working directory, we can give the following command to change the name of this directory to ‘test’:

>>> os.rename('deneme', 'test')

If there is already a directory called ‘test’ (and it is hollow), the above command will overwrite the directory called ‘test’ in GNU/Linux, and it will give an error in Windows.


the replace() function of the os module works like the rename() function that we just learned:

>>> os.replace('deneme', 'test')

This command will change the name of the array called experiment to test, just like the rename() function.

If a directory called test already exists, the replace() function tries to overwrite this existing test directory, both on Windows and GNU/Linux. GNU / Linux does this in most cases, but on Windows you may still encounter various permissions errors.


the OS module’s remove () function allows us to delete files from our computer:

>>> os.remove('dosya_adı')

Only you must use this command very carefully. Because this command directly deletes the file without asking any questions before deleting it.


the rmdir() function of the OS module is used to delete a hollow directory:

>>> os.rmdir('dizin_adı')

If there is any other directory or file in the directory you are trying to delete, this function will give an error.

For example, let’s consider a directory structure as follows:

|___ anadizin
    |___ dizin1
        |___ dizin2
            |___ dizin3
                |___ dizin4

By the way, you know what to do to create this directory structure easily:

>>> os.makedirs('anadizin/dizin1/dizin2/dizin3/dizin4')

The following commands will give an error when you are under your native language:

>>> os.rmdir('anadizin')
>>> os.rmdir(r'anadizin/dizin1')
>>> os.rmdir(r'anadizin/dizin1/dizin2/dizin3')

Because none of these directories are hollow; each one has a directory inside it. But the following command will succeed:

>>> os.rmdir(r'anadizin/dizin1/dizin2/dizin3/dizin4')

This way, you can delete all directories in order by moving up:

>>> os.rmdir(r'anadizin/dizin1/dizin2/dizin3/')
>>> os.rmdir(r'anadizin/dizin1/dizin2/')
>>> os.rmdir(r'anadizin/dizin1')
>>> os.rmdir(r'anadizin/')


the removedirs() function of the OS module allows us to delete hollow directory paths. Well, what does this mean?

Let’s say we have a directory structure like this:

|___ anadizin
    |___ dizin1
        |___ dizin2
            |___ dizin3
                |___ dizin4

When we give the following command from the bottom of the mother tongue:

>>> os.removedirs('anadizin/dizin1/dizin2/dizin3/dizin4')

If all directories are hollow, all directories from anadizin to Index4 (including anadizin and Index4) will be deleted.


the stat() function of the os module allows us to get information about files. Using this function, we can query the size of a file, the date it was created, the date it was modified, and the date it was accessed.

we use the stat() function as follows:

>>> dosya = os.stat('dosya_adı')
>>> dosya

Here we get a printout like this:

os.stat_result(st_mode=33279, st_ino=17732923532961356,
st_dev=1745874298, st_nlink=1, st_uid=0, st_gid=0,
st_size=495616, st_atime=1416488851, st_mtime=1415275662,

This is a special data type that contains a number of attributes in itself. To see the attributes of this data type, you can use the dir() function, as always:


here are the attributes that will be especially useful: st_atime

last access to the file historyist_ctime

file creation date (in Windows)st_mtime

file last modified datest_size

the size of the file

For example, to find out the size of a file, we can use the st_size attribute as follows:

>>> dosya = os.stat('dosya_adı')
>>> dosya.st_size

This function gives us an output in ‘bytes’. To convert it to kilobytes, you can divide this value by 1024:

>>> dosya.st_size / 1024

you can also get the creation, access, and modification dates of a file using the stat() function of the os module:

>>> dosya = os.stat('dosya_adı')
>>> dosya.st_ctime #oluşturulma tarihi
>>> dosya.st_atime #erişilme tarihi
>>> dosya.st_mtime #değiştirme tarihi

It is not possible to know when a file was created in GNU/Linux. Therefore, the file.st_ctime command returns only the date a file was created in Windows. When we give this command in GNU/Linux, what we get is the last modification date of the file.

By the way, the output of the above commands may have been meaningless to you. In a moment, when we learn a module called datetime, we will also explain how to turn these meaningless numbers into meaningful date information.


the system() function of the os module allows us to run system commands or other programs from within Python. For example:

>>> os.system('notepad.exe')


the urandom() function of the OS module can be used to obtain random byte sequences:

>>> os.urandom(12)

This command creates a random array of 12 bytes. You can use the random value you get here in cryptographic studies or in random password generation operations.


If you remember, we mentioned a function called listdir() in the os module on the previous pages. This function allowed us to list the contents of a directory. For example, we could use a command like this to find out which files and subdirectories were in the directory we were in at the time:

>>> os.listdir('.')

['build.py', 'gtk', 'kitap', 'make.bat', 'Makefile',
 'meta_conf.py', 'py2', 'py3', 'theme', 'tk2', '__pycache__']

As you can see, this function lists only the contents of the directory given to it as a parameter. For example, gtk, book, py2, py3, theme, tk2, and pycache one directory that appears in the output above. But the listdir () function does not try to enter these directories and list the content here. If we want to list the contents of the theme directory, for example, we need to specify it clearly:

>>> os.listdir('theme')

['layout.html', 'localtoc.html', 'pydoctheme',
 'sidebar.html', 'static']

Or, if we also want to access a directory called static in the theme directory, we also need to express it clearly as follows:

>>> os.listdir('theme/static')

['basic.css', 'copybutton.js', 'py.png', 'sidebar.js']

Or, if we also want to access a directory called static in the theme directory, we also need to express it clearly as follows:

For this, you can write a recursive function using the listdir () function:

import os

def tara(dizin):
    başlangıç = os.getcwd()
    dosyalar = []

    for öğe in os.listdir(os.curdir):
        if not os.path.isdir(öğe):

    return dosyalar

The only thing we haven’t learned in these codes is os.path.isdir () function. This function allows us to determine whether a value given to it as a parameter is an index.

In the above code, first of all, we throw the location of the array we are in at that moment into a variable called Start. Because we’ll have to come back here later.:

başlangıç = os.getcwd()

Then we create a list called Files:

dosyalar = []

This list will contain all the files within the directories.

Then, we enter the directory named Index, which is given as a parameter to the scan() function:


After entering this directory, we scan all the elements in the current directory one by one with the listdir() function:

for öğe in os.listdir(os.curdir):

If the item we encounter during scanning is not an index:

if not os.path.isdir(öğe):

We send this item directly to the list of files that we defined at the beginning:


But if the item we encounter during scanning is an index:


we return to the beginning of the tara() function and recursively apply all the operations that we define on this directory and process the items that we get in the list called files using the extend() method:


To understand why we use extend() instead of append() here, you can type the above code with append() and evaluate the output you get.

after exiting the for loop, we run the following command to return to the top position again:


If we do not go back to the beginning in this way, after entering the first subdirectory in the directory structure, our program cannot scan inside other parent directories because it will remain stuck in this location. To understand what that means, the codes are also os.you can try to run without the chdir(startup) code.

While the above method is correct, it is not the best way to scan a directory to the bottom in Python. Python Gives us a special function for this job. Here is the name of this function, which we will consider in this section, walk().

The word Walk means ‘walk’ in English. the walk () function also allows the word to ‘walk’ in indexes, in accordance with this meaning. Let’s explain this a little.

Imagine a situation like this: your hard disk has a lot of files scattered in many subdirectories in a directory. I mean, like this:


You break through this nested file stack .you want to collect what ends with jpeg in one place. Of course, if you want, this is it .you can manually find and move jpeg files one by one. But this method doesn’t suit a Python programmer, does it?

Python programmers prefer to do such chores to Python instead of doing them themselves. So we’ll use Python to do it.

you can easily perform this task by using the OS module's walk() function.

Yes, but how?

First, with the help of the following codes, let’s create the file-directory structure that we mentioned above. Thus, we have the opportunity to work on a more concrete structure:

import os

uzantılar = ['txt', 'doc', 'xls',
             'jpeg', 'pdf', 'zip',
             'mp3', 'ogg', 'jpeg']

şablon1 = ['{}.{}'.format('dosya', i) for i in uzantılar[:4]]
şablon2 = ['resim{}.{}'.format(i, uzantılar[-1]) for i in range(1, 5)]
şablon3 = ['{}.{}'.format('dosya', i) for i in uzantılar[4:]]

dosyalar = [('anadizin',  şablon1),
            ('resimler', şablon2),
            ('başkadosyalar', şablon3)]

os.makedirs(os.sep.join([dosya[0] for dosya in dosyalar]))

for dizin, şablon in dosyalar:
    for s in şablon:
        open(os.sep.join([dizin, s]), 'w')

There’s nothing in these codes that we haven’t seen or learned so far. You have enough Python knowledge to easily understand these codes.

Since we have created our file-directory structure, we can switch to how to use the os module’s walk() function on this structure.

Now let’s launch the interactive shell in the directory where the folder named ‘anadizin’ is located and give the following commands:

>>> for i in os.walk('anadizin'):
...     print(i)

We’ll get this printout from here:

('anadizin', ['resimler'], ['dosya.doc', 'dosya.jpeg',
              'dosya.txt', 'dosya.xls'])
('anadizin\\resimler', ['başkadosyalar'], ['resim1.jpeg',
              'resim2.jpeg', 'resim3.jpeg', 'resim4.jpeg'])
('anadizin\\resimler\\başkadosyalar', [], ['dosya.jpeg',
              'dosya.mp3', 'dosya.ogg', 'dosya.pdf', 'dosya.zip'])

Let’s consider the first part of this output for ease of review:

('anadizin', ['resimler'], ['dosya.doc', 'dosya.jpeg',
                            'dosya.txt', 'dosya.xls'])

As you can see, there’s a bunch of three elements here. If you examine other parts of the output, you will see the same structure. Hence the os.the walk () command gives us a bunch of the following three elements:

(kökdizin, altdizinler, dosyalar)

You can easily see this structure when you examine the output above:

kökdizin    => 'anadizin'
altdizinler => ['resimler']
dosyalar    => ['dosya.doc', 'dosya.jpeg',
                'dosya.txt', 'dosya.xls']

kökdizin    => 'anadizin\\resimler'
altdizinler => ['başkadosyalar']
dosyalar    => ['resim1.jpeg', 'resim2.jpeg',
                'resim3.jpeg', 'resim4.jpeg']

kökdizin    => 'anadizin\\resimler\\başkadosyalar'
altdizinler => []
dosyalar    => ['dosya.jpeg', 'dosya.mp3',
                'dosya.ogg', 'dosya.pdf',

For example, if you want to import only files from this three-element bunch, you can give a command like this:

>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
...     print(dosyalar)

Here, os.each element of the three-element bundle presented to us by the walk command(‘motherizin’), using the following line, we throw it into individual variables called rootdizin, subdirectories, and files:

>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
...     ...

Then, from this triple, we print the variable named Files on the screen:

>>> print(dosyalar)

That gives us a printout like this:

['dosya.doc', 'dosya.jpeg', 'dosya.txt', 'dosya.xls']
['resim1.jpeg', 'resim2.jpeg', 'resim3.jpeg', 'resim4.jpeg']
['dosya.jpeg', 'dosya.mp3', 'dosya.ogg', 'dosya.pdf', 'dosya.zip']

As you can see, this output contains all the files contained in your ‘native’ and all the directories under it. As we said at the beginning of this topic when defining the walk() function, the walk() function really allows you to ‘walk’ in indexes.

Let’s do a few more experiments to better understand this function:

>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
...     print(altdizinler)

This gives us the names of the subdirectories in ‘motherizin’.

Let’s look at what the root variable is:

>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
...     print(yol)

Here, we printed rootdizin among these triple variables, and we saw that this variable gives us path information for all root directories, that is, the address of the directories. So we can get the full address of a file by combining the root variable and the files variable.

Look carefully:

>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
...     for dosya in dosyalar:
...             print(os.sep.join([yol, dosya]))

As you know, the data type that the file variable gives us is a list. So note that we also set a for loop on this list to get the elements of this list individually.

All of you contained in the above directories .if we want to list jpeg files, we can also write code like this:

>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
...     for dosya in dosyalar:
...             if dosya.endswith('.jpeg'):
...                     print(dosya)

As you can see, os.the walk () function is a very practical and useful tool.


the environ attribute of the OS module allows us to learn about the environment variables in the operating system we use.

This attribute is an ordinary dictionary. So you can see what’s going on in this dictionary with the following codes:

>>> for k, v in os.environ.items():
...     print(k.ljust(10), v)

You know how to access a desired value in the dictionary:

>>> os.environ['HOMEPATH']

'\\Documents and Settings\\fozgul'

>>> os.environ['USERNAME']


However, since Environment Variables and their names are different in Windows and GNU/Linux operating systems, naturally the environ attribute also gives different outputs in different operating systems. In programs that we have designed to run on multiple operating systems, we should pay attention to this situation. For example, in Windows, the environment variable that gives the user name is ‘USERNAME’, while in GNU/Linux, this variable is called ‘USER’.


when you apply the dir() function on the os module, you will see that there is an attribute named path. This attribute contains many important functions and other attributes in itself.

Now in this section os.we will examine the content of this attribute called path.


the abspath () function tells you what the exact path of a file is:

>>> os.path.abspath('falanca.txt')


the dirname () function returns the directory portion of a file path:

>>> os.path.dirname('/home/istihza/Desktop/falanca.txt')


You can use this function together with the abspath() function:

>>> os.path.dirname(os.path.abspath('falanca.txt'))



The exists () function checks whether a file or directory exist

>>> os.path.exists('/home/istihza/Desktop/falanca.txt')

If such a file exists, the above code outputs True, or False.


the expanduser () function returns the address of the user’s directory on the computer:

>>> os.path.expanduser('~')

'C:\\Documents and Settings\\fozgul'


>>> os.path.expanduser('~')


Using this function, you can also create a specific user name and directory in Windows:

>>> os.path.expanduser('~denizege')

'C:\\Documents and Settings\\denizege'


the isdir () function queries whether the element given to it as a parameter is an index:

>>> os.path.isdir('/home/istihza')

If the parameter is a directory, True, if it is a file, False is output.


the isfile () function queries whether the element given to it as a parameter is a file:

>>> os.path.isfile('/home/istihza/falance.txt')

If the parameter is a file, True, if it is a directory, False is output.


the join () function creates path addresses appropriate to the corresponding operating system from the parameters given to it:

>>> os.path.join('dizin1', 'dizin2', 'dizin3') #Windows


>>> os.path.join('dizin1', 'dizin2', 'dizin3')



the split () function separates the last part of a path address from the head part:

>>> os.path.split('/home/istihza/Desktop')

('/home/istihza', 'Desktop')

Using this function, you can separate file names from directory names:

>>> dizin, dosya = os.path.split('/home/istihza/Desktop/falanca.txt')
>>> dizin


>>> dosya



the splitext () function is used to separate the file name and its extension:

>>> dosya, uzantı = os.path.splitext('falanca.txt')
>>> dosya


>>> uzantı


As you can see, an os that contains many attributes and functions in itself.path is an extremely useful tool that allows us to perform directory operations according to the operating system we use.

Come here, if you want, now some of this os.let’s talk about some important features of the path attribute.

If you remember, in our previous lessons, we mentioned a tool called file that allows us to see the source files of modules. For example, when we apply this tool on the os module, we get output similar to this:

>>> os.__file__


This means that the source code of the os module is located in this directory…

Normally, you can apply the file attribute only to module names. File tool cannot be used on attributes and functions of modules:

>>> os.name.__file__

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__file__'

>>> os.walk.__file__

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__file__'

But for the path attribute of the os module, the situation is slightly different:

>>> os.path.__file__

If you have given this command in Windows, you will get the following output:


But if you gave this command in GNU/Linux, you will get output similar to this:


As you can see, _ _ file__, os.it can be used on path. According to the above outputs, os.the path attribute refers to a module called ntpath on Windows and posixpath on GNU/Linux.

So actually we are os.when using the path attribute, we import a module called ntpath if we are in Windows, but a module called posixpath if we are in GNU/Linux.

If os.if there was no common interface called path, os above.in order to use the tools we reviewed under the path heading, we would have to manually import the appropriate one from the posixpath or ntpath modules according to the operating system we use:

if os.name == 'nt':
    import ntpath as path

    import posixpath as path

But the Python programming language OS us.because it offers an attribute called path, we do not need to import the ntpath module for the Windows operating system and the posixpath module for the GNU/Linux operating system separately. Python does all the work for us. Thus, different operations related to different operating systems, os.we can perform it through a single interface called path.


You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *