So after a lot research i found the solution to this and how it works also. It's a little bit confusing, none of the other stackoverflow answers were really that explanatory. I want to try it here:
I have made a sample project for that only purpose to demostrate and test the solution. I have come up with two solutions: one using the data_files argument of the setup() function and the other using the package_data argument which i preferred the most.
Here is the link to the github repo you can download and test
To use it after installation run
proj init <some-name>
But to be brief there are the most important modules for each method.
USING data_files= ARGUMENT METHOD:
Project structure:
project_initializer
project_initializer
__init__.py
__main__.py
init.py
README.md
setup.py
in setup.py
import setuptools
import os
import sys
PROJECT_NAME = "project_initializer"
DATA_DIR = os.path.join(
sys.prefix, "local/lib/python3.6/dist-packages", PROJECT_NAME)
setuptools.setup(
name='project_initializer',
version='0.1.0',
packages=setuptools.find_packages(),
install_requires=[
'docopt'
],
data_files=[ # is the important part
(DATA_DIR, [
"README.md",
".gitignore"
])
],
entry_points={
'console_scripts': [
'proj = project_initializer.__main__:main'
]
}
)
in init.py
import subprocess
import os
import shutil
import sys
"""Create a new project and initialize it with a .gitignore file
@params project: name of a project to be initialized
effects:
/project
README.md
README.md in the created project directory must be the same as the README.md in THIS directory
"""
PROJECT_NAME = "project_initializer"
DATA_DIR = os.path.join(
sys.prefix, "local/lib/python3.6/dist-packages", PROJECT_NAME)
def run(project):
os.mkdir(project)
shutil.copyfile(os.path.join(DATA_DIR, "README.md"),
f"{project}/README.md") # problem solved
if __name__ == '__main__':
run("hello-world")
USING package_data= ARGUMENT METHOD (which i preferred)
Project structure:
project_initializer
project_initializer
data/
README.md # the file we want to copy
__init__.py
__main__.py
init.py
README.md
setup.py
in setup.py
import setuptools
setuptools.setup(
name='project_initializer',
version='0.1.0',
packages=setuptools.find_packages(),
package_dir={'project_initializer': 'project_initializer'}, # are the ...
package_data={'project_initializer': [ # ... important parameters
'data/README.md', 'data/.gitignore']},
install_requires=[
'docopt'
],
entry_points={
'console_scripts': [
'proj = project_initializer.__main__:main'
]
}
)
in init.py
import subprocess
import os
import shutil
import sys
PROJECT_DIR = os.path.dirname(__file__)
"""Create a new project and initialize it with a .gitignore file
@params project: name of a project to be initialized
effects:
/project
.gitignore
.gitignore in the created project directory must be the same as the gitignore in THIS directory
"""
def run(project):
os.mkdir(project)
shutil.copyfile(os.path.join(PROJECT_DIR, 'data/README.md'),
f"{project}/README.md") # problem solved
if __name__ == '__main__':
run("hello-world")
The reason why i prefer this last method is because you have not to import anything in the setup.py module which could be presumably a bad practice. I guess nothing should be imported in the setup.py file since it is an external file to the main package.
For more detailed explanation of what are the differences between the two arguments check out the python docs
Using data_files= argument
Using package_data= argument