ticket2pr 0.3.4__py2.py3-none-any.whl → 0.3.6__py2.py3-none-any.whl

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.
@@ -1,7 +1,6 @@
1
1
  from pathlib import Path
2
2
 
3
- from src.agents.base import extract_session_id, print_agent_message, run_agent_query
4
- from src.shell.pre_commit_runner import run_pre_commit
3
+ from src.agents.base import print_agent_message, run_agent_query
5
4
 
6
5
  SYSTEM_PROMPT = """
7
6
  You are an expert Software Engineer specializing in fixing pre-commit hook failures.
@@ -13,6 +12,8 @@ Your role is to:
13
12
  4. Preserve the original functionality and purpose of the changes
14
13
 
15
14
  CRITICAL RULES:
15
+ - You MUST address ALL pre-commit issues reported - do not miss any errors or warnings
16
+ - Carefully parse the entire pre-commit output and fix every single issue mentioned
16
17
  - Only fix formatting, linting, type errors, and other pre-commit hook violations
17
18
  - DO NOT change the logic or functionality of the code
18
19
  - DO NOT add new features or remove existing functionality
@@ -45,37 +46,29 @@ Pre-commit output:
45
46
  """
46
47
 
47
48
 
48
- async def verify_pre_commit_and_fix(
49
- workspace_path: Path, max_retries: int = 5, mcp_config_path: Path | None = None
50
- ) -> bool:
49
+ async def try_fix_pre_commit(
50
+ workspace_path: Path,
51
+ pre_commit_output: str,
52
+ max_retries: int = 5,
53
+ mcp_config_path: Path | None = None,
54
+ ) -> None:
51
55
  """
52
- Verify pre-commit hooks pass on STAGED FILES ONLY, fixing issues if needed.
56
+ Attempt to fix pre-commit hook failures using AI.
53
57
 
54
- This function:
55
- 1. Runs pre-commit hooks on staged files ONLY (never --all-files)
56
- 2. If successful, returns True
57
- 3. If failed, uses AI to fix the issues (AI will stage its own fixes and retry)
58
+ This function uses AI to analyze pre-commit failures and apply fixes.
59
+ The caller is responsible for running pre-commit before and after to verify.
58
60
 
59
61
  Args:
60
62
  workspace_path: Path to the workspace root
61
- max_retries: Maximum number of retry attempts to tell the AI (default: 5)
63
+ pre_commit_output: The output from a failed pre-commit run
64
+ max_retries: Maximum number of retry attempts for the AI (default: 5)
62
65
  mcp_config_path: Optional path to MCP config file
63
-
64
- Returns:
65
- True if pre-commit passes, False otherwise
66
66
  """
67
- result = run_pre_commit(workspace_path)
68
-
69
- if result.success:
70
- return True
71
-
72
67
  system_prompt = SYSTEM_PROMPT.format(max_retries=max_retries)
73
-
74
68
  prompt = PROMPT_TEMPLATE.format(
75
- pre_commit_output=result.output,
69
+ pre_commit_output=pre_commit_output,
76
70
  )
77
71
 
