devDocs 1.0.3__tar.gz → 2.0.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devDocs
3
- Version: 1.0.3
3
+ Version: 2.0.3
4
4
  Summary: AI-powered CLI tool that builds professional '*.md' documentation files of a project for internal teams using the Google Gemini API.
5
5
  Author: Gantavya Bansal
6
6
  Author-email: Gantavya Bansal <gantavyaoo@gmail.com>
@@ -0,0 +1,119 @@
1
+ k='docs'
2
+ Y='utf-8'
3
+ X='README'
4
+ W=any
5
+ V=open
6
+ Q='.md'
7
+ N='.'
8
+ G=str
9
+ F=print
10
+ B=''
11
+ A=Exception
12
+ from logging import basicConfig as l,info as H,WARNING as Z,INFO,getLogger as a,exception as E
13
+ from os import listdir as m,getcwd as J,chdir as R,scandir as n,curdir as o,makedirs as S
14
+ from os.path import isdir as O,join as C,splitext as p,exists as b,getsize as q,dirname as c,abspath as d
15
+ from google.genai import Client as r
16
+ from google.genai.types import GenerateContentConfig as D
17
+ from argparse import ArgumentParser as s
18
+ from time import sleep
19
+ l(level=INFO)
20
+ a('google_genai').setLevel(Z)
21
+ a('httpx').setLevel(Z)
22
+ P='\nYou are Gantavya Bansal, a senior software engineer and expert technical writer. Your task is to generate clean, professional, and well-structured `README.md` documentation in Markdown format. Use the provided filename, source code, and any existing README or folder structure as context.\n\nYour output must be:\n\n- Concise and easy to follow\n- Focused on technical clarity and usability\n- Markdown-only (no extra commentary, no code fences)\n\nYour output must include:\n\n1. **Project Title** – Inferred from the filename or main script\n2. **Folder Structure** – Tree view if available, with clickable index links\n3. **Description** – What the project does and its purpose\n4. **How to Use** – Installation steps, CLI/API usage examples\n5. **Technologies Used** – Languages, tools, libraries\n6. **Architecture or Code Overview** – Key components, flow, functions, or classes\n7. **Known Issues / Improvements** – Current limitations, TODOs\n8. **Additional Notes or References** – Licensing, credits, related tools\n\nOnly return the final `README.md` content. Do not include any explanations, prefixes, or suffixes.\n\n '
23
+ def t(file,code,readme):
24
+ J='```';I='```markdown';G=readme;F=code;C=file
25
+ try:B=M.models.generate_content(model='gemini-2.0-flash-lite',config=D(system_instruction=P),contents=[f"Filename: {C}",f"Code:\n{F}",f"Existing README (if any):\n{G}"]);return B.text.removeprefix(I).removesuffix(J).strip()
26
+ except A as H:
27
+ try:B=M.models.generate_content(model='gemini-2.0-flash',config=D(system_instruction=P),contents=[f"Filename: {C}",f"Code:\n{F}",f"Existing README (if any):\n{G}"]);return B.text.removeprefix(I).removesuffix(J).strip()
28
+ except A as H:
29
+ try:B=M.models.generate_content(model='gemini-2.5-flash-lite',config=D(system_instruction=P),contents=[f"Filename: {C}",f"Code:\n{F}",f"Existing README (if any):\n{G}"]);return B.text.removeprefix(I).removesuffix(J).strip()
30
+ except A as H:
31
+ try:B=M.models.generate_content(model='gemini-2.5-flash',config=D(system_instruction=P),contents=[f"Filename: {C}",f"Code:\n{F}",f"Existing README (if any):\n{G}"]);return B.text.removeprefix(I).removesuffix(J).strip()
32
+ except A as H:E(f"Error generating README for {C}: {H}");return f"# {C}\n\n⚠️ Failed to generate documentation GEMINI SERVER ERROR."
33
+ def e(start_path=N,prefix=B):
34
+ L=prefix;D=start_path
35
+ try:
36
+ I=B;J=[];F=[]
37
+ if not O(D):
38
+ if O(c(d(D))):D=c(d(D))
39
+ else:return B
40
+ with n(D)as G:
41
+ for H in G:
42
+ if h(H.name):
43
+ if H.is_dir():F.append(H.name)
44
+ else:J.append(H.name)
45
+ F.sort();J.sort();G=F+J
46
+ for(N,K)in enumerate(G):
47
+ P=C(D,K);M=N==len(G)-1;Q='└── 'if M else'├── ';I+=L+Q+K+'\n'
48
+ if K in F:R=' 'if M else'│ ';I+=e(P,L+R)
49
+ return I
50
+ except A as S:E(f"Error generating Tree for {D} dir: {S}");return f"# {D}\n\n⚠️ Failed to generate documentation tree."
51
+ def u(base,folders,files):
52
+ I=files;G=folders;D=base
53
+ try:
54
+ F=K(D);F+=f"\n {e(start_path=D)} \n"
55
+ if G:
56
+ for L in G:O=C(J(),L);F+=f"\n readme for folder:{L} \n content inside: \n {K(O)} \n"
57
+ if I:
58
+ for M in I:F+=f"\n readme for file:{M} \n content inside: {K(M)} \n"
59
+ f(X if D==N else D,F,K(X if D==N else D));H(B)
60
+ except A as P:E(f"Error generating README for {D}: {P}")
61
+ def K(file):
62
+ C=file
63
+ try:
64
+ if b(C+Q):
65
+ with V(C+Q,'r',encoding=Y)as D:return D.read()
66
+ else:return B
67
+ except A as F:E(f"Error reading README for {C}: {F}");return f"# {C}\n\n⚠️ Failed to read {C}.md"
68
+ def v(file):
69
+ B=file
70
+ try:
71
+ with V(B,'r',encoding=Y)as C:return C.read()
72
+ except A as D:E(f"Error reading code in {B}: {D}");return f"# {B}\n\n⚠️ Failed to read {B}"
73
+ def f(file,code,readme):
74
+ N='README.md';G=readme;D=file
75
+ try:
76
+ O=J().replace(U,B).lstrip('\\/').replace('\\','/');K=C(U,I,O);S(K,exist_ok=True);L=p(D)[0]+Q
77
+ if X in L.upper():
78
+ if not j:H('skipping overwriting README');M=C(K,N)
79
+ else:M=C(N)
80
+ else:M=C(K,L)
81
+ G=i+G
82
+ with V(M,'w',encoding=Y)as P:P.write(t(D,code,G))
83
+ F(f"Written to: {L}")
84
+ except A as R:E(f"Error writing README for {D}: {R}")
85
+ L=['cache','node','module','pkg','package','@','$','#','&','util','hook','component','python','compile','dist','build','env',k,'lib','bin','obj','out','__pycache__','.next','.turbo','.expo','.idea','.vscode','coverage','test','tests','fixtures','migrations','assets','static','logs','debug','config','style']
86
+ w=[N,'-','_','~']
87
+ T=['.log','.png','.jpg','.jpeg','.svg','.ico','.gif','.webp','.pyc','.class','.zip','.min.js','.mp4','.mp3','.wav','.pdf','.docx','.xlsx','.db','.sqlite','.bak','.7z','.rar','.tar.gz','.exe','.dll','.so','.ttf','.woff','.eot','.swp','.map','.webm',Q,'.css']
88
+ def g(base):
89
+ I=base
90
+ try:
91
+ R(I);F(f"Reading Folder: {I}");N=[A for A in m()if h(A)];L=[A for A in N if O(C(J(),A))]
92
+ if L:
93
+ F('Folders found:')
94
+ for D in L:H(D)
95
+ for D in L:H(B);F(f"Opening Folder: {D}");g(D);F(f"Closing Folder: {D}");H(B)
96
+ M=[A for A in N if not O(C(J(),A))and q(A)<1000000]
97
+ if M:
98
+ F('Files found:')
99
+ for G in M:H(G)
100
+ for G in M:P=v(G);Q=K(G);f(G,P,Q)
101
+ u(I,L,M);R('..')
102
+ except A as S:E(f"Failed to read {I} folder.")
103
+ def x(include,exclude):
104
+ D=exclude;C=include
105
+ try:
106
+ C=[A.strip()for A in C.split(',')if A.strip()];D=[A.strip()for A in D.split(',')if A.strip()]
107
+ for F in C:L.append(F.strip())
108
+ for B in D:
109
+ if B in L:L.remove(B.strip())
110
+ if B in T:T.remove(B.strip())
111
+ except A as G:E('Error in use with args --include || --exclude')
112
+ def h(entry):A=entry.lower();return not W(A.startswith(B)for B in w)and not W(A.endswith(B)for B in T)and not W(B in A for B in L)
113
+ def y():
114
+ try:
115
+ C=s(description='Auto-generate documentation from source code and folder structure.');C.add_argument('-p','--path',type=G,default=N,help='Root path to scan (default: current directory)');C.add_argument('--name',type=G,default='My Project',help='Project name to include in README');C.add_argument('--description',type=G,default='No description provided.',help='Short description of the project');C.add_argument('--authors',type=G,default='Anonymous',help='Comma-separated list of author names');C.add_argument('--keywords',type=G,default=B,help='Comma-separated keywords (e.g., cli, docs, auto)');C.add_argument('--overwrite',action='store_true',help='Overwrite existing README files (default: False)');C.add_argument('--output',type=G,default=k,help='Output dir where docs to be stored (default: docs)');C.add_argument('--exclude',type=G,default=B,help='Folders, files, extensionse to exclude ((e.g., docs, ext, setting, config)');C.add_argument('--include',type=G,default=B,help='Folders, files, extensionse to include ((e.g., docs, ext, setting, config)');global M;global U;global I;global i;global j;D=C.parse_args();U=J();j=D.overwrite;I=D.output;x(include=D.include,exclude=D.exclude)
116
+ if not b(I):S(I)
117
+ L.append(I);i=f"name: {D.name}\ndescription: {D.description}\nauthors: {D.authors}\nkeywords: {D.keywords}";M=r(api_key=input('Paste your Google Gemini API Key here:').strip());F(f"📁 Starting in: {D.path}");S(I,exist_ok=True);R(D.path);g(o);F('✅ Documentation generated successfully.')
118
+ except A as H:E('Error during execution. Try using --help.')
119
+ if __name__=='__main__':y()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devDocs
3
- Version: 1.0.3
3
+ Version: 2.0.3
4
4
  Summary: AI-powered CLI tool that builds professional '*.md' documentation files of a project for internal teams using the Google Gemini API.
