kopipasta 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kopipasta might be problematic. Click here for more details.
- kopipasta-0.1.0/LICENSE +0 -0
- kopipasta-0.1.0/MANIFEST.in +3 -0
- kopipasta-0.1.0/PKG-INFO +64 -0
- kopipasta-0.1.0/README.md +41 -0
- kopipasta-0.1.0/kopipasta/__init__.py +0 -0
- kopipasta-0.1.0/kopipasta/main.py +222 -0
- kopipasta-0.1.0/kopipasta.egg-info/PKG-INFO +64 -0
- kopipasta-0.1.0/kopipasta.egg-info/SOURCES.txt +13 -0
- kopipasta-0.1.0/kopipasta.egg-info/dependency_links.txt +1 -0
- kopipasta-0.1.0/kopipasta.egg-info/entry_points.txt +2 -0
- kopipasta-0.1.0/kopipasta.egg-info/requires.txt +1 -0
- kopipasta-0.1.0/kopipasta.egg-info/top_level.txt +1 -0
- kopipasta-0.1.0/requirements.txt +1 -0
- kopipasta-0.1.0/setup.cfg +4 -0
- kopipasta-0.1.0/setup.py +38 -0
kopipasta-0.1.0/LICENSE
ADDED
|
File without changes
|
kopipasta-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: kopipasta
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A CLI tool to generate prompts with project structure and file contents
|
|
5
|
+
Home-page: https://github.com/mkorpela/kopipasta
|
|
6
|
+
Author: Mikko Korpela
|
|
7
|
+
Author-email: mikko.korpela@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: pyperclip==1.9.0
|
|
23
|
+
|
|
24
|
+
# kopipasta
|
|
25
|
+
|
|
26
|
+
A CLI tool to generate prompts with project structure and file contents.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
You can install kopipasta using pipx (or pip):
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
pipx install kopipasta
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
To use kopipasta, run the following command in your terminal:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
kopipasta [files_or_directories]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Replace `[files_or_directories]` with the paths to the files or directories you want to include in the prompt.
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
```
|
|
48
|
+
kopipasta . src/ config.json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This will generate a prompt including the project structure and contents of the specified files and directories, ignoring files and directories typically excluded in version control (based on common .gitignore patterns).
|
|
52
|
+
|
|
53
|
+
The generated prompt will be displayed in the console and automatically copied to your clipboard.
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
- Generates a structured prompt with project overview, file contents, and task instructions
|
|
58
|
+
- Ignores files and directories based on common .gitignore patterns
|
|
59
|
+
- Allows interactive selection of files to include
|
|
60
|
+
- Automatically copies the generated prompt to the clipboard
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
This project is licensed under the MIT License.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# kopipasta
|
|
2
|
+
|
|
3
|
+
A CLI tool to generate prompts with project structure and file contents.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
You can install kopipasta using pipx (or pip):
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
pipx install kopipasta
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
To use kopipasta, run the following command in your terminal:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
kopipasta [files_or_directories]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Replace `[files_or_directories]` with the paths to the files or directories you want to include in the prompt.
|
|
22
|
+
|
|
23
|
+
Example:
|
|
24
|
+
```
|
|
25
|
+
kopipasta . src/ config.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This will generate a prompt including the project structure and contents of the specified files and directories, ignoring files and directories typically excluded in version control (based on common .gitignore patterns).
|
|
29
|
+
|
|
30
|
+
The generated prompt will be displayed in the console and automatically copied to your clipboard.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Generates a structured prompt with project overview, file contents, and task instructions
|
|
35
|
+
- Ignores files and directories based on common .gitignore patterns
|
|
36
|
+
- Allows interactive selection of files to include
|
|
37
|
+
- Automatically copies the generated prompt to the clipboard
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
|
|
41
|
+
This project is licensed under the MIT License.
|
|
File without changes
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import os
|
|
3
|
+
import argparse
|
|
4
|
+
import pyperclip
|
|
5
|
+
import fnmatch
|
|
6
|
+
|
|
7
|
+
def read_gitignore():
|
|
8
|
+
default_ignore_patterns = [
|
|
9
|
+
'.git', 'node_modules', 'venv', '.venv', 'dist', '.idea', '__pycache__',
|
|
10
|
+
'*.pyc', '.ruff_cache', '.mypy_cache', '.pytest_cache', '.vscode', '.vite',
|
|
11
|
+
'.terraform', 'output', 'poetry.lock', 'package-lock.json', '.env',
|
|
12
|
+
'*.log', '*.bak', '*.swp', '*.swo', '*.tmp', 'tmp', 'temp', 'logs',
|
|
13
|
+
'build', 'target', '.DS_Store', 'Thumbs.db', '*.class', '*.jar',
|
|
14
|
+
'*.war', '*.ear', '*.sqlite', '*.db', '.github', '.gitignore'
|
|
15
|
+
]
|
|
16
|
+
gitignore_patterns = default_ignore_patterns.copy()
|
|
17
|
+
|
|
18
|
+
if os.path.exists('.gitignore'):
|
|
19
|
+
with open('.gitignore', 'r') as file:
|
|
20
|
+
for line in file:
|
|
21
|
+
line = line.strip()
|
|
22
|
+
if line and not line.startswith('#'):
|
|
23
|
+
gitignore_patterns.append(line)
|
|
24
|
+
return gitignore_patterns
|
|
25
|
+
|
|
26
|
+
def is_ignored(path, ignore_patterns):
|
|
27
|
+
path = os.path.normpath(path)
|
|
28
|
+
for pattern in ignore_patterns:
|
|
29
|
+
if fnmatch.fnmatch(os.path.basename(path), pattern) or fnmatch.fnmatch(path, pattern):
|
|
30
|
+
return True
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
def get_project_structure(ignore_patterns):
|
|
34
|
+
tree = []
|
|
35
|
+
for root, dirs, files in os.walk('.'):
|
|
36
|
+
# Remove ignored directories
|
|
37
|
+
dirs[:] = [d for d in dirs if not is_ignored(os.path.join(root, d), ignore_patterns)]
|
|
38
|
+
# Remove ignored files
|
|
39
|
+
files = [f for f in files if not is_ignored(os.path.join(root, f), ignore_patterns)]
|
|
40
|
+
level = root.replace('.', '').count(os.sep)
|
|
41
|
+
indent = ' ' * 4 * level + '|-- '
|
|
42
|
+
tree.append(f"{indent}{os.path.basename(root)}/")
|
|
43
|
+
subindent = ' ' * 4 * (level + 1) + '|-- '
|
|
44
|
+
for f in files:
|
|
45
|
+
tree.append(f"{subindent}{f}")
|
|
46
|
+
return '\n'.join(tree)
|
|
47
|
+
|
|
48
|
+
def read_file_contents(file_path):
|
|
49
|
+
try:
|
|
50
|
+
with open(file_path, 'r') as file:
|
|
51
|
+
return file.read()
|
|
52
|
+
except Exception as e:
|
|
53
|
+
print(f"Error reading {file_path}: {e}")
|
|
54
|
+
return ""
|
|
55
|
+
|
|
56
|
+
def get_relative_path(file_path):
|
|
57
|
+
return os.path.relpath(file_path)
|
|
58
|
+
|
|
59
|
+
def get_language_for_file(file_path):
|
|
60
|
+
extension = os.path.splitext(file_path)[1].lower()
|
|
61
|
+
language_map = {
|
|
62
|
+
'.py': 'python',
|
|
63
|
+
'.js': 'javascript',
|
|
64
|
+
'.jsx': 'jsx',
|
|
65
|
+
'.ts': 'typescript',
|
|
66
|
+
'.tsx': 'tsx',
|
|
67
|
+
'.html': 'html',
|
|
68
|
+
'.css': 'css',
|
|
69
|
+
'.json': 'json',
|
|
70
|
+
'.md': 'markdown',
|
|
71
|
+
'.sql': 'sql',
|
|
72
|
+
'.sh': 'bash',
|
|
73
|
+
'.yml': 'yaml',
|
|
74
|
+
'.yaml': 'yaml',
|
|
75
|
+
'.go': 'go',
|
|
76
|
+
'.toml': 'toml'
|
|
77
|
+
}
|
|
78
|
+
return language_map.get(extension, '')
|
|
79
|
+
|
|
80
|
+
def select_files_in_directory(directory, ignore_patterns):
|
|
81
|
+
files = [f for f in os.listdir(directory)
|
|
82
|
+
if os.path.isfile(os.path.join(directory, f)) and not is_ignored(os.path.join(directory, f), ignore_patterns)]
|
|
83
|
+
|
|
84
|
+
if not files:
|
|
85
|
+
return []
|
|
86
|
+
|
|
87
|
+
print(f"\nDirectory: {directory}")
|
|
88
|
+
print("Files:")
|
|
89
|
+
for file in files:
|
|
90
|
+
print(f"- {file}")
|
|
91
|
+
|
|
92
|
+
while True:
|
|
93
|
+
choice = input("\n(y)es add all / (n)o ignore all / (s)elect individually / (q)uit? ").lower()
|
|
94
|
+
if choice == 'y':
|
|
95
|
+
print(f"Added all files from {directory}")
|
|
96
|
+
return files
|
|
97
|
+
elif choice == 'n':
|
|
98
|
+
print(f"Ignored all files from {directory}")
|
|
99
|
+
return []
|
|
100
|
+
elif choice == 's':
|
|
101
|
+
selected_files = []
|
|
102
|
+
for file in files:
|
|
103
|
+
while True:
|
|
104
|
+
file_choice = input(f"{file} (y/n/q)? ").lower()
|
|
105
|
+
if file_choice == 'y':
|
|
106
|
+
selected_files.append(file)
|
|
107
|
+
break
|
|
108
|
+
elif file_choice == 'n':
|
|
109
|
+
break
|
|
110
|
+
elif file_choice == 'q':
|
|
111
|
+
print(f"Quitting selection for {directory}")
|
|
112
|
+
return selected_files
|
|
113
|
+
else:
|
|
114
|
+
print("Invalid choice. Please enter 'y', 'n', or 'q'.")
|
|
115
|
+
print(f"Added {len(selected_files)} files from {directory}")
|
|
116
|
+
return selected_files
|
|
117
|
+
elif choice == 'q':
|
|
118
|
+
print(f"Quitting selection for {directory}")
|
|
119
|
+
return []
|
|
120
|
+
else:
|
|
121
|
+
print("Invalid choice. Please try again.")
|
|
122
|
+
|
|
123
|
+
def process_directory(directory, ignore_patterns):
|
|
124
|
+
files_to_include = []
|
|
125
|
+
processed_dirs = set()
|
|
126
|
+
|
|
127
|
+
for root, dirs, files in os.walk(directory):
|
|
128
|
+
# Remove ignored directories
|
|
129
|
+
dirs[:] = [d for d in dirs if not is_ignored(os.path.join(root, d), ignore_patterns)]
|
|
130
|
+
# Remove ignored files
|
|
131
|
+
files = [f for f in files if not is_ignored(os.path.join(root, f), ignore_patterns)]
|
|
132
|
+
|
|
133
|
+
if root in processed_dirs:
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
selected_files = select_files_in_directory(root, ignore_patterns)
|
|
137
|
+
full_paths = [os.path.join(root, f) for f in selected_files]
|
|
138
|
+
files_to_include.extend(full_paths)
|
|
139
|
+
processed_dirs.add(root)
|
|
140
|
+
|
|
141
|
+
return files_to_include, processed_dirs
|
|
142
|
+
|
|
143
|
+
def generate_prompt(files_to_include, ignore_patterns):
|
|
144
|
+
prompt = "# Project Overview\n\n"
|
|
145
|
+
prompt += "## Summary of Included Files\n\n"
|
|
146
|
+
for file in files_to_include:
|
|
147
|
+
relative_path = get_relative_path(file)
|
|
148
|
+
prompt += f"- {relative_path}\n"
|
|
149
|
+
prompt += "\n"
|
|
150
|
+
|
|
151
|
+
prompt += "## Project Structure\n\n"
|
|
152
|
+
prompt += "```\n"
|
|
153
|
+
prompt += get_project_structure(ignore_patterns)
|
|
154
|
+
prompt += "\n```\n\n"
|
|
155
|
+
|
|
156
|
+
prompt += "## File Contents\n\n"
|
|
157
|
+
for file in files_to_include:
|
|
158
|
+
relative_path = get_relative_path(file)
|
|
159
|
+
language = get_language_for_file(file)
|
|
160
|
+
prompt += f"### {relative_path}\n\n"
|
|
161
|
+
prompt += f"```{language}\n"
|
|
162
|
+
prompt += read_file_contents(file)
|
|
163
|
+
prompt += "\n```\n\n"
|
|
164
|
+
|
|
165
|
+
prompt += "## Task Instructions\n\n"
|
|
166
|
+
task_instructions = input("Enter the task instructions: ")
|
|
167
|
+
prompt += f"{task_instructions}\n\n"
|
|
168
|
+
|
|
169
|
+
prompt += "## Task Analysis and Planning\n\n"
|
|
170
|
+
prompt += (
|
|
171
|
+
"Before starting, explain the task back to me in your own words. "
|
|
172
|
+
"Ask for any clarifications if needed. Once you're clear, ask to proceed.\n\n"
|
|
173
|
+
"Then, outline a plan for the task. Finally, use your plan to complete the task."
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
return prompt
|
|
177
|
+
|
|
178
|
+
def main():
|
|
179
|
+
parser = argparse.ArgumentParser(description="Generate a prompt with project structure and file contents.")
|
|
180
|
+
parser.add_argument('inputs', nargs='+', help='Files or directories to include in the prompt')
|
|
181
|
+
args = parser.parse_args()
|
|
182
|
+
|
|
183
|
+
ignore_patterns = read_gitignore()
|
|
184
|
+
|
|
185
|
+
files_to_include = []
|
|
186
|
+
processed_dirs = set()
|
|
187
|
+
|
|
188
|
+
for input_path in args.inputs:
|
|
189
|
+
if os.path.isfile(input_path):
|
|
190
|
+
if not is_ignored(input_path, ignore_patterns):
|
|
191
|
+
files_to_include.append(input_path)
|
|
192
|
+
print(f"Added file: {input_path}")
|
|
193
|
+
else:
|
|
194
|
+
print(f"Ignored file: {input_path}")
|
|
195
|
+
elif os.path.isdir(input_path):
|
|
196
|
+
dir_files, dir_processed = process_directory(input_path, ignore_patterns)
|
|
197
|
+
files_to_include.extend(dir_files)
|
|
198
|
+
processed_dirs.update(dir_processed)
|
|
199
|
+
else:
|
|
200
|
+
print(f"Warning: {input_path} is not a valid file or directory. Skipping.")
|
|
201
|
+
|
|
202
|
+
if not files_to_include:
|
|
203
|
+
print("No files were selected. Exiting.")
|
|
204
|
+
return
|
|
205
|
+
|
|
206
|
+
print("\nFile selection complete.")
|
|
207
|
+
print(f"Summary: Added {len(files_to_include)} files from {len(processed_dirs)} directories.")
|
|
208
|
+
|
|
209
|
+
prompt = generate_prompt(files_to_include, ignore_patterns)
|
|
210
|
+
print("\nGenerated prompt:")
|
|
211
|
+
print(prompt)
|
|
212
|
+
|
|
213
|
+
# Copy the prompt to clipboard
|
|
214
|
+
try:
|
|
215
|
+
pyperclip.copy(prompt)
|
|
216
|
+
print("\nPrompt has been copied to clipboard.")
|
|
217
|
+
except pyperclip.PyperclipException as e:
|
|
218
|
+
print(f"Failed to copy to clipboard: {e}")
|
|
219
|
+
|
|
220
|
+
if __name__ == "__main__":
|
|
221
|
+
main()
|
|
222
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: kopipasta
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A CLI tool to generate prompts with project structure and file contents
|
|
5
|
+
Home-page: https://github.com/mkorpela/kopipasta
|
|
6
|
+
Author: Mikko Korpela
|
|
7
|
+
Author-email: mikko.korpela@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: pyperclip==1.9.0
|
|
23
|
+
|
|
24
|
+
# kopipasta
|
|
25
|
+
|
|
26
|
+
A CLI tool to generate prompts with project structure and file contents.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
You can install kopipasta using pipx (or pip):
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
pipx install kopipasta
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
To use kopipasta, run the following command in your terminal:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
kopipasta [files_or_directories]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Replace `[files_or_directories]` with the paths to the files or directories you want to include in the prompt.
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
```
|
|
48
|
+
kopipasta . src/ config.json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This will generate a prompt including the project structure and contents of the specified files and directories, ignoring files and directories typically excluded in version control (based on common .gitignore patterns).
|
|
52
|
+
|
|
53
|
+
The generated prompt will be displayed in the console and automatically copied to your clipboard.
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
- Generates a structured prompt with project overview, file contents, and task instructions
|
|
58
|
+
- Ignores files and directories based on common .gitignore patterns
|
|
59
|
+
- Allows interactive selection of files to include
|
|
60
|
+
- Automatically copies the generated prompt to the clipboard
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
This project is licensed under the MIT License.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
requirements.txt
|
|
5
|
+
setup.py
|
|
6
|
+
kopipasta/__init__.py
|
|
7
|
+
kopipasta/main.py
|
|
8
|
+
kopipasta.egg-info/PKG-INFO
|
|
9
|
+
kopipasta.egg-info/SOURCES.txt
|
|
10
|
+
kopipasta.egg-info/dependency_links.txt
|
|
11
|
+
kopipasta.egg-info/entry_points.txt
|
|
12
|
+
kopipasta.egg-info/requires.txt
|
|
13
|
+
kopipasta.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyperclip==1.9.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
kopipasta
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyperclip==1.9.0
|
kopipasta-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
|
4
|
+
long_description = fh.read()
|
|
5
|
+
|
|
6
|
+
setup(
|
|
7
|
+
name="kopipasta",
|
|
8
|
+
version="0.1.0",
|
|
9
|
+
author="Mikko Korpela",
|
|
10
|
+
author_email="mikko.korpela@gmail.com",
|
|
11
|
+
description="A CLI tool to generate prompts with project structure and file contents",
|
|
12
|
+
long_description=long_description,
|
|
13
|
+
long_description_content_type="text/markdown",
|
|
14
|
+
url="https://github.com/mkorpela/kopipasta",
|
|
15
|
+
packages=find_packages(),
|
|
16
|
+
install_requires=[
|
|
17
|
+
"pyperclip==1.9.0",
|
|
18
|
+
],
|
|
19
|
+
classifiers=[
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.8",
|
|
26
|
+
"Programming Language :: Python :: 3.9",
|
|
27
|
+
"Programming Language :: Python :: 3.10",
|
|
28
|
+
"Programming Language :: Python :: 3.11",
|
|
29
|
+
"Programming Language :: Python :: 3.12",
|
|
30
|
+
],
|
|
31
|
+
python_requires=">=3.8",
|
|
32
|
+
license="MIT",
|
|
33
|
+
entry_points={
|
|
34
|
+
"console_scripts": [
|
|
35
|
+
"kopipasta=kopipasta.main:main",
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
)
|