78
- session_id = None
79
72
  async for message in run_agent_query(
80
73
  prompt=prompt,
81
74
  system_prompt=system_prompt,
@@ -84,11 +77,4 @@ async def verify_pre_commit_and_fix(
84
77
  cwd=workspace_path,
85
78
  mcp_config_path=mcp_config_path,
86
79
  ):
87
- if session_id is None:
88
- session_id = extract_session_id(message)
89
- if session_id:
90
- continue
91
80
  print_agent_message(message)
92
-
93
- final_result = run_pre_commit(workspace_path)
94
- return final_result.success
@@ -59,14 +59,19 @@ You are an expert Software Engineer in the EXECUTION phase of implementing a Jir
59
59
  Your role in this phase is to implement the plan provided in the prompt:
60
60
  1. Follow the plan step-by-step to implement the solution
61
61
  2. Make the necessary code changes
62
- 3. Git add all relevant files that were changed or created
62
+ 3. Git add ONLY the files that are part of the implementation (listed in the plan)
63
63
 
64
64
  CRITICAL RULES FOR THIS PHASE:
65
65
  - Follow the plan's file list and implementation steps
66
66
  - Only modify/create files that are listed in the plan
67
67
  - Maintain existing code style and patterns
68
68
  - Add appropriate error handling and validation if needed
69
- - After making changes, use `git add` to stage all files that were modified or created
69
+ - Write code that conforms to the project's configured linters, formatters, and type checkers
70
+ - DO NOT write new tests - a separate agent handles test writing if needed
71
+ - After making changes, use `git add` to stage ONLY the files listed in the plan
72
+ - DO NOT git add any temporary or helper files you created for your own use (e.g., JSON files
73
+ describing violations, test scripts for debugging, analysis files, scratch files, etc.)
74
+ - If you create any temporary helper files, delete them before finishing
70
75
 
71
76
  You have full access to modify files, but stay within the scope of the plan.
72
77
  """
@@ -87,6 +92,52 @@ Plan:
87
92
  {plan_content}
88
93
  """
89
94
 
95
+ TEST_WRITER_PHASE_SYSTEM_PROMPT = """
96
+ You are an expert Software Engineer evaluating whether tests are needed for recent code changes.
97
+
98
+ CRITICAL: In MOST cases, new tests are NOT needed. Only add tests in these rare situations:
99
+ 1. New complex or risky logic that doesn't have existing test coverage
100
+ 2. Entirely new modules or components with no tests
101
+
102
+ DO NOT add tests for:
103
+ - Simple changes, bug fixes, or refactors
104
+ - Code that is already covered by existing tests
105
+ - Configuration changes
106
+ - Changes to existing well-tested code
107
+ - Minor feature additions to tested modules
108
+
109
+ Your role:
110
+ 1. Review the staged changes (git diff --cached)
111
+ 2. Check existing test coverage for the modified areas
112
+ 3. ONLY if one of the rare situations above applies, write minimal focused tests
113
+ 4. If you add tests, use `git add` to stage them
114
+
115
+ CRITICAL RULES:
116
+ - Default to NOT writing tests - most changes don't need them
117
+ - If existing tests cover the changes, do nothing
118
+ - If you write tests, keep them minimal and focused
119
+ - Follow existing test patterns in the codebase
120
+ - After writing tests, use `git add` to stage ONLY the test files you created
121
+ - DO NOT git add any temporary or helper files you created for your own use
122
+ - If you create any temporary helper files, delete them before finishing
123
+ """
124
+
125
+ TEST_WRITER_PHASE_PROMPT_TEMPLATE = """
126
+ Review the staged changes and determine if new tests are truly needed.
127
+
128
+ Issue Key: {issue_key}
129
+ Summary: {summary}
130
+
131
+ Remember: Most changes do NOT need new tests. Only add tests for new complex/risky logic
132
+ without existing coverage, or entirely new modules.
133
+
134
+ Steps:
135
+ 1. Run `git diff --cached` to see what was changed
136
+ 2. Check if existing tests already cover these changes
137
+ 3. Only if truly needed (rare), write minimal tests
138
+ 4. Run `git add` to stage ONLY the test files you created
139
+ """
140
+
90
141
 
91
142
  async def plan_ticket(
92
143
  issue: JiraIssue, workspace_path: Path | None = None, mcp_config_path: Path | None = None
@@ -160,20 +211,55 @@ async def execute_plan(
160
211
  print_agent_message(message)
161
212
 
162
213
 
214
+ async def write_tests_if_needed(
215
+ issue: JiraIssue,
216
+ session_id: str,
217
+ workspace_path: Path | None = None,
218
+ mcp_config_path: Path | None = None,
219
+ ) -> None:
220
+ """
221
+ Evaluate staged changes and add tests only if truly needed.
222
+
223
+ Tests are only added in rare cases:
224
+ - New complex/risky logic without existing test coverage
225
+ - Entirely new modules or components
226
+ """
227
+ issue_context = {
228
+ "issue_key": issue.key,
229
+ "summary": issue.summary,
230
+ }
231
+ test_writer_prompt = TEST_WRITER_PHASE_PROMPT_TEMPLATE.format(**issue_context)
232
+
233
+ async for message in run_agent_query(
234
+ prompt=test_writer_prompt,
235
+ system_prompt=TEST_WRITER_PHASE_SYSTEM_PROMPT,
236
+ allowed_tools=["Glob", "Bash", "Read", "Grep", "Write"],
237
+ cwd=workspace_path,
238
+ mcp_config_path=mcp_config_path,
239
+ session_id=session_id,
240
+ ):
241
+ print_agent_message(message)
242
+
243
+
163
244
  async def try_solve_ticket(
164
- issue: JiraIssue, workspace_path: Path | None = None, mcp_config_path: Path | None = None
245
+ issue: JiraIssue,
246
+ workspace_path: Path | None = None,
247
+ mcp_config_path: Path | None = None,
248
+ enable_test_writer: bool = False,
165
249
  ) -> str:
166
250
  """
167
251
  Solve a Jira ticket using a Plan-Act workflow with Claude Agent SDK.
168
252
 
169
- The workflow consists of two phases:
253
+ The workflow consists of phases:
170
254
  1. Planning Phase: Explore codebase and create PLAN.md with implementation details
171
- 2. Execution Phase: Implement the plan and run tests
255
+ 2. Execution Phase: Implement the plan
256
+ 3. Test Writing Phase (optional): Add tests only if truly needed (rare cases)
172
257
 
173
258
  Args:
174
259
  issue: The JiraIssue object containing all issue details
175
260
  workspace_path: Optional path to workspace root. Defaults to current directory.
176
261
  mcp_config_path: Optional path to mcp.json configuration file.
262
+ enable_test_writer: Whether to run the test writer phase. Defaults to False.
177
263
 
178
264
  Returns:
179
265
  The session_id from the conversation
@@ -183,4 +269,7 @@ async def try_solve_ticket(
183
269
  "Plan file created at - %s. Now running the executor agent to implement it.", str(plan_path)
184
270
  )
185
271
  await execute_plan(issue, session_id, plan_path, workspace_path, mcp_config_path)
272
+ if enable_test_writer:
273
+ logger.info("Evaluating if new tests are needed for the changes.")
274
+ await write_tests_if_needed(issue, session_id, workspace_path, mcp_config_path)
186
275
  return session_id
src/branch_creator.py CHANGED
@@ -4,7 +4,6 @@ from datetime import datetime
4
4
 
5
5
  from src.clients.github_client import GitHubClient
6
6
  from src.clients.jira_client import JiraClient, JiraIssue
7
- from src.exceptions import GithubBranchAlreadyExistsError
8
7
 
9
8
  logger = logging.getLogger(__name__)
10
9
 
@@ -32,10 +31,15 @@ def generate_branch_name(
32
31
  if issue_type:
33
32
  branch_name = f"{issue_type.lower()}/{branch_name}"
34
33
 
35
- if len(branch_name) > max_length:
36
- branch_name = branch_name[:max_length].rstrip("-")
34
+ # Add timestamp suffix to ensure uniqueness and avoid an extra
35
+ # API call to check if branch exists
36
+ timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
37
+ suggested_branch_name = f"{branch_name}-{timestamp}"
38
+ if len(suggested_branch_name) > max_length:
39
+ chars_count_to_remove = len(suggested_branch_name) - max_length
40
+ branch_name = branch_name[:-chars_count_to_remove]
37
41
 
38
- return branch_name
42
+ return f"{branch_name}-{timestamp}"
39
43
 
40
44
 
41
45
  def create_branch_from_jira_issue(
@@ -48,20 +52,7 @@ def create_branch_from_jira_issue(
48
52
  # TODO: Consider replacing the 2 next lines with local git client
49
53
  base_ref = github_client.get_base_branch_ref(base_branch)
50
54
 
51
- try:
52
- branch_url = github_client.create_branch(branch_name, base_ref)
53
- except GithubBranchAlreadyExistsError:
54
- # Branch already exists, add timestamp suffix and retry
55
- original_branch_name = branch_name
56
- timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
57
- branch_name = f"{branch_name}-{timestamp}"
58
- logger.info(
59
- "Branch '%s' already exists. Retrying with new name: '%s'",
60
- original_branch_name,
61
- branch_name,
62
- )
63
- branch_url = github_client.create_branch(branch_name, base_ref)
64
-
55
+ branch_url = github_client.create_branch(branch_name, base_ref)
65
56
  jira_client.link_branch(jira_issue.key, branch_url, branch_name)
66
57
 
67
58
  return branch_name
src/cli.py CHANGED
@@ -101,7 +101,9 @@ def _setup_workspace(
101
101
  if workspace_path is None:
102
102
  shared_temp_dir = Path(tempfile.gettempdir()) / "ticket2pr"
103
103
  shared_temp_dir.mkdir(exist_ok=True)
104
- temp_dir = Path(tempfile.mkdtemp(dir=shared_temp_dir))
104
+ temp_dir = Path(
105
+ tempfile.mkdtemp(dir=shared_temp_dir, prefix=f"{github_client.repo.name}_")
106
+ )
105
107
  logger.info(
106
108
  "No workspace path provided, cloning repository to temp directory: %s", temp_dir
107
109
  )
src/enhanced_git.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from pathlib import Path
2
- from typing import Self
3
2
 
4
3
  import git
4
+ from typing_extensions import Self
5
5
 
6
6
  from src.exceptions import (
7
7
  GitCloneError,
src/logging_setup.py CHANGED
@@ -2,10 +2,10 @@ import abc
2
2
  import logging
3
3
  from enum import Enum
4
4
  from pathlib import Path
5
- from typing import Self
6
5
 
7
6
  import colorlog
8
7
  from pydantic import BaseModel, Field, field_validator, model_validator
8
+ from typing_extensions import Self
9
9
 
10
10
  LOG_COLORS = {
11
11
  "DEBUG": "white",
@@ -43,7 +43,9 @@ class SetupLoggerParams(BaseModel):
43
43
  @field_validator("level")
44
44
  @classmethod
45
45
  def validate_log_level_string(cls, value: str) -> str:
46
- valid_levels = set(logging.getLevelNamesMapping())
46
+ # logging.logging.getLevelNamesMapping() is not being used here because
47
+ # it's new in Python 3.11
48
+ valid_levels = logging._nameToLevel
47
49
  if value.upper() not in valid_levels:
48
50
  msg = f"'level' must be one of: {valid_levels}. Got '{value}'."
49
51
  raise ValueError(msg)
src/workflow.py CHANGED
@@ -4,7 +4,7 @@ from pathlib import Path
4
4
  from pydantic import BaseModel
5
5
 
6
6
  from src.agents.pr_generator import generate_commit_and_pr_body
7
- from src.agents.pre_commit_fixer import verify_pre_commit_and_fix
7
+ from src.agents.pre_commit_fixer import try_fix_pre_commit as try_fix_pre_commit_agent
8
8
  from src.agents.ticket_solver import try_solve_ticket
9
9
  from src.branch_creator import create_branch_from_jira_issue
10
10
  from src.clients.github_client import GitHubClient
@@ -23,6 +23,48 @@ class WorkflowResult(BaseModel):
23
23
  jira_issue_permalink: str
24
24
 
25
25
 
26
+ async def try_fix_pre_commit(
27
+ git: EnhancedGit, mcp_config_path: Path | None = None, retries: int = 3
28
+ ) -> bool:
29
+ """
30
+ Try to run pre-commit and fix any failures with retries.
31
+
32
+ Returns:
33
+ True if pre-commit passes, False if it still fails after all retries.
34
+ """
35
+ result = run_pre_commit(git.repo_path)
36
+
37
+ if result.success:
38
+ logger.info("pre-commit passed on first run")
39
+ return True
40
+
41
+ for attempt in range(1, retries + 1):
42
+ logger.info(
43
+ "pre-commit failed (attempt %d/%d). Trying to fix it (workspace: %s)",
44
+ attempt,
45
+ retries,
46
+ git.repo_path,
47
+ )
48
+ await try_fix_pre_commit_agent(
49
+ git.repo_path,
50
+ pre_commit_output=result.output,
51
+ mcp_config_path=mcp_config_path,
52
+ )
53
+
54
+ result = run_pre_commit(git.repo_path)
55
+ if result.success:
56
+ logger.info("pre-commit passed after fix attempt %d", attempt)
57
+ return True
58
+
59
+ logger.warning("pre-commit still failing after fix attempt %d/%d", attempt, retries)
60
+
61
+ logger.warning(
62
+ "pre-commit verification failed after %d fix attempts. Will commit with --no-verify",
63
+ retries,
64
+ )
65
+ return False
66
+
67
+
26
68
  async def workflow(
27
69
  github_client: GitHubClient,
28
70
  jira_client: JiraClient,
@@ -50,20 +92,8 @@ async def workflow(
50
92
  if commit_no_verify:
51
93
  logger.info("Skipping pre-commit verification: --commit-no-verify flag is set")
52
94
  elif is_pre_commit_installed():
53
- logger.info("pre-commit is installed. Trying to run it")
54
- result = run_pre_commit(git.repo_path)
55
- if not result.success:
56
- logger.info("pre-commit failed. trying to fix it (workspace: %s)", git.repo_path)
57
- commit_no_verify = not await verify_pre_commit_and_fix(
58
- git.repo_path, mcp_config_path=mcp_config_path
59
- )
60
- if commit_no_verify:
61
- logger.warning(
62
- "pre-commit verification failed after fix attempts. "
63
- "Will commit with --no-verify"
64
- )
65
- else:
66
- logger.info("Skipping pre-commit fix: pre-commit is is already passing")
95
+ logger.info("pre-commit is installed. Trying to run it and fix any failures.")
96
+ await try_fix_pre_commit(git, mcp_config_path=mcp_config_path)
67
97
  else:
68
98
  logger.info("Skipping pre-commit verification: pre-commit is not installed")
69
99
  logger.info("Generating commit message and PR body for branch: %s", branch_name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ticket2pr
3
- Version: 0.3.4
3
+ Version: 0.3.6
4
4
  Summary: Automate Jira ticket to GitHub PR workflow
5
5
  Home-page: https://github.com/bengabay11/ticket2pr
6
6
  Author: Ben Gabay
@@ -19,6 +19,7 @@ Requires-Dist: python-dotenv>=1.1.0
19
19
  Requires-Dist: rich>=14.0.0
20
20
  Requires-Dist: tomli-w>=1.2.0
21
21
  Requires-Dist: typer>=0.21.1
22
+ Requires-Dist: typing_extensions>=4.0.0
22
23
  Dynamic: author
23
24
  Dynamic: author-email
24
25
  Dynamic: home-page
@@ -1,22 +1,22 @@
1
1
  src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- src/branch_creator.py,sha256=8KqlIjP-VDnB8_qd_1NjiyimAs6yn5xJdr0o9OMtzsw,2230
3
- src/cli.py,sha256=4fL7R4-hbTJlN5OzdkRRk9bFDERuJUgNKQWWeBUxjzM,8215
2
+ src/branch_creator.py,sha256=HViz7L7CxokrjKTQzt2wMuMeF5QZgq0V5Mpy6MkZa2g,1983
3
+ src/cli.py,sha256=UXo0cBXae3dJpgKN3ftjW8TLFMsfBqFd9pCJG9iPTaY,8283
4
4
  src/console_utils.py,sha256=TbVl_WhiGi1Kq7txk_WpCIfs7gvTJ3qPrSNVBOZ_ZiQ,6928
5
- src/enhanced_git.py,sha256=DONRfrYrYKXNyk1Yt9TfpvglGS3U4e1V2Q3FnvvUo38,5189
5
+ src/enhanced_git.py,sha256=WTgPK_kH2B57KSYpMtrAfkDzuGLT_zK8bCPmxRjS_Dw,5200
6
6
  src/exceptions.py,sha256=HVtaiVoX6Hw9NOW3z9k2tfirHZTBOeQzMp52mBw2S6Y,4704
7
- src/logging_setup.py,sha256=k6CILizhJdh9WecRluL_lYPe005GVAXOHXt58xZsD1s,4046
7
+ src/logging_setup.py,sha256=0lBahne5Vf8oe8NYW_0BUiTe6XaVUYwvpvGbYFOTpiY,4156
8
8
  src/main.py,sha256=tsAVc2lIoiXBJqhNOV3ZOnv9qcaArLF_EJiYibPGBXg,121
9
9
  src/pr_content.py,sha256=ValoIl20sNvh4QZS4-Lm0r3SzfzMMrXyq3S7FW_cFuw,407
10
10
  src/settings.py,sha256=lkuBarOVaCUTijAq9niE8KOEhk_4FXPpOvn_RBBPrU4,3741
11
11
  src/settings_init.py,sha256=MrcyWMF9HttSArzbUDSlSIbkeSVvhvRA38C_7ROYHX8,5781
12
12
  src/validators.py,sha256=3AWj99f2PsR7O51zd2uMuYj9fyKfsT3K8kB1iVCjEm8,1972
13
- src/workflow.py,sha256=23dLaI3UNNdWkpD6ENuFS0FysipbXLQBldtiael3Akg,3998
13
+ src/workflow.py,sha256=cf56sGAjnqBrkSMw5DI1KMfhiRAGuek3gpzKp0Kbe7g,4733
14
14
  src/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  src/agents/base.py,sha256=pr0E2i0rdynJTTwiiOZ8WbDjK2wUa7yo8XkVGI7NWTM,6284
16
16
  src/agents/commit_message.py,sha256=D9AGDPzJjtnAdQb5fp67HcParesqL_pXu-fSYdTanBw,2555
17
17
  src/agents/pr_generator.py,sha256=keIFAQCGcM8lObpX7G1oUSjh9pV7eOkkGvpKUh7K9XE,4340
18
- src/agents/pre_commit_fixer.py,sha256=J8aqTZ40mJffANxoBu2T0-ch6t7IHe25nmr4jsgM6F0,3513
19
- src/agents/ticket_solver.py,sha256=9lPbYw_cQZkCnjlFPDmSdbrDDxRPQVLgi8qt8pO9ZiU,6320
18
+ src/agents/pre_commit_fixer.py,sha256=LVaPe7WByGVTo10cQ8P1LOjawgz3j7wAc9rg9BDZ6_Q,3231
19
+ src/agents/ticket_solver.py,sha256=le5yRFxy9u7UTelN6agVo4WhB3wafn5Iqspi5t10xbg,9866
20
20
  src/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  src/clients/github_client.py,sha256=6WwbVxLGtn97WRix7CdORiW_k7F1guJXsKmqXdReb9M,4234
22
22
  src/clients/jira_client.py,sha256=wdDRqiUSTOdBucrqIFkUkJlM7fDMk4DMfUiWCAG-c9U,2323
@@ -28,9 +28,9 @@ tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
28
28
  tests/integration/test_find_first_toml.py,sha256=Wq4rDReqcWLC0CsgcDBDX62wtMljcsm8UHUDTLr4-_A,902
29
29
  tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
30
  tests/unit/test_nothing.py,sha256=qRI0MSdLiBRklBNEsOAkr4jxfcrO2v2CuB2hHWePonU,103
31
- ticket2pr-0.3.4.dist-info/licenses/LICENSE,sha256=omgsokA67LJXOOKpXtf1wNH71Bfs35NWEAuLowNUMyM,1066
32
- ticket2pr-0.3.4.dist-info/METADATA,sha256=xDthvsrpPz4U0RbM9QcwzIELfnH_O5pcV9dgybqLLIY,3264
33
- ticket2pr-0.3.4.dist-info/WHEEL,sha256=Mk1ST5gDzEO5il5kYREiBnzzM469m5sI8ESPl7TRhJY,110
34
- ticket2pr-0.3.4.dist-info/entry_points.txt,sha256=DnWUjexpwtqVcRSICrpnveMIjGJA9_0K5IjZt10jVkM,47
35
- ticket2pr-0.3.4.dist-info/top_level.txt,sha256=KW3xgkz9NLMTcmmzgKvW8RFpCFkRIQ085qzq2diFf68,10
36
- ticket2pr-0.3.4.dist-info/RECORD,,
31
+ ticket2pr-0.3.6.dist-info/licenses/LICENSE,sha256=omgsokA67LJXOOKpXtf1wNH71Bfs35NWEAuLowNUMyM,1066
32
+ ticket2pr-0.3.6.dist-info/METADATA,sha256=GNRSmAb2pxhMT0Yy4w3aSufB6i3GYKZyDoIkAsHkoF0,3304
33
+ ticket2pr-0.3.6.dist-info/WHEEL,sha256=Mk1ST5gDzEO5il5kYREiBnzzM469m5sI8ESPl7TRhJY,110
34
+ ticket2pr-0.3.6.dist-info/entry_points.txt,sha256=DnWUjexpwtqVcRSICrpnveMIjGJA9_0K5IjZt10jVkM,47
35
+ ticket2pr-0.3.6.dist-info/top_level.txt,sha256=KW3xgkz9NLMTcmmzgKvW8RFpCFkRIQ085qzq2diFf68,10
36
+ ticket2pr-0.3.6.dist-info/RECORD,,