5
5
  Author: Gantavya Bansal
6
6
  Author-email: Gantavya Bansal <gantavyaoo@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "devDocs"
7
- version = "1.0.3"
7
+ version = "2.0.3"
8
8
  description = "AI-powered CLI tool that builds professional '*.md' documentation files of a project for internal teams using the Google Gemini API."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -1,2 +1,2 @@
1
1
  from setuptools import setup,find_packages as A
2
- setup(name='devDocs',version='1.0.3',packages=A(),install_requires=['google-generativeai'],entry_points={'console_scripts':['devDocs=devDocs.cli:x']},author='Gantavya Bansal',description="Auto-generate Project's markdown documentation using Gemini AI for Internal teams.",long_description=open('README.md',encoding='utf-8').read(),long_description_content_type='text/markdown',license='MIT',python_requires='>=3.8',classifiers=['Programming Language :: Python :: 3','License :: OSI Approved :: MIT License'])
2
+ setup(name='devDocs',version='2.0.3',packages=A(),install_requires=['google-generativeai'],entry_points={'console_scripts':['devDocs=devDocs.cli:x']},author='Gantavya Bansal',description="Auto-generate Project's markdown documentation using Gemini AI for Internal teams.",long_description=open('README.md',encoding='utf-8').read(),long_description_content_type='text/markdown',license='MIT',python_requires='>=3.8',classifiers=['Programming Language :: Python :: 3','License :: OSI Approved :: MIT License'])
@@ -1,112 +0,0 @@
1
- i='docs'
2
- V='utf-8'
3
- U='README'
4
- T=any
5
- S=open
6
- C='.md'
7
- M='.'
8
- G=str
9
- F=print
10
- E=Exception
11
- A=''
12
- from logging import basicConfig as j,info as H,WARNING as W,INFO,getLogger as X,exception as D
13
- from os import listdir as k,getcwd as J,chdir as O,scandir as l,curdir as m,makedirs as P
14
- from os.path import isdir as N,join as B,splitext as n,exists as Y,getsize as o,dirname as Z,abspath as a
15
- from google.genai import Client as p
16
- from google.genai.types import GenerateContentConfig as q
17
- from argparse import ArgumentParser as r
18
- from time import sleep
19
- j(level=INFO)
20
- X('google_genai').setLevel(W)
21
- X('httpx').setLevel(W)
22
- def s(file,code,readme):
23
- A=file
24
- try:sleep(1);B=f.models.generate_content(model='gemini-2.0-flash-lite',config=q(system_instruction='\nYou are Gantavya Bansal, a senior software engineer and expert technical writer. Your task is to generate clean, professional, and well-structured `README.md` documentation in Markdown format. Use the provided filename, source code, and any existing README or folder structure as context.\n\nYour output must be:\n\n- Concise and easy to follow\n- Focused on technical clarity and usability\n- Markdown-only (no extra commentary, no code fences)\n\nYour output must include:\n\n1. **Project Title** – Inferred from the filename or main script\n2. **Folder Structure** – Tree view if available, with clickable index links\n3. **Description** – What the project does and its purpose\n4. **How to Use** – Installation steps, CLI/API usage examples\n5. **Technologies Used** – Languages, tools, libraries\n6. **Architecture or Code Overview** – Key components, flow, functions, or classes\n7. **Known Issues / Improvements** – Current limitations, TODOs\n8. **Additional Notes or References** – Licensing, credits, related tools\n\nOnly return the final `README.md` content. Do not include any explanations, prefixes, or suffixes.\n\n '),contents=[f"Filename: {A}",f"Code:\n{code}",f"Existing README (if any):\n{readme}"]);return B.text.removeprefix('```markdown').removesuffix('```').strip()
25
- except E as C:D(f"Error generating README for {A}: {C}");return f"# {A}\n\n⚠️ Failed to generate documentation GEMINI SERVER ERROR."
26
- def b(start_path=M,prefix=A):
27
- L=prefix;C=start_path
28
- try:
29
- I=A;J=[];F=[]
30
- if not N(C):
31
- if N(Z(a(C))):C=Z(a(C))
32
- else:return A
33
- with l(C)as G:
34
- for H in G:
35
- if e(H.name):
36
- if H.is_dir():F.append(H.name)
37
- else:J.append(H.name)
38
- F.sort();J.sort();G=F+J
39
- for(O,K)in enumerate(G):
40
- P=B(C,K);M=O==len(G)-1;Q='└── 'if M else'├── ';I+=L+Q+K+'\n'
41
- if K in F:R=' 'if M else'│ ';I+=b(P,L+R)
42
- return I
43
- except E as S:D(f"Error generating Tree for {C} dir: {S}");return f"# {C}\n\n⚠️ Failed to generate documentation tree."
44
- def t(base,folders,files):
45
- I=files;G=folders;C=base
46
- try:
47
- F=K(C);F+=f"\n {b(start_path=C)} \n"
48
- if G:
49
- for L in G:O=B(J(),L);F+=f"\n readme for folder:{L} \n content inside: \n {K(O)} \n"
50
- if I:
51
- for N in I:F+=f"\n readme for file:{N} \n content inside: {K(N)} \n"
52
- c(U if C==M else C,F,K(U if C==M else C));H(A)
53
- except E as P:D(f"Error generating README for {C}: {P}")
54
- def K(file):
55
- B=file
56
- try:
57
- if Y(B+C):
58
- with S(B+C,'r',encoding=V)as F:return F.read()
59
- else:return A
60
- except E as G:D(f"Error reading README for {B}: {G}");return f"# {B}\n\n⚠️ Failed to read {B}.md"
61
- def u(file):
62
- A=file
63
- try:
64
- with S(A,'r',encoding=V)as B:return B.read()
65
- except E as C:D(f"Error reading code in {A}: {C}");return f"# {A}\n\n⚠️ Failed to read {A}"
66
- def c(file,code,readme):
67
- O='README.md';K=readme;G=file
68
- try:
69
- Q=J().replace(R,A).lstrip('\\/').replace('\\','/');L=B(R,I,Q);P(L,exist_ok=True);M=n(G)[0]+C
70
- if U in M.upper():
71
- if not h:H('skipping overwriting README');N=B(L,O)
72
- else:N=B(O)
73
- else:N=B(L,M)
74
- K=g+K
75
- with S(N,'w',encoding=V)as T:T.write(s(G,code,K))
76
- F(f"Written to: {M}")
77
- except E as W:D(f"Error writing README for {G}: {W}")
78
- L=['cache','node','module','pkg','package','@','$','#','&','util','hook','component','python','compile','dist','build','env',i,'lib','bin','obj','out','__pycache__','.next','.turbo','.expo','.idea','.vscode','coverage','test','tests','fixtures','migrations','assets','static','logs','debug','config','style']
79
- v=[M,'-','_','~']
80
- Q=['.log','.png','.jpg','.jpeg','.svg','.ico','.gif','.webp','.pyc','.class','.zip','.min.js','.mp4','.mp3','.wav','.pdf','.docx','.xlsx','.db','.sqlite','.bak','.7z','.rar','.tar.gz','.exe','.dll','.so','.ttf','.woff','.eot','.swp','.map','.webm',C,'.css']
81
- def d(base):
82
- I=base
83
- try:
84
- O(I);F(f"Reading Folder: {I}");P=[A for A in k()if e(A)];L=[A for A in P if N(B(J(),A))]
85
- if L:
86
- F('Folders found:')
87
- for C in L:H(C)
88
- for C in L:H(A);F(f"Opening Folder: {C}");d(C);F(f"Closing Folder: {C}");H(A)
89
- M=[A for A in P if not N(B(J(),A))and o(A)<1000000]
90
- if M:
91
- F('Files found:')
92
- for G in M:H(G)
93
- for G in M:Q=u(G);R=K(G);c(G,Q,R)
94
- t(I,L,M);O('..')
95
- except E as S:D(f"Failed to read {I} folder.")
96
- def w(include,exclude):
97
- C=exclude;B=include
98
- try:
99
- B=[A.strip()for A in B.split(',')if A.strip()];C=[A.strip()for A in C.split(',')if A.strip()]
100
- for F in B:L.append(F.strip())
101
- for A in C:
102
- if A in L:L.remove(A.strip())
103
- if A in Q:Q.remove(A.strip())
104
- except E as G:D('Error in use with args --include || --exclude')
105
- def e(entry):A=entry.lower();return not T(A.startswith(B)for B in v)and not T(A.endswith(B)for B in Q)and not T(B in A for B in L)
106
- def x():
107
- try:
108
- B=r(description='Auto-generate documentation from source code and folder structure.');B.add_argument('-p','--path',type=G,default=M,help='Root path to scan (default: current directory)');B.add_argument('--name',type=G,default='My Project',help='Project name to include in README');B.add_argument('--description',type=G,default='No description provided.',help='Short description of the project');B.add_argument('--authors',type=G,default='Anonymous',help='Comma-separated list of author names');B.add_argument('--keywords',type=G,default=A,help='Comma-separated keywords (e.g., cli, docs, auto)');B.add_argument('--overwrite',action='store_true',help='Overwrite existing README files (default: False)');B.add_argument('--output',type=G,default=i,help='Output dir where docs to be stored (default: docs)');B.add_argument('--exclude',type=G,default=A,help='Folders, files, extensionse to exclude ((e.g., docs, ext, setting, config)');B.add_argument('--include',type=G,default=A,help='Folders, files, extensionse to include ((e.g., docs, ext, setting, config)');global f;global R;global I;global g;global h;C=B.parse_args();R=J();h=C.overwrite;I=C.output;w(include=C.include,exclude=C.exclude)
109
- if not Y(I):P(I)
110
- L.append(I);g=f"name: {C.name}\ndescription: {C.description}\nauthors: {C.authors}\nkeywords: {C.keywords}";f=p(api_key=input('Paste your Google Gemini API Key here:').strip());F(f"📁 Starting in: {C.path}");P(I,exist_ok=True);O(C.path);d(m);F('✅ Documentation generated successfully.')
111
- except E as H:D('Error during execution. Try using --help.')
112
- if __name__=='__main__':x()
File without changes
File without changes
File without